/*****************************************************************************\ Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. This file is licensed under the Snes9x License. For further information, consult the LICENSE file in the root directory. \*****************************************************************************/ /*********************************************************************************** SNES9X for Mac OS (c) Copyright John Stiles Snes9x for Mac OS X (c) Copyright 2001 - 2011 zones (c) Copyright 2002 - 2005 107 (c) Copyright 2002 PB1400c (c) Copyright 2004 Alexander and Sander (c) Copyright 2004 - 2005 Steven Seeger (c) Copyright 2005 Ryan Vogt (c) Copyright 2019 Michael Donald Buckley ***********************************************************************************/ #include "port.h" #include "mac-prefix.h" #include "mac-dialog.h" #include "mac-gworld.h" #include "mac-os.h" #include "mac-keyboard.h" #define kmUpArrowKey 0x7E #define kmDownArrowKey 0x7D #define kmRightArrowKey 0x7C #define kmLeftArrowKey 0x7B #define kmReturnKey 0x24 #define kmTabKey 0x30 #define kmShiftKey 0x38 #define kmControlKey 0x3B #define kmOptionKey 0x3A #define kmCommandKey 0x37 #define kmXKey 0x07 #define kmZKey 0x06 #define kmKP2Key 0x54 #define kmKP4Key 0x56 #define kmKP5Key 0x57 #define kmKP6Key 0x58 #define kmKP8Key 0x5B #define kmKPEnterKey 0x4C #define kmKPPlusKey 0x45 #define kmKP0Key 0x52 #define kmKPPeriodKey 0x41 #define kmHomeKey 0x73 #define kmPageUpKey 0x74 #define kmEndKey 0x77 #define kmPageDownKey 0x79 #define kmBackslashKey 0x2A #define km1Key 0x12 #define km0Key 0x1D #define kmIKey 0x22 #define kmJKey 0x26 #define kmKKey 0x28 #define kmLKey 0x25 #define kmTildeKey 0x32 #define kmRKey 0x0F #define kmBKey 0x0B #define kmNKey 0x2D #define kmMKey 0x2E #define kmSpaceKey 0x31 #define kmSlashKey 0x2C #define kmPeriodKey 0x2F #define kmQKey 0x0C #define kmWKey 0x0D #define kmEscKey 0x35 #define kmCommaKey 0x2B #define kIconSize 16 #define kKeySize 24 #define KS kKeySize uint8 keyCode[kKeys] = { kmUpArrowKey, kmDownArrowKey, kmLeftArrowKey, kmRightArrowKey, kmShiftKey, kmOptionKey, kmControlKey, kmCommandKey, kmZKey, kmXKey, kmReturnKey, kmTabKey, kmKP8Key, kmKP2Key, kmKP4Key, kmKP6Key, kmPageDownKey, kmPageUpKey, kmEndKey, kmHomeKey, kmKP0Key, kmKPPeriodKey, kmKPEnterKey, kmKPPlusKey, kmBackslashKey, km1Key, km0Key, kmTildeKey, kmRKey, kmBKey, kmNKey, kmMKey, kmSpaceKey, kmSlashKey, kmPeriodKey, kmQKey, kmWKey, kmEscKey, kmCommaKey }; typedef struct { int keyWidth, keyHeight; uint8 scancode; const char *keyLabel; } KeyboardLayout; typedef struct { HIViewRef view; } CustomViewData; static CGImageRef iconTableImage; static CGImageRef keyLayoutImage; static CGImageRef iconPlaceImage; static Ptr iconTableCGWld; static Ptr keyLayoutWorld; static Ptr iconPlaceWorld; static CGRect keyRect[0x80][2]; static uint8 defaultKeys[kKeys]; static HIObjectClassRef theClass; static HIViewRef customView; static HIPoint mousePos; static float ofsx, ofsy; static int dragKey; static CGPoint dragKeyOfs; static CGRect dragKeyRect; static volatile Boolean keyInDrag; static const int kKeyLayoutWidth = kKeySize * 23 + 1, kKeyLayoutHeight = kKeySize * 7 + 1; static KeyboardLayout keys[] = { { KS, KS, 0x35, "esc" }, { KS, KS, 0x00, NULL }, { KS, KS, 0x7a, "F1" }, { KS, KS, 0x78, "F2" }, { KS, KS, 0x63, "F3" }, { KS, KS, 0x76, "F4" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x60, "F5" }, { KS, KS, 0x61, "F6" }, { KS, KS, 0x62, "F7" }, { KS, KS, 0x64, "F8" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x65, "F9" }, { KS, KS, 0x6d, "F10" }, { KS, KS, 0x67, "F11" }, { KS, KS, 0x6f, "F12" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x69, "F13" }, { KS, KS, 0x6b, "F14" }, { KS, KS, 0x71, "F15" }, { 0, 0, 0x00, NULL }, { 0, 0, 0x00, NULL }, { KS, KS, 0x32, "`" }, { KS, KS, 0x12, "1" }, { KS, KS, 0x13, "2" }, { KS, KS, 0x14, "3" }, { KS, KS, 0x15, "4" }, { KS, KS, 0x17, "5" }, { KS, KS, 0x16, "6" }, { KS, KS, 0x1a, "7" }, { KS, KS, 0x1c, "8" }, { KS, KS, 0x19, "9" }, { KS, KS, 0x1d, "0" }, { KS, KS, 0x1b, "-" }, { KS, KS, 0x18, "=" }, { KS * 2, KS, 0x33, "delete" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x72, "ins" }, { KS, KS, 0x73, "hom" }, { KS, KS, 0x74, "pgu" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x47, "clr" }, { KS, KS, 0x51, "=" }, { KS, KS, 0x4b, "/" }, { KS, KS, 0x43, "*" }, { 0, 0, 0x00, NULL }, { KS * 3 / 2, KS, 0x30, "tab" }, { KS, KS, 0x0c, "Q" }, { KS, KS, 0x0d, "W" }, { KS, KS, 0x0e, "E" }, { KS, KS, 0x0f, "R" }, { KS, KS, 0x11, "T" }, { KS, KS, 0x10, "Y" }, { KS, KS, 0x20, "U" }, { KS, KS, 0x22, "I" }, { KS, KS, 0x1f, "O" }, { KS, KS, 0x23, "P" }, { KS, KS, 0x21, "[" }, { KS, KS, 0x1e, "]" }, { KS * 3 / 2, KS, 0x2a, "\\" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x75, "del" }, { KS, KS, 0x77, "end" }, { KS, KS, 0x79, "pgd" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x59, "7" }, { KS, KS, 0x5b, "8" }, { KS, KS, 0x5c, "9" }, { KS, KS, 0x4e, "-" }, { 0, 0, 0x00, NULL }, { KS * 2, KS, 0x39, "caps" }, { KS, KS, 0x00, "A" }, { KS, KS, 0x01, "S" }, { KS, KS, 0x02, "D" }, { KS, KS, 0x03, "F" }, { KS, KS, 0x05, "G" }, { KS, KS, 0x04, "H" }, { KS, KS, 0x26, "J" }, { KS, KS, 0x28, "K" }, { KS, KS, 0x25, "L" }, { KS, KS, 0x29, ";" }, { KS, KS, 0x27, "\xd3" }, { KS * 2, KS, 0x24, "return" }, { KS * 4, KS, 0x00, NULL }, { KS, KS, 0x56, "4" }, { KS, KS, 0x57, "5" }, { KS, KS, 0x58, "6" }, { KS, KS, 0x45, "+" }, { 0, 0, 0x00, NULL }, { KS * 5 / 2, KS, 0x38, "shift" }, { KS, KS, 0x06, "Z" }, { KS, KS, 0x07, "X" }, { KS, KS, 0x08, "C" }, { KS, KS, 0x09, "V" }, { KS, KS, 0x0b, "B" }, { KS, KS, 0x2d, "N" }, { KS, KS, 0x2e, "M" }, { KS, KS, 0x2b, "," }, { KS, KS, 0x2f, "." }, { KS, KS, 0x2c, "/" }, { KS * 5 / 2, KS, 0x38, "shift" }, { KS * 3 / 2, KS, 0x00, NULL }, { KS, KS, 0x7e, "up" }, { KS * 3 / 2, KS, 0x00, NULL }, { KS, KS, 0x53, "1" }, { KS, KS, 0x54, "2" }, { KS, KS, 0x55, "3" }, { KS, KS * 2, 0x4c, "ent" }, { 0, 0, 0x00, NULL }, { KS * 3 / 2, KS, 0x3b, "ctrl" }, { KS * 3 / 2, KS, 0x3a, "opt" }, { KS * 3 / 2, KS, 0x37, "cmd" }, { KS * 6, KS, 0x31, " " }, { KS * 3 / 2, KS, 0x37, "cmd" }, { KS * 3 / 2, KS, 0x3a, "opt" }, { KS * 3 / 2, KS, 0x3b, "ctrl" }, { KS / 2, KS, 0x00, NULL }, { KS, KS, 0x7b, "lt" }, { KS, KS, 0x7d, "dn" }, { KS, KS, 0x7c, "rt" }, { KS / 2, KS, 0x00, NULL }, { KS * 2, KS, 0x52, "0" }, { KS, KS, 0x41, "." }, { 0, 0, 0x00, NULL } }; static void CreateIconTableImage (void); static void ReleaseIconTableImage (void); static void CreateKeyLayoutImage (void); static void ReleaseKeyLayoutImage (void); static void CreateIconPlaceImage (void); static void UpdateIconPlaceImage (void); static void ReleaseIconPlaceImage (void); static void DrawPlacedIcon (CGContextRef, int); static void DrawDraggedIcon (CGContextRef, int, CGPoint *); static Boolean KeyCodeInUse (int); static int FindHitKey (HIPoint, CGRect *, CGPoint *); static OSStatus KeyWindowEventHandler (EventHandlerCallRef, EventRef, void *); static OSStatus KeyLegendEventHandler (EventHandlerCallRef, EventRef, void *); static OSStatus KeyLayoutEventHandler (EventHandlerCallRef, EventRef, void *); #define kCustomLayoutViewClassID CFSTR("com.snes9x.macos.snes9x.keylayout") void ConfigureKeyboard (void) { // OSStatus err; // IBNibRef nibRef; // // err = CreateNibReference(kMacS9XCFString, &nibRef); // if (err == noErr) // { // WindowRef tWindowRef; // // err = CreateWindowFromNib(nibRef, CFSTR("Keyboard"), &tWindowRef); // if (err == noErr) // { // EventHandlerRef wref, iref1, iref2; // EventHandlerUPP wUPP, iUPP; // EventTypeSpec wEvents[] = { { kEventClassWindow, kEventWindowClose }, // { kEventClassCommand, kEventCommandProcess }, // { kEventClassCommand, kEventCommandUpdateStatus } }, // cEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct }, // { kEventClassHIObject, kEventHIObjectDestruct }, // { kEventClassHIObject, kEventHIObjectInitialize }, // { kEventClassControl, kEventControlDraw }, // { kEventClassControl, kEventControlHitTest }, // { kEventClassControl, kEventControlTrack } }, // iEvents[] = { { kEventClassControl, kEventControlDraw } }; // HIObjectRef hiObject; // HIViewRef contentView, image1, image2; // HIViewID cid; // HIRect frame; // Rect winBounds; // // UpdateIconPlaceImage(); // // keyInDrag = false; // dragKey = -1; // dragKeyOfs = CGPointMake(0.0f, 0.0f); // dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); // mousePos = CGPointMake(0.0f, 0.0f); // // err = noErr; // if (theClass == NULL) // err = HIObjectRegisterSubclass(kCustomLayoutViewClassID, kHIViewClassID, 0, KeyLayoutEventHandler, GetEventTypeCount(cEvents), cEvents, NULL, &theClass); // // if (err == noErr) // { // err = HIObjectCreate(kCustomLayoutViewClassID, NULL, &hiObject); // if (err == noErr) // { // GetWindowBounds(tWindowRef, kWindowContentRgn, &winBounds); // // frame.origin.x = 2.0f; // frame.origin.y = 2.0f; // frame.size.width = (float) (winBounds.right - winBounds.left) - 4.0f; // frame.size.height = (float) kKeyLayoutHeight + 36.0f; // // ofsx = (float) (((int) frame.size.width - kKeyLayoutWidth ) >> 1) + 1.0f; // ofsy = (float) (((int) frame.size.height - kKeyLayoutHeight) >> 1) + 1.0f; // // customView = (HIViewRef) hiObject; // // HIViewFindByID(HIViewGetRoot(tWindowRef), kHIViewWindowContentID, &contentView); // HIViewAddSubview(contentView, customView); // HIViewSetFrame(customView, &frame); // HIViewSetVisible(customView, true); // // cid.signature = 'Lgnd'; // cid.id = 0; // HIViewFindByID(contentView, cid, &image1); // cid.id = 1; // HIViewFindByID(contentView, cid, &image2); // iUPP = NewEventHandlerUPP(KeyLegendEventHandler); // err = InstallControlEventHandler(image1, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image1, &iref1); // err = InstallControlEventHandler(image2, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image2, &iref2); // // wUPP = NewEventHandlerUPP(KeyWindowEventHandler); // err = InstallWindowEventHandler(tWindowRef, wUPP, GetEventTypeCount(wEvents), wEvents, (void *) tWindowRef, &wref); // // MoveWindowPosition(tWindowRef, kWindowKeyConfig, false); // ShowWindow(tWindowRef); // err = RunAppModalLoopForWindow(tWindowRef); // HideWindow(tWindowRef); // SaveWindowPosition(tWindowRef, kWindowKeyConfig); // // err = RemoveEventHandler(iref2); // err = RemoveEventHandler(iref1); // DisposeEventHandlerUPP(iUPP); // // err = RemoveEventHandler(wref); // DisposeEventHandlerUPP(wUPP); // } // } // // CFRelease(tWindowRef); // } // // DisposeNibReference(nibRef); // } } static void CreateIconTableImage (void) { CGContextRef ctx; CGDataProviderRef prov; CGColorSpaceRef color; CGRect rct; rct = CGRectMake(0.0f, 0.0f, (float) kIconSize, (float) kIconSize); iconTableCGWld = (Ptr) malloc(kIconSize * kKeys * (kIconSize + 1) * 4); if (!iconTableCGWld) QuitWithFatalError(@"keyboard 08"); ctx = NULL; color = CGColorSpaceCreateDeviceRGB(); if (color) { ctx = CGBitmapContextCreate(iconTableCGWld, kIconSize * kKeys, kIconSize, 8, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrderDefault); CGColorSpaceRelease(color); } if (!ctx) QuitWithFatalError(@"keyboard 09"); CGContextTranslateCTM(ctx, 0.0f, (float) kIconSize); CGContextScaleCTM(ctx, 1.0f, -1.0f); // SNES pads for (int i = macPadIconIndex; i < macPadIconIndex + 12 * 2; i++) { CGContextDrawImage(ctx, rct, macIconImage[i]); } // Function buttons for (int i = macFunctionIconIndex; i < macFunctionIconIndex + 17; i++) { CGContextDrawImage(ctx, rct, macIconImage[i]); rct = CGRectOffset(rct, kIconSize, 0); } CGContextRelease(ctx); iconTableImage = NULL; prov = CGDataProviderCreateWithData(NULL, iconTableCGWld, kIconSize * kKeys * kIconSize * 4, NULL); if (prov) { color = CGColorSpaceCreateDeviceRGB(); if (color) { iconTableImage = CGImageCreate(kIconSize * kKeys, kIconSize, 8, 32, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrderDefault, prov, NULL, 0, kCGRenderingIntentDefault); CGColorSpaceRelease(color); } CGDataProviderRelease(prov); } if (!iconTableImage) QuitWithFatalError(@"keyboard 10"); } static void ReleaseIconTableImage (void) { CGImageRelease(iconTableImage); free(iconTableCGWld); } static void CreateKeyLayoutImage (void) { CGContextRef ctx; CGDataProviderRef prov; CGColorSpaceRef color; CGAffineTransform flipMatrix; CGRect rct, r; int index, scancode; rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); for (int i = 0; i < 0x80; i++) keyRect[i][0] = keyRect[i][1] = rct; keyLayoutWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4); if (!keyLayoutWorld) QuitWithFatalError(@"keyboard 02"); ctx = NULL; color = CGColorSpaceCreateDeviceRGB(); if (color) { ctx = CGBitmapContextCreate(keyLayoutWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault); CGColorSpaceRelease(color); } if (!ctx) QuitWithFatalError(@"keyboard 04"); CGContextSetLineJoin(ctx, kCGLineJoinMiter); flipMatrix = CGAffineTransformMake(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman); CGContextSetTextDrawingMode(ctx, kCGTextFill); CGContextSetTextMatrix(ctx, flipMatrix); rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight); CGContextClearRect(ctx, rct); index = 0; rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); for (int i = 0; i < 7; i++) { while (keys[index].keyWidth) { rct.size.width = (float) keys[index].keyWidth; if (keys[index].keyLabel) { rct.size.height = (float) keys[index].keyHeight; scancode = keys[index].scancode; if (keyRect[scancode][0].size.height < 1.0) keyRect[scancode][0] = rct; else keyRect[scancode][1] = rct; r = rct; r.origin.x += 1.0f; r.origin.y += 1.0f; r.size.width -= 1.0f; r.size.height -= 1.0f; CGContextSetRGBStrokeColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f); CGContextStrokeRect(ctx, r); float h, p; CGRectInset(r, 2.0f, 2.0f); h = r.size.height; for (float f = h; f >= 1.0f; f -= 1.0f) { p = (155.0f + (h - f)) / 180.0f; CGContextSetRGBFillColor(ctx, p, p, p, 1.0f); CGContextFillRect(ctx, r); r.size.height -= 1.0f; } CGContextSetRGBFillColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f); CGContextShowTextAtPoint(ctx, rct.origin.x + 3.0f, rct.origin.y + rct.size.height - 3.0f, keys[index].keyLabel, strlen(keys[index].keyLabel)); } rct.origin.x += rct.size.width; index++; } rct.origin.y += kKeySize; rct.origin.x = rct.size.width = 0; index++; } CGContextRelease(ctx); keyLayoutImage = NULL; prov = CGDataProviderCreateWithData(NULL, keyLayoutWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL); if (prov) { color = CGColorSpaceCreateDeviceRGB(); if (color) { keyLayoutImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault, prov, NULL, 0, kCGRenderingIntentDefault); CGColorSpaceRelease(color); } CGDataProviderRelease(prov); } if (!keyLayoutImage) QuitWithFatalError(@"keyboard 05"); } static void ReleaseKeyLayoutImage (void) { CGImageRelease(keyLayoutImage); free(keyLayoutWorld); } static void CreateIconPlaceImage (void) { iconPlaceWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4); if (!iconPlaceWorld) QuitWithFatalError(@"keyboard 06"); iconPlaceImage = NULL; UpdateIconPlaceImage(); } static void UpdateIconPlaceImage (void) { CGContextRef ctx; CGDataProviderRef prov; CGColorSpaceRef color; CGRect rct; if (iconPlaceImage) CGImageRelease(iconPlaceImage); iconPlaceImage = NULL; color = CGColorSpaceCreateDeviceRGB(); if (color) { ctx = CGBitmapContextCreate(iconPlaceWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault); if (ctx) { rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight); CGContextDrawImage(ctx, rct, keyLayoutImage); for (int i = 0; i < kKeys; i++) DrawPlacedIcon(ctx, i); CGContextRelease(ctx); } prov = CGDataProviderCreateWithData(NULL, iconPlaceWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL); if (prov) { iconPlaceImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrderDefault, prov, NULL, 0, kCGRenderingIntentDefault); CGDataProviderRelease(prov); } CGColorSpaceRelease(color); } if (!iconPlaceImage) QuitWithFatalError(@"keyboard 07"); } static void ReleaseIconPlaceImage (void) { CGImageRelease(iconPlaceImage); free(iconPlaceWorld); } void InitKeyboard (void) { theClass = NULL; memcpy(defaultKeys, keyCode, sizeof(keyCode)); CreateIconTableImage(); CreateKeyLayoutImage(); CreateIconPlaceImage(); } void DeinitKeyboard (void) { ReleaseIconPlaceImage(); ReleaseKeyLayoutImage(); ReleaseIconTableImage(); } static void DrawPlacedIcon (CGContextRef ctx, int which) { CGRect keyBounds, srcRect, dstRect; CGContextSaveGState(ctx); CGContextSetRGBFillColor(ctx, 0.40f, 0.40f, 0.65f, 0.5f); for (int each = 0; each <= 1; each++) { keyBounds = keyRect[keyCode[which]][each]; if (keyBounds.size.height > 1.0f) { keyBounds.origin.x += 1.0f; keyBounds.origin.y += 1.0f; keyBounds.size.width -= 1.0f; keyBounds.size.height -= 1.0f; CGContextFillRect(ctx, keyBounds); keyBounds.origin.x -= 1.0f; keyBounds.origin.y -= 1.0f; keyBounds.size.width += 1.0f; keyBounds.size.height += 1.0f; srcRect.origin.x = (float) (which * kIconSize); srcRect.origin.y = 0.0f; srcRect.size.width = (float) kIconSize; srcRect.size.height = (float) kIconSize; dstRect.origin.x = keyBounds.origin.x + (keyBounds.size.width - kIconSize) / 2.0f; dstRect.origin.y = keyBounds.origin.y + (keyBounds.size.height - kIconSize) / 2.0f; dstRect.size.width = (float) kIconSize; dstRect.size.height = (float) kIconSize; DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect); } } CGContextRestoreGState(ctx); } static void DrawDraggedIcon (CGContextRef ctx, int which, CGPoint *offset) { CGRect srcRect, dstRect; CGContextSaveGState(ctx); srcRect.origin.x = (float) (which * kIconSize); srcRect.origin.y = 0.0f; srcRect.size.width = (float) kIconSize; srcRect.size.height = (float) kIconSize; dstRect.origin.x = mousePos.x + offset->x; dstRect.origin.y = mousePos.y + offset->y; dstRect.size.width = (float) kIconSize; dstRect.size.height = (float) kIconSize; CGContextSetAlpha(ctx, 0.5f); DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect); CGContextRestoreGState(ctx); } static Boolean KeyCodeInUse (int code) { for (int i = 0; i < kKeys; i++) if (keyCode[i] == code) return (true); return (false); } static int FindHitKey (HIPoint where, CGRect *keybounds, CGPoint *offset) { int hit; hit = -1; *offset = CGPointMake(0.0f, 0.0f); *keybounds = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); for (int which = 0; which < kKeys; which++) { for (int each = 0; each <= 1; each++) { if (CGRectContainsPoint(keyRect[keyCode[which]][each], where)) { hit = which; *keybounds = keyRect[keyCode[which]][each]; offset->x = keybounds->origin.x + (keybounds->size.width - kIconSize) / 2.0f - where.x + 18.0f; offset->y = keybounds->origin.y + (keybounds->size.height - kIconSize) / 2.0f - where.y + 18.0f; } } } return (hit); } static OSStatus KeyWindowEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) { // OSStatus err, result = eventNotHandledErr; // WindowRef tWindowRef = (WindowRef) inUserData; // // switch (GetEventClass(inEvent)) // { // case kEventClassWindow: // switch (GetEventKind(inEvent)) // { // case kEventWindowClose: // QuitAppModalLoopForWindow(tWindowRef); // result = noErr; // } // // break; // // case kEventClassCommand: // switch (GetEventKind(inEvent)) // { // HICommand tHICommand; // // case kEventCommandUpdateStatus: // err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); // if (err == noErr && tHICommand.commandID == 'clos') // { // UpdateMenuCommandStatus(true); // result = noErr; // } // // break; // // case kEventCommandProcess: // err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); // if (err == noErr) // { // if (tHICommand.commandID == 'DFLT') // { // memcpy(keyCode, defaultKeys, sizeof(keyCode)); // UpdateIconPlaceImage(); // HIViewSetNeedsDisplay(customView, true); // result = noErr; // } // } // } // } // // return (result); return 0; } static OSStatus KeyLegendEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) { // OSStatus err, result = eventNotHandledErr; // HIViewRef view = (HIViewRef) inUserData; // // switch (GetEventClass(inEvent)) // { // case kEventClassControl: // switch (GetEventKind(inEvent)) // { // case kEventControlDraw: // CGContextRef ctx; // // err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); // if (err == noErr) // { // HIViewID cid; // HIRect bounds; // // GetControlID(view, &cid); // HIViewGetBounds(view, &bounds); // CGContextTranslateCTM(ctx, 0, bounds.size.height); // CGContextScaleCTM(ctx, 1.0f, -1.0f); // CGContextDrawImage(ctx, CGRectMake(0, 0, kIconSize, kIconSize), macIconImage[macLegendIconIndex + cid.id]); // // result = noErr; // } // } // } // // return (result); return 0; } static OSStatus KeyLayoutEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) { // OSStatus err, result = eventNotHandledErr; // CustomViewData *data = (CustomViewData *) inUserData; // // switch (GetEventClass(inEvent)) // { // case kEventClassHIObject: // switch (GetEventKind(inEvent)) // { // case kEventHIObjectConstruct: // data = (CustomViewData *) calloc(1, sizeof(CustomViewData)); // if (data) // { // HIViewRef epView; // // err = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView); // if (err == noErr) // { // data->view = epView; // result = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(data), &data); // } // } // // break; // // case kEventHIObjectDestruct: // if (data) // free(data); // // result = noErr; // break; // // case kEventHIObjectInitialize: // result = CallNextEventHandler(inHandlerRef, inEvent); // } // // break; // // case kEventClassControl: // switch (GetEventKind(inEvent)) // { // case kEventControlDraw: // CGContextRef ctx; // // err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(ctx), NULL, &ctx); // if (err == noErr) // { // HIRect bounds, srcRect, dstRect; // // HIViewGetBounds(customView, &bounds); // srcRect = CGRectMake(0, 0, kKeyLayoutWidth, kKeyLayoutHeight); // // dstRect.origin.x = (float) (((int) bounds.size.width - kKeyLayoutWidth ) >> 1); // dstRect.origin.y = (float) (((int) bounds.size.height - kKeyLayoutHeight) >> 1); // dstRect.size.width = (float) kKeyLayoutWidth; // dstRect.size.height = (float) kKeyLayoutHeight; // // DrawSubCGImage(ctx, iconPlaceImage, srcRect, dstRect); // if (keyInDrag && (dragKey != -1)) // DrawDraggedIcon(ctx, dragKey, &dragKeyOfs); // } // // result = noErr; // break; // // case kEventControlHitTest: // ControlPartCode part; // // part = kControlButtonPart; // result = SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); // // break; // // case kEventControlTrack: // MouseTrackingResult trackResult; // WindowRef window; // HIViewRef contentView; // HIPoint hipt; // // dragKey = -1; // dragKeyOfs = CGPointMake(0.0f, 0.0f); // dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); // mousePos = CGPointMake(0.0f, 0.0f); // trackResult = kMouseTrackingMouseDown; // // window = GetControlOwner(customView); // HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &contentView); // // #ifdef MAC_TIGER_PANTHER_SUPPORT // CGrafPtr oldPort; // Point qdpt; // Boolean portChanged = false; // // if (systemVersion < 0x1050) // portChanged = QDSwapPort(GetWindowPort(window), &oldPort); // #endif // // err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(hipt), NULL, &hipt); // if (err == noErr) // { // hipt.x -= ofsx; // hipt.y -= ofsy; // // dragKey = FindHitKey(hipt, &dragKeyRect, &dragKeyOfs); // if (dragKey != -1) // { // keyInDrag = true; // // while (trackResult != kMouseTrackingMouseUp) // { // if (CGPointEqualToPoint(mousePos, hipt) == 0) // { // mousePos = hipt; // HIViewSetNeedsDisplay(customView, true); // } // // if (systemVersion >= 0x1050) // { // err = HIViewTrackMouseLocation(customView, 0, kEventDurationForever, 0, NULL, &hipt, NULL, NULL, &trackResult); // hipt.x -= ofsx; // hipt.y -= ofsy; // } // #ifdef MAC_TIGER_PANTHER_SUPPORT // else // { // TrackMouseLocation(NULL, &qdpt, &trackResult); // hipt.x = qdpt.h - ofsx; // hipt.y = qdpt.v - ofsy; // HIViewConvertPoint(&hipt, contentView, customView); // } // #endif // } // // keyInDrag = false; // // for (int code = 0; code < 0x80; code++) // { // for (int each = 0; each <= 1; each++) // { // if (CGRectContainsPoint(keyRect[code][each], mousePos)) // { // if (!KeyCodeInUse(code)) // { // keyCode[dragKey] = code; // UpdateIconPlaceImage(); // } // } // } // } // // HIViewSetNeedsDisplay(customView, true); // } // } // // #ifdef MAC_TIGER_PANTHER_SUPPORT // if (systemVersion < 0x1050) // { // if (portChanged) // QDSwapPort(oldPort, NULL); // } // #endif // // result = noErr; // } // } // // return (result); return 0; }