• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkTypes.h"
2 
3 #if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
4 
5 #include <Carbon/Carbon.h>
6 #include "SkCGUtils.h"
7 
8 #include "SkWindow.h"
9 #include "SkCanvas.h"
10 #include "SkOSMenu.h"
11 #include "SkTime.h"
12 
13 #include "SkGraphics.h"
14 #include <new.h>
15 
16 static void (*gPrevNewHandler)();
17 
18 extern "C" {
sk_new_handler()19 	static void sk_new_handler()
20 	{
21 		if (SkGraphics::SetFontCacheUsed(0))
22 			return;
23 		if (gPrevNewHandler)
24 			gPrevNewHandler();
25 		else
26 			sk_throw();
27 	}
28 }
29 
30 static SkOSWindow* gCurrOSWin;
31 static EventTargetRef gEventTarget;
32 static EventQueueRef gCurrEventQ;
33 
MyDrawEventHandler(EventHandlerCallRef myHandler,EventRef event,void * userData)34 static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler,
35                                    EventRef event, void *userData) {
36 	// NOTE: GState is save/restored by the HIView system doing the callback,
37     // so the draw handler doesn't need to do it
38 
39 	OSStatus status = noErr;
40 	CGContextRef context;
41 	HIRect		bounds;
42 
43 	// Get the CGContextRef
44 	status = GetEventParameter (event, kEventParamCGContextRef,
45                                 typeCGContextRef, NULL,
46                                 sizeof (CGContextRef),
47                                 NULL,
48                                 &context);
49 
50 	if (status != noErr) {
51 		SkDebugf("Got error %d getting the context!\n", status);
52 		return status;
53 	}
54 
55 	// Get the bounding rectangle
56 	HIViewGetBounds ((HIViewRef) userData, &bounds);
57 
58     gCurrOSWin->doPaint(context);
59 	return status;
60 }
61 
62 #define SK_MacEventClass			FOUR_CHAR_CODE('SKec')
63 #define SK_MacEventKind				FOUR_CHAR_CODE('SKek')
64 #define SK_MacEventParamName		FOUR_CHAR_CODE('SKev')
65 #define SK_MacEventSinkIDParamName	FOUR_CHAR_CODE('SKes')
66 
set_bindingside(HISideBinding * side,HIViewRef parent,HIBindingKind kind)67 static void set_bindingside(HISideBinding* side, HIViewRef parent, HIBindingKind kind) {
68     side->toView = parent;
69     side->kind = kind;
70     side->offset = 0;
71 }
72 
set_axisscale(HIAxisScale * axis,HIViewRef parent)73 static void set_axisscale(HIAxisScale* axis, HIViewRef parent) {
74     axis->toView = parent;
75     axis->kind = kHILayoutScaleAbsolute;
76     axis->ratio = 1;
77 }
78 
set_axisposition(HIAxisPosition * pos,HIViewRef parent,HIPositionKind kind)79 static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKind kind) {
80     pos->toView = parent;
81     pos->kind = kind;
82     pos->offset = 0;
83 }
84 
SkOSWindow(void * hWnd)85 SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
86 {
87 	OSStatus    result;
88     WindowRef   wr = (WindowRef)hWnd;
89 
90     HIViewRef imageView, parent;
91     HIViewRef rootView = HIViewGetRoot(wr);
92     HIViewFindByID(rootView, kHIViewWindowContentID, &parent);
93     result = HIImageViewCreate(NULL, &imageView);
94 	SkASSERT(result == noErr);
95 
96     result = HIViewAddSubview(parent, imageView);
97 	SkASSERT(result == noErr);
98 
99     fHVIEW = imageView;
100 
101     HIViewSetVisible(imageView, true);
102     HIViewPlaceInSuperviewAt(imageView, 0, 0);
103 
104     if (true) {
105         HILayoutInfo layout;
106         layout.version = kHILayoutInfoVersionZero;
107         set_bindingside(&layout.binding.left, parent, kHILayoutBindLeft);
108         set_bindingside(&layout.binding.top, parent, kHILayoutBindTop);
109         set_bindingside(&layout.binding.right, parent, kHILayoutBindRight);
110         set_bindingside(&layout.binding.bottom, parent, kHILayoutBindBottom);
111         set_axisscale(&layout.scale.x, parent);
112         set_axisscale(&layout.scale.y, parent);
113         set_axisposition(&layout.position.x, parent, kHILayoutPositionLeft);
114         set_axisposition(&layout.position.y, rootView, kHILayoutPositionTop);
115         HIViewSetLayoutInfo(imageView, &layout);
116     }
117 
118     HIImageViewSetOpaque(imageView, true);
119     HIImageViewSetScaleToFit(imageView, false);
120 
121 	static const EventTypeSpec  gTypes[] = {
122 		{ kEventClassKeyboard,  kEventRawKeyDown			},
123         { kEventClassKeyboard,  kEventRawKeyUp              },
124 		{ kEventClassMouse,		kEventMouseDown				},
125 		{ kEventClassMouse,		kEventMouseDragged			},
126 		{ kEventClassMouse,		kEventMouseUp				},
127 		{ kEventClassTextInput, kEventTextInputUnicodeForKeyEvent   },
128 		{ kEventClassWindow,	kEventWindowBoundsChanged	},
129 //		{ kEventClassWindow,	kEventWindowDrawContent		},
130 		{ SK_MacEventClass,		SK_MacEventKind				}
131 	};
132 
133 	EventHandlerUPP handlerUPP = NewEventHandlerUPP(SkOSWindow::EventHandler);
134 	int				count = SK_ARRAY_COUNT(gTypes);
135 
136 	result = InstallEventHandler(GetWindowEventTarget(wr), handlerUPP,
137 						count, gTypes, this, nil);
138 	SkASSERT(result == noErr);
139 
140 	gCurrOSWin = this;
141 	gCurrEventQ = GetCurrentEventQueue();
142 	gEventTarget = GetWindowEventTarget(wr);
143 
144 	static bool gOnce = true;
145 	if (gOnce) {
146 		gOnce = false;
147 		gPrevNewHandler = set_new_handler(sk_new_handler);
148 	}
149 }
150 
doPaint(void * ctx)151 void SkOSWindow::doPaint(void* ctx)
152 {
153 #if 0
154 	this->update(NULL);
155 
156     const SkBitmap& bm = this->getBitmap();
157     CGImageRef img = SkCreateCGImageRef(bm);
158 
159     if (img) {
160         CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
161 
162         CGContextRef cg = reinterpret_cast<CGContextRef>(ctx);
163 
164         CGContextSaveGState(cg);
165         CGContextTranslateCTM(cg, 0, r.size.height);
166         CGContextScaleCTM(cg, 1, -1);
167 
168         CGContextDrawImage(cg, r, img);
169 
170         CGContextRestoreGState(cg);
171 
172         CGImageRelease(img);
173     }
174 #endif
175 }
176 
updateSize()177 void SkOSWindow::updateSize()
178 {
179 	Rect	r;
180 
181 	GetWindowBounds((WindowRef)fHWND, kWindowContentRgn, &r);
182 	this->resize(r.right - r.left, r.bottom - r.top);
183 
184 #if 0
185     HIRect    frame;
186     HIViewRef imageView = (HIViewRef)getHVIEW();
187     HIViewRef parent = HIViewGetSuperview(imageView);
188 
189     HIViewGetBounds(imageView, &frame);
190     SkDebugf("------ %d bounds %g %g %g %g\n", r.right - r.left,
191              frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
192 #endif
193 }
194 
onHandleInval(const SkIRect & r)195 void SkOSWindow::onHandleInval(const SkIRect& r)
196 {
197     SkEvent* evt = new SkEvent("inval-imageview");
198     evt->post(this->getSinkID());
199 }
200 
onEvent(const SkEvent & evt)201 bool SkOSWindow::onEvent(const SkEvent& evt) {
202     if (evt.isType("inval-imageview")) {
203         this->update(NULL);
204 
205         const SkBitmap& bm = this->getBitmap();
206 
207         CGImageRef img = SkCreateCGImageRef(bm);
208         HIImageViewSetImage((HIViewRef)getHVIEW(), img);
209         CGImageRelease(img);
210         return true;
211     }
212     return INHERITED::onEvent(evt);
213 }
214 
onSetTitle(const char title[])215 void SkOSWindow::onSetTitle(const char title[])
216 {
217     CFStringRef str = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
218     SetWindowTitleWithCFString((WindowRef)fHWND, str);
219     CFRelease(str);
220 }
221 
onAddMenu(const SkOSMenu * sk_menu)222 void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
223 {
224 }
225 
getparam(EventRef inEvent,OSType name,OSType type,UInt32 size,void * data)226 static void getparam(EventRef inEvent, OSType name, OSType type, UInt32 size, void* data)
227 {
228 	EventParamType  actualType;
229 	UInt32			actualSize;
230 	OSStatus		status;
231 
232 	status = GetEventParameter(inEvent, name, type, &actualType, size, &actualSize, data);
233 	SkASSERT(status == noErr);
234 	SkASSERT(actualType == type);
235 	SkASSERT(actualSize == size);
236 }
237 
238 enum {
239 	SK_MacReturnKey		= 36,
240 	SK_MacDeleteKey		= 51,
241 	SK_MacEndKey		= 119,
242 	SK_MacLeftKey		= 123,
243 	SK_MacRightKey		= 124,
244 	SK_MacDownKey		= 125,
245 	SK_MacUpKey			= 126,
246 
247     SK_Mac0Key          = 0x52,
248     SK_Mac1Key          = 0x53,
249     SK_Mac2Key          = 0x54,
250     SK_Mac3Key          = 0x55,
251     SK_Mac4Key          = 0x56,
252     SK_Mac5Key          = 0x57,
253     SK_Mac6Key          = 0x58,
254     SK_Mac7Key          = 0x59,
255     SK_Mac8Key          = 0x5b,
256     SK_Mac9Key          = 0x5c
257 };
258 
raw2key(UInt32 raw)259 static SkKey raw2key(UInt32 raw)
260 {
261 	static const struct {
262 		UInt32  fRaw;
263 		SkKey   fKey;
264 	} gKeys[] = {
265 		{ SK_MacUpKey,		kUp_SkKey		},
266 		{ SK_MacDownKey,	kDown_SkKey		},
267 		{ SK_MacLeftKey,	kLeft_SkKey		},
268 		{ SK_MacRightKey,   kRight_SkKey	},
269 		{ SK_MacReturnKey,  kOK_SkKey		},
270 		{ SK_MacDeleteKey,  kBack_SkKey		},
271 		{ SK_MacEndKey,		kEnd_SkKey		},
272         { SK_Mac0Key,       k0_SkKey        },
273         { SK_Mac1Key,       k1_SkKey        },
274         { SK_Mac2Key,       k2_SkKey        },
275         { SK_Mac3Key,       k3_SkKey        },
276         { SK_Mac4Key,       k4_SkKey        },
277         { SK_Mac5Key,       k5_SkKey        },
278         { SK_Mac6Key,       k6_SkKey        },
279         { SK_Mac7Key,       k7_SkKey        },
280         { SK_Mac8Key,       k8_SkKey        },
281         { SK_Mac9Key,       k9_SkKey        }
282 	};
283 
284 	for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
285 		if (gKeys[i].fRaw == raw)
286 			return gKeys[i].fKey;
287 	return kNONE_SkKey;
288 }
289 
post_skmacevent()290 static void post_skmacevent()
291 {
292 	EventRef	ref;
293 	OSStatus	status = CreateEvent(nil, SK_MacEventClass, SK_MacEventKind, 0, 0, &ref);
294 	SkASSERT(status == noErr);
295 
296 #if 0
297 	status = SetEventParameter(ref, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
298 	SkASSERT(status == noErr);
299 	status = SetEventParameter(ref, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
300 	SkASSERT(status == noErr);
301 #endif
302 
303 	EventTargetRef target = gEventTarget;
304 	SetEventParameter(ref, kEventParamPostTarget, typeEventTargetRef, sizeof(target), &target);
305 	SkASSERT(status == noErr);
306 
307 	status = PostEventToQueue(gCurrEventQ, ref, kEventPriorityStandard);
308 	SkASSERT(status == noErr);
309 
310 	ReleaseEvent(ref);
311 }
312 
EventHandler(EventHandlerCallRef inHandler,EventRef inEvent,void * userData)313 pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData )
314 {
315 	SkOSWindow* win = (SkOSWindow*)userData;
316 	OSStatus	result = eventNotHandledErr;
317 	UInt32		wClass = GetEventClass(inEvent);
318 	UInt32		wKind = GetEventKind(inEvent);
319 
320 	gCurrOSWin = win;	// will need to be in TLS. Set this so PostEvent will work
321 
322 	switch (wClass) {
323         case kEventClassMouse: {
324 			Point   pt;
325 			getparam(inEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pt), &pt);
326 			SetPortWindowPort((WindowRef)win->getHWND());
327 			GlobalToLocal(&pt);
328 
329 			switch (wKind) {
330 			case kEventMouseDown:
331 				(void)win->handleClick(pt.h, pt.v, Click::kDown_State);
332 				break;
333 			case kEventMouseDragged:
334 				(void)win->handleClick(pt.h, pt.v, Click::kMoved_State);
335 				break;
336 			case kEventMouseUp:
337 				(void)win->handleClick(pt.h, pt.v, Click::kUp_State);
338 				break;
339 			default:
340 				break;
341 			}
342             break;
343 		}
344         case kEventClassKeyboard:
345             if (wKind == kEventRawKeyDown) {
346                 UInt32  raw;
347                 getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
348                 SkKey key = raw2key(raw);
349                 if (key != kNONE_SkKey)
350                     (void)win->handleKey(key);
351             } else if (wKind == kEventRawKeyUp) {
352                 UInt32 raw;
353                 getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
354                 SkKey key = raw2key(raw);
355                 if (key != kNONE_SkKey)
356                     (void)win->handleKeyUp(key);
357             }
358             break;
359         case kEventClassTextInput:
360             if (wKind == kEventTextInputUnicodeForKeyEvent) {
361                 UInt16  uni;
362                 getparam(inEvent, kEventParamTextInputSendText, typeUnicodeText, sizeof(uni), &uni);
363                 win->handleChar(uni);
364             }
365             break;
366         case kEventClassWindow:
367             switch (wKind) {
368                 case kEventWindowBoundsChanged:
369                     win->updateSize();
370                     break;
371                 case kEventWindowDrawContent: {
372                     CGContextRef cg;
373                     result = GetEventParameter(inEvent,
374                                                kEventParamCGContextRef,
375                                                typeCGContextRef,
376                                                NULL,
377                                                sizeof (CGContextRef),
378                                                NULL,
379                                                &cg);
380                     if (result != 0) {
381                         cg = NULL;
382                     }
383                     win->doPaint(cg);
384                     break;
385                 }
386                 default:
387                     break;
388             }
389             break;
390         case SK_MacEventClass: {
391             SkASSERT(wKind == SK_MacEventKind);
392             if (SkEvent::ProcessEvent()) {
393                     post_skmacevent();
394             }
395     #if 0
396             SkEvent*		evt;
397             SkEventSinkID	sinkID;
398             getparam(inEvent, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
399             getparam(inEvent, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
400     #endif
401             result = noErr;
402             break;
403         }
404         default:
405             break;
406 	}
407 	if (result == eventNotHandledErr) {
408 		result = CallNextEventHandler(inHandler, inEvent);
409     }
410 	return result;
411 }
412 
413 ///////////////////////////////////////////////////////////////////////////////////////
414 
SignalNonEmptyQueue()415 void SkEvent::SignalNonEmptyQueue()
416 {
417 	post_skmacevent();
418 //	SkDebugf("signal nonempty\n");
419 }
420 
421 static TMTask	gTMTaskRec;
422 static TMTask*	gTMTaskPtr;
423 
sk_timer_proc(TMTask * rec)424 static void sk_timer_proc(TMTask* rec)
425 {
426 	SkEvent::ServiceQueueTimer();
427 //	SkDebugf("timer task fired\n");
428 }
429 
SignalQueueTimer(SkMSec delay)430 void SkEvent::SignalQueueTimer(SkMSec delay)
431 {
432 	if (gTMTaskPtr)
433 	{
434 		RemoveTimeTask((QElem*)gTMTaskPtr);
435 		DisposeTimerUPP(gTMTaskPtr->tmAddr);
436 		gTMTaskPtr = nil;
437 	}
438 	if (delay)
439 	{
440 		gTMTaskPtr = &gTMTaskRec;
441 		memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
442 		gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
443 		OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
444 //		SkDebugf("installtimetask of %d returned %d\n", delay, err);
445 		PrimeTimeTask((QElem*)gTMTaskPtr, delay);
446 	}
447 }
448 
449 #endif
450 
451