• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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