1 #if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS) 2 3 #include "SkWindow.h" 4 #include "SkCanvas.h" 5 #include "SkOSMenu.h" 6 #include "SkTime.h" 7 8 #include "SkGraphics.h" 9 #include <new.h> 10 11 static void (*gPrevNewHandler)(); 12 13 extern "C" { 14 static void sk_new_handler() 15 { 16 if (SkGraphics::SetFontCacheUsed(0)) 17 return; 18 if (gPrevNewHandler) 19 gPrevNewHandler(); 20 else 21 sk_throw(); 22 } 23 } 24 25 static SkOSWindow* gCurrOSWin; 26 static EventTargetRef gEventTarget; 27 static EventQueueRef gCurrEventQ; 28 29 #define SK_MacEventClass FOUR_CHAR_CODE('SKec') 30 #define SK_MacEventKind FOUR_CHAR_CODE('SKek') 31 #define SK_MacEventParamName FOUR_CHAR_CODE('SKev') 32 #define SK_MacEventSinkIDParamName FOUR_CHAR_CODE('SKes') 33 34 SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) 35 { 36 static const EventTypeSpec gTypes[] = { 37 { kEventClassKeyboard, kEventRawKeyDown }, 38 { kEventClassKeyboard, kEventRawKeyUp }, 39 { kEventClassMouse, kEventMouseDown }, 40 { kEventClassMouse, kEventMouseDragged }, 41 { kEventClassMouse, kEventMouseUp }, 42 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, 43 { kEventClassWindow, kEventWindowBoundsChanged }, 44 { kEventClassWindow, kEventWindowDrawContent }, 45 { SK_MacEventClass, SK_MacEventKind } 46 }; 47 48 EventHandlerUPP handlerUPP = NewEventHandlerUPP(SkOSWindow::EventHandler); 49 int count = SK_ARRAY_COUNT(gTypes); 50 OSStatus result; 51 52 result = InstallEventHandler(GetWindowEventTarget((WindowRef)hWnd), handlerUPP, 53 count, gTypes, this, nil); 54 SkASSERT(result == noErr); 55 56 gCurrOSWin = this; 57 gCurrEventQ = GetCurrentEventQueue(); 58 gEventTarget = GetWindowEventTarget((WindowRef)hWnd); 59 60 static bool gOnce = true; 61 if (gOnce) { 62 gOnce = false; 63 gPrevNewHandler = set_new_handler(sk_new_handler); 64 } 65 } 66 67 void SkOSWindow::doPaint(void* ctx) 68 { 69 this->update(NULL); 70 71 this->getBitmap().drawToPort((WindowRef)fHWND, (CGContextRef)ctx); 72 } 73 74 void SkOSWindow::updateSize() 75 { 76 Rect r; 77 78 GetWindowBounds((WindowRef)fHWND, kWindowContentRgn, &r); 79 this->resize(r.right - r.left, r.bottom - r.top); 80 } 81 82 void SkOSWindow::onHandleInval(const SkIRect& r) 83 { 84 Rect rect; 85 86 rect.left = r.fLeft; 87 rect.top = r.fTop; 88 rect.right = r.fRight; 89 rect.bottom = r.fBottom; 90 InvalWindowRect((WindowRef)fHWND, &rect); 91 } 92 93 void SkOSWindow::onSetTitle(const char title[]) 94 { 95 CFStringRef str = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); 96 SetWindowTitleWithCFString((WindowRef)fHWND, str); 97 CFRelease(str); 98 } 99 100 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu) 101 { 102 } 103 104 static void getparam(EventRef inEvent, OSType name, OSType type, UInt32 size, void* data) 105 { 106 EventParamType actualType; 107 UInt32 actualSize; 108 OSStatus status; 109 110 status = GetEventParameter(inEvent, name, type, &actualType, size, &actualSize, data); 111 SkASSERT(status == noErr); 112 SkASSERT(actualType == type); 113 SkASSERT(actualSize == size); 114 } 115 116 enum { 117 SK_MacReturnKey = 36, 118 SK_MacDeleteKey = 51, 119 SK_MacEndKey = 119, 120 SK_MacLeftKey = 123, 121 SK_MacRightKey = 124, 122 SK_MacDownKey = 125, 123 SK_MacUpKey = 126, 124 125 SK_Mac0Key = 0x52, 126 SK_Mac1Key = 0x53, 127 SK_Mac2Key = 0x54, 128 SK_Mac3Key = 0x55, 129 SK_Mac4Key = 0x56, 130 SK_Mac5Key = 0x57, 131 SK_Mac6Key = 0x58, 132 SK_Mac7Key = 0x59, 133 SK_Mac8Key = 0x5b, 134 SK_Mac9Key = 0x5c 135 }; 136 137 static SkKey raw2key(UInt32 raw) 138 { 139 static const struct { 140 UInt32 fRaw; 141 SkKey fKey; 142 } gKeys[] = { 143 { SK_MacUpKey, kUp_SkKey }, 144 { SK_MacDownKey, kDown_SkKey }, 145 { SK_MacLeftKey, kLeft_SkKey }, 146 { SK_MacRightKey, kRight_SkKey }, 147 { SK_MacReturnKey, kOK_SkKey }, 148 { SK_MacDeleteKey, kBack_SkKey }, 149 { SK_MacEndKey, kEnd_SkKey }, 150 { SK_Mac0Key, k0_SkKey }, 151 { SK_Mac1Key, k1_SkKey }, 152 { SK_Mac2Key, k2_SkKey }, 153 { SK_Mac3Key, k3_SkKey }, 154 { SK_Mac4Key, k4_SkKey }, 155 { SK_Mac5Key, k5_SkKey }, 156 { SK_Mac6Key, k6_SkKey }, 157 { SK_Mac7Key, k7_SkKey }, 158 { SK_Mac8Key, k8_SkKey }, 159 { SK_Mac9Key, k9_SkKey } 160 }; 161 162 for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++) 163 if (gKeys[i].fRaw == raw) 164 return gKeys[i].fKey; 165 return kNONE_SkKey; 166 } 167 168 static void post_skmacevent() 169 { 170 EventRef ref; 171 OSStatus status = CreateEvent(nil, SK_MacEventClass, SK_MacEventKind, 0, 0, &ref); 172 SkASSERT(status == noErr); 173 174 #if 0 175 status = SetEventParameter(ref, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt); 176 SkASSERT(status == noErr); 177 status = SetEventParameter(ref, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID); 178 SkASSERT(status == noErr); 179 #endif 180 181 EventTargetRef target = gEventTarget; 182 SetEventParameter(ref, kEventParamPostTarget, typeEventTargetRef, sizeof(target), &target); 183 SkASSERT(status == noErr); 184 185 status = PostEventToQueue(gCurrEventQ, ref, kEventPriorityStandard); 186 SkASSERT(status == noErr); 187 188 ReleaseEvent(ref); 189 } 190 191 pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData ) 192 { 193 SkOSWindow* win = (SkOSWindow*)userData; 194 OSStatus result = eventNotHandledErr; 195 UInt32 wClass = GetEventClass(inEvent); 196 UInt32 wKind = GetEventKind(inEvent); 197 198 gCurrOSWin = win; // will need to be in TLS. Set this so PostEvent will work 199 200 switch (wClass) { 201 case kEventClassMouse: { 202 Point pt; 203 getparam(inEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pt), &pt); 204 SetPortWindowPort((WindowRef)win->getHWND()); 205 GlobalToLocal(&pt); 206 207 switch (wKind) { 208 case kEventMouseDown: 209 (void)win->handleClick(pt.h, pt.v, Click::kDown_State); 210 break; 211 case kEventMouseDragged: 212 (void)win->handleClick(pt.h, pt.v, Click::kMoved_State); 213 break; 214 case kEventMouseUp: 215 (void)win->handleClick(pt.h, pt.v, Click::kUp_State); 216 break; 217 default: 218 break; 219 } 220 break; 221 } 222 case kEventClassKeyboard: 223 if (wKind == kEventRawKeyDown) { 224 UInt32 raw; 225 getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw); 226 SkKey key = raw2key(raw); 227 if (key != kNONE_SkKey) 228 (void)win->handleKey(key); 229 } else if (wKind == kEventRawKeyUp) { 230 UInt32 raw; 231 getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw); 232 SkKey key = raw2key(raw); 233 if (key != kNONE_SkKey) 234 (void)win->handleKeyUp(key); 235 } 236 break; 237 case kEventClassTextInput: 238 if (wKind == kEventTextInputUnicodeForKeyEvent) { 239 UInt16 uni; 240 getparam(inEvent, kEventParamTextInputSendText, typeUnicodeText, sizeof(uni), &uni); 241 win->handleChar(uni); 242 } 243 break; 244 case kEventClassWindow: 245 switch (wKind) { 246 case kEventWindowBoundsChanged: 247 win->updateSize(); 248 break; 249 case kEventWindowDrawContent: { 250 CGContextRef cg; 251 result = GetEventParameter(inEvent, 252 kEventParamCGContextRef, 253 typeCGContextRef, 254 NULL, 255 sizeof (CGContextRef), 256 NULL, 257 &cg); 258 if (result != 0) { 259 cg = NULL; 260 } 261 win->doPaint(cg); 262 break; 263 } 264 default: 265 break; 266 } 267 break; 268 case SK_MacEventClass: { 269 SkASSERT(wKind == SK_MacEventKind); 270 if (SkEvent::ProcessEvent()) { 271 post_skmacevent(); 272 } 273 #if 0 274 SkEvent* evt; 275 SkEventSinkID sinkID; 276 getparam(inEvent, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt); 277 getparam(inEvent, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID); 278 #endif 279 result = noErr; 280 break; 281 } 282 default: 283 break; 284 } 285 if (result == eventNotHandledErr) { 286 result = CallNextEventHandler(inHandler, inEvent); 287 } 288 return result; 289 } 290 291 /////////////////////////////////////////////////////////////////////////////////////// 292 293 void SkEvent::SignalNonEmptyQueue() 294 { 295 post_skmacevent(); 296 // SkDebugf("signal nonempty\n"); 297 } 298 299 static TMTask gTMTaskRec; 300 static TMTask* gTMTaskPtr; 301 302 static void sk_timer_proc(TMTask* rec) 303 { 304 SkEvent::ServiceQueueTimer(); 305 // SkDebugf("timer task fired\n"); 306 } 307 308 void SkEvent::SignalQueueTimer(SkMSec delay) 309 { 310 if (gTMTaskPtr) 311 { 312 RemoveTimeTask((QElem*)gTMTaskPtr); 313 DisposeTimerUPP(gTMTaskPtr->tmAddr); 314 gTMTaskPtr = nil; 315 } 316 if (delay) 317 { 318 gTMTaskPtr = &gTMTaskRec; 319 memset(gTMTaskPtr, 0, sizeof(gTMTaskRec)); 320 gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc); 321 OSErr err = InstallTimeTask((QElem*)gTMTaskPtr); 322 // SkDebugf("installtimetask of %d returned %d\n", delay, err); 323 PrimeTimeTask((QElem*)gTMTaskPtr, delay); 324 } 325 } 326 327 #endif 328 329