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
11static void (*gPrevNewHandler)();
12
13extern "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
25static SkOSWindow* gCurrOSWin;
26static EventTargetRef gEventTarget;
27static 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
34SkOSWindow::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
67void SkOSWindow::doPaint(void* ctx)
68{
69	this->update(NULL);
70
71	this->getBitmap().drawToPort((WindowRef)fHWND, (CGContextRef)ctx);
72}
73
74void 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
82void 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
93void SkOSWindow::onSetTitle(const char title[])
94{
95    CFStringRef str = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
96    SetWindowTitleWithCFString((WindowRef)fHWND, str);
97    CFRelease(str);
98}
99
100void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
101{
102}
103
104static 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
116enum {
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
137static 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
168static 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
191pascal 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
293void SkEvent::SignalNonEmptyQueue()
294{
295	post_skmacevent();
296//	SkDebugf("signal nonempty\n");
297}
298
299static TMTask	gTMTaskRec;
300static TMTask*	gTMTaskPtr;
301
302static void sk_timer_proc(TMTask* rec)
303{
304	SkEvent::ServiceQueueTimer();
305//	SkDebugf("timer task fired\n");
306}
307
308void 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