snes9x/macosx/mac-keyboard.mm

1029 lines
33 KiB
Plaintext
Executable File

/*****************************************************************************\
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;
}