Home | History | Annotate | Download | only in ports
      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