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" {
sk_new_handler()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
SkOSWindow(void * hWnd)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
doPaint(void * ctx)67 void SkOSWindow::doPaint(void* ctx)
68 {
69 this->update(NULL);
70
71 this->getBitmap().drawToPort((WindowRef)fHWND, (CGContextRef)ctx);
72 }
73
updateSize()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
onHandleInval(const SkIRect & r)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
onSetTitle(const char title[])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
onAddMenu(const SkOSMenu * sk_menu)100 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
101 {
102 }
103
getparam(EventRef inEvent,OSType name,OSType type,UInt32 size,void * data)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
raw2key(UInt32 raw)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
post_skmacevent()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
EventHandler(EventHandlerCallRef inHandler,EventRef inEvent,void * userData)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
SignalNonEmptyQueue()293 void SkEvent::SignalNonEmptyQueue()
294 {
295 post_skmacevent();
296 // SkDebugf("signal nonempty\n");
297 }
298
299 static TMTask gTMTaskRec;
300 static TMTask* gTMTaskPtr;
301
sk_timer_proc(TMTask * rec)302 static void sk_timer_proc(TMTask* rec)
303 {
304 SkEvent::ServiceQueueTimer();
305 // SkDebugf("timer task fired\n");
306 }
307
SignalQueueTimer(SkMSec delay)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