Open lxxzq opened 3 years ago
typedef TISInputSourceRef (PFN_TISCopyCurrentKeyboardLayoutInputSource)(void); typedef void (PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef); typedef UInt8 (PFN_LMGetKbdType)(void);
struct MacOsTIS { CFBundleRef bundle; PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource; PFN_TISGetInputSourceProperty GetInputSourceProperty; PFN_LMGetKbdType GetKbdType; CFStringRef kPropertyUnicodeKeyLayoutData; };
void PlatformPostEmptyEvent(void) { @autoreleasepool { NSEvent event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0 windowNumber:0 context:nil subtype:0 data1:0 data2:0]; [NSApp postEvent:event atStart:YES]; } } void AppleCommandWindowClose(void sender) { struct PlatformOpengl obj = (struct PlatformOpengl)sender; obj->isRun = 0; PlatformPostEmptyEvent(); } void AppleCommandWindowMinimize(void sender) { struct PlatformOpengl obj = (struct PlatformOpengl)sender; NSView view = obj->view; [view.window miniaturize:view]; } void AppleCommandWindowMaximize(void sender) { struct PlatformOpengl obj = (struct PlatformOpengl)sender; NSView view = obj->view; if (obj->windowState.isMaximized == 0) { obj->windowState.isMaximized = 1; NSRect rect = [view frame]; rect = [view.window convertRectToScreen:rect]; obj->windowState.windowPosX = rect.origin.x; obj->windowState.windowPosY = rect.origin.y; obj->windowState.windowSizeWidth = rect.size.width; obj->windowState.windowSizeHeight = rect.size.height; rect = [[NSScreen mainScreen] frame]; rect.size.height -= (24 + 80); rect.origin.y += 80; [view.window setFrame:[view.window frameRectForContentRect:rect] display:YES]; } else { NSRect rect = NSMakeRect(obj->windowState.windowPosX, obj->windowState.windowPosY, obj->windowState.windowSizeWidth, obj->windowState.windowSizeHeight); [view.window setFrame:[view.window frameRectForContentRect:rect] display:YES]; obj->windowState.isMaximized = 0; } } static NSUInteger getStyleMask(bool isBorderless) { NSUInteger styleMask; if (isBorderless) { styleMask = NSWindowStyleMaskBorderless; } else { styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable; } return styleMask; }
static int updateUnicodeData(struct PlatformOpengl* obj) { if (obj->inputSource) { CFRelease(obj->inputSource); obj->inputSource = 0; obj->inputSourceUnicodeData = 0; } obj->inputSource = TISCopyCurrentKeyboardLayoutInputSource(); if (!obj->inputSource) { NSLog(@"Cocoa: Failed to retrieve keyboard layout input source"); return 0; } obj->inputSourceUnicodeData = TISGetInputSourceProperty(obj->inputSource, kTISPropertyUnicodeKeyLayoutData); if (!obj->inputSourceUnicodeData) { NSLog(@"Cocoa: Failed to retrieve keyboard layout Unicode data"); return 0; } return 1; }
@interface InputSource : NSObject @end
@implementation InputSource { struct PlatformOpengl* platform; }
} @end static PObool initializeTIS(struct PlatformOpengl obj) { struct MacOsTIS tis = (struct MacOsTIS)obj->dll; tis->bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox")); if (!tis->bundle) { NSLog(@"Cocoa: Failed to load HIToolbox.framework"); return 0; } CFStringRef kPropertyUnicodeKeyLayoutData = CFBundleGetDataPointerForName(tis->bundle, CFSTR("kTISPropertyUnicodeKeyLayoutData")); tis->CopyCurrentKeyboardLayoutInputSource = CFBundleGetFunctionPointerForName(tis->bundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource")); tis->GetInputSourceProperty = CFBundleGetFunctionPointerForName(tis->bundle, CFSTR("TISGetInputSourceProperty")); tis->GetKbdType = CFBundleGetFunctionPointerForName(tis->bundle, CFSTR("LMGetKbdType"));
if (!kPropertyUnicodeKeyLayoutData ||
!tis->CopyCurrentKeyboardLayoutInputSource ||
!tis->GetInputSourceProperty ||
!tis->GetKbdType)
{
NSLog(@"Cocoa: Failed to load TIS API symbols");
return 0;
}
tis->kPropertyUnicodeKeyLayoutData = *kPropertyUnicodeKeyLayoutData;
return updateUnicodeData(obj);
}
PObool PlatformInit(struct PlatformOpengl obj, int x, int y, int w, int h)
{
@autoreleasepool
{
obj->dll = calloc(1, sizeof(struct MacOsTIS));
NSApplicationLoad();
NSRect rect = NSMakeRect(x, y, w, h);
NSWindow win = [[NSWindow alloc] initWithContentRect:rect
styleMask:getStyleMask(1)
backing: NSBackingStoreBuffered
defer: NO];
ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType (&psn, kProcessTransformToForegroundApplication);
[win setAcceptsMouseMovedEvents:YES];
[NSApp activateIgnoringOtherApps:YES];
[win makeKeyAndOrderFront: NSApp];
obj->window = win;
NSOpenGLPixelFormatAttribute attributes[] =
{
NSOpenGLPFADoubleBuffer,
0
};
NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc]
initWithAttributes:attributes];
OpenGLView* view = [[OpenGLView alloc] initWithFrame:rect pixelFormat:pf];
[view setPlatform:obj];
[win setContentView: view];
[win center];
obj->eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (!obj->eventSource)
return 0;
CGEventSourceSetLocalEventsSuppressionInterval((CGEventSourceRef)obj->eventSource, 0.0);
initializeTIS(obj);
obj->CommandWindowClose = AppleCommandWindowClose;
obj->CommandWindowMaximize = AppleCommandWindowMaximize;
obj->CommandWindowMinimize = AppleCommandWindowMinimize;
}
return POtrue;
}
void PlatformExit(struct PlatformOpengl obj) { if (obj->inputSource) { CFRelease(obj->inputSource); obj->inputSource = NULL; obj->inputSourceUnicodeData = nil; } if (obj->eventSource) { CFRelease(obj->eventSource); obj->eventSource = 0; } if(obj->view) { OpenGLView view = (OpenGLView)obj->view; [view release]; obj->view = 0; } if(obj->dll) { free(obj->dll); } NSLog(@"PlatformExit"); } void PlatformSwicthBuffer(struct PlatformOpengl obj) { OpenGLView view = (OpenGLView)obj->view; [[view openGLContext] flushBuffer]; } void PlatformPollEvents(struct PlatformOpengl obj) { @autoreleasepool { do { NSEvent evt = [NSApp nextEventMatchingMask : NSEventMaskAny untilDate : [NSDate distantFuture] inMode : NSDefaultRunLoopMode dequeue : YES ]; NSEventType evtType = [evt type]; if (evtType == NSEventTypeApplicationDefined) { break; } PlatformEventType(obj, evt); [NSApp sendEvent : evt]; } while (1); } }
void InputChar(void* window, unsigned int code, int mods, int plain) { NSLog(@"InputChar code:%d mods:%d plain:%d", code, mods, plain); }
static int keyModsFlags(NSUInteger flags) { int mods = 0; if (flags & NSEventModifierFlagShift) mods |= KEY_MOD_SHIFT; if (flags & NSEventModifierFlagControl) mods |= KEY_MOD_CONTROL; if (flags & NSEventModifierFlagOption) mods |= KEY_MOD_ALT; if (flags & NSEventModifierFlagCommand) mods |= KEY_MOD_SUPER; if (flags & NSEventModifierFlagCapsLock) mods |= KEY_MOD_CAPS_LOCK; return mods; }
@implementation OpenGLView { struct PlatformOpengl* platform; }
}
(void)keyDown:(NSEvent *)event {
printf("keyCode:%d\n", event.keyCode); printf("characters:%ls\n", event.characters);
/*
unichar character;
character = [characters characterAtIndex: 0];
if (character == NSRightArrowFunctionKey) { [self moveSelectedBlockBy: 1];
} else if (character == NSLeftArrowFunctionKey) { [self moveSelectedBlockBy: -1];
} //也可以获取其他按键 */
printf("keyDown %d\n", [event keyCode]); //const int key = translateKey([event keyCode]); //const int mods = translateFlags([event modifierFlags]);
//_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
[self interpretKeyEvents:@[event]]; }
(void)flagsChanged:(NSEvent )event { / int action; const unsigned int modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; const int key = translateKey([event keyCode]); const int mods = translateFlags(modifierFlags); const NSUInteger keyFlag = translateKeyToModifierFlag(key);
if (keyFlag & modifierFlags) { if (window->keys[key] == GLFW_PRESS) action = GLFW_RELEASE; else action = GLFW_PRESS; } else action = GLFW_RELEASE;
_glfwInputKey(window, key, [event keyCode], action, mods); */ printf("flagsChanged\n"); }
enum MouseKey { MouseKeyLeft = 0, MouseKeyRight, MouseKeyOther }; enum MouseEvent { MouseEventNormal = 0, MouseEventDown = 1, MouseEventUp = 2 }; typedef void (PlatformCommandWindowClose)(void sender); typedef void (PlatformCommandWindowMinimize)(void sender); typedef void (PlatformCommandWindowMaximize)(void sender); typedef void (PlatformEventMouseKey)(void sender, enum MouseKey key, enum MouseEvent evt, int x, int y); typedef void (PlatformEventMouseMove)(void sender, PObool isRect, int x, int y); typedef void (PlatformEventMouseDragged)(void sender, enum MouseKey key, PObool isRect, int x, int y); typedef void (PlatformEventScrollWheel)(void sender, float v);
struct MouseDragged { int isDrag; float xScreen; float yScreen; float xOrigin; float yOrigin; float xDelta; float yDelta; }; struct WindowState { int isMaximized; int windowPosX; int windowPosY; int windowSizeWidth; int windowSizeHeight; }; struct PlatformOpengl { PObool isRun; void application; void window; void view; void dll; struct MouseDragged mouseDragged; struct WindowState windowState; void eventSource; void inputSource; void* inputSourceUnicodeData; PlatformCommandWindowClose CommandWindowClose; PlatformCommandWindowMinimize CommandWindowMinimize; PlatformCommandWindowMaximize CommandWindowMaximize; PlatformEventMouseKey EventMouseKey; PlatformEventMouseMove EventMouseMove; PlatformEventMouseDragged EventMouseDragged; PlatformEventScrollWheel EventScrollWheel; };
extern PObool PlatformOpenglInit(struct PlatformOpengl* obj); extern void PlatformOpenglRun(struct PlatformOpengl obj, int x, int y, int w, int h); extern void PlatformOpenglExit(struct PlatformOpengl** obj);
extern PObool PlatformInit(struct PlatformOpengl obj, int x, int y, int w, int h); extern void PlatformExit(struct PlatformOpengl obj); extern void PlatformPollEvents(struct PlatformOpengl obj); extern void PlatformSwicthBuffer(struct PlatformOpengl obj);
PObool PlatformOpenglInit(struct PlatformOpengl obj) { if (obj) { struct PlatformOpengl po = (struct PlatformOpengl)calloc(1, sizeof(struct PlatformOpengl)); obj = po; return POtrue; } return POfalse; } void PlatformOpenglRun(struct PlatformOpengl obj, int x, int y, int w, int h) { if (obj && PlatformInit(obj, x, y, w, h)) { obj->isRun = 1; while (obj->isRun) { PlatformPollEvents(obj); PlatformSwicthBuffer(obj); } PlatformExit(obj); } } void PlatformOpenglExit(struct PlatformOpengl obj) { if (obj && (obj)) { free(obj); *obj = 0; } }
import "CocoaWindow.h"
import "CocoaView.h"
void PlatformEventType(struct PlatformOpengl obj, NSEvent event) { char str = 0; NSEventType type = [event type]; switch((int)type) { case EventTypeLeftMouseDown: if(obj->EventMouseKey) { OpenGLView view = (OpenGLView)obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; obj->EventMouseKey(obj, MouseKeyLeft, MouseEventDown, (int)pos.x, (int)(rect.size.height - pos.y));
if(rect.size.height - pos.y < 32 && obj->windowState.isMaximized == 0) { NSWindow window = view.window; rect = [window convertRectToScreen:NSMakeRect(pos.x, pos.y, 1, 1)]; pos = window.frame.origin; obj->mouseDragged.xDelta = 0.0f; obj->mouseDragged.yDelta = 0.0f; obj->mouseDragged.xOrigin = pos.x; obj->mouseDragged.yOrigin = pos.y; obj->mouseDragged.xScreen = rect.origin.x; obj->mouseDragged.yScreen = rect.origin.y; obj->mouseDragged.isDrag = 1; } } break; case EventTypeLeftMouseUp: if(obj->EventMouseKey) { OpenGLView view = (OpenGLView)obj->view; const NSRect rect = [view frame]; const NSPoint pos = [event locationInWindow]; obj->mouseDragged.isDrag = 0; obj->EventMouseKey(obj, MouseKeyLeft, MouseEventUp, (int)pos.x, (int)(rect.size.height - pos.y)); } break; case EventTypeRightMouseDown: if(obj->EventMouseKey) { OpenGLView view = (OpenGLView)obj->view; const NSRect rect = [view frame]; const NSPoint pos = [event locationInWindow]; obj->EventMouseKey(obj, MouseKeyRight, MouseEventDown, (int)pos.x, (int)(rect.size.height - pos.y)); } break; case EventTypeRightMouseUp: if(obj->EventMouseKey) { OpenGLView view = (OpenGLView)obj->view; const NSRect rect = [view frame]; const NSPoint pos = [event locationInWindow]; obj->EventMouseKey(obj, MouseKeyRight, MouseEventUp, (int)pos.x, (int)(rect.size.height - pos.y)); } break; case EventTypeMouseMoved: if(obj->EventMouseMove) { float x, y; OpenGLView view = (OpenGLView)obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; x = pos.x; y = rect.size.height - pos.y; if(x < 0 || y < 0 || x > rect.size.width || y > rect.size.height) obj->EventMouseMove(obj, 0, (int)x, (int)y); else obj->EventMouseMove(obj, 1, (int)x, (int)y); } break; case EventTypeLeftMouseDragged: if(obj->EventMouseDragged) { float x, y; OpenGLView view = (OpenGLView)obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; x = pos.x; y = rect.size.height - pos.y; if(x < 0 || y < 0 || x > rect.size.width || y > rect.size.height) { obj->EventMouseDragged(obj, MouseKeyLeft, 0, (int)x, (int)y); } else { obj->EventMouseDragged(obj, MouseKeyLeft, 1, (int)x, (int)y); } if(obj->mouseDragged.isDrag) { NSWindow window = view.window; rect = [window convertRectToScreen:NSMakeRect(pos.x, pos.y, 1, 1)]; obj->mouseDragged.xDelta += rect.origin.x - obj->mouseDragged.xScreen; obj->mouseDragged.yDelta += rect.origin.y - obj->mouseDragged.yScreen; obj->mouseDragged.xScreen = rect.origin.x; obj->mouseDragged.yScreen = rect.origin.y; if (fabs(obj->mouseDragged.xDelta) > 1 || fabs(obj->mouseDragged.yDelta) > 1) { obj->mouseDragged.xOrigin += obj->mouseDragged.xDelta; obj->mouseDragged.yOrigin += obj->mouseDragged.yDelta; obj->mouseDragged.xDelta = 0.0; obj->mouseDragged.yDelta = 0.0; window.frameOrigin = NSMakePoint(obj->mouseDragged.xOrigin, obj->mouseDragged.yOrigin); } } } break; case EventTypeRightMouseDragged: if(obj->EventMouseDragged) { float x, y; OpenGLView view = (OpenGLView)obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; x = pos.x; y = rect.size.height - pos.y; if(x < 0 || y < 0 || x > rect.size.width || y > rect.size.height) obj->EventMouseDragged(obj, MouseKeyRight, 0, (int)x, (int)y); else obj->EventMouseDragged(obj, MouseKeyRight, 1, (int)x, (int)y); } break; case EventTypeMouseEntered: //str = "EventTypeMouseEntered"; break; case EventTypeMouseExited: //str = "EventTypeMouseExited"; break; case EventTypeKeyDown: str = "EventTypeKeyDown"; printf("keyCode:%d\n", event.keyCode); printf("characters:%ls\n", event.characters); break; case EventTypeKeyUp: str = "EventTypeKeyUp"; break; case EventTypeFlagsChanged: str = "EventTypeFlagsChanged"; break; case EventTypeAppKitDefined: str = "EventTypeAppKitDefined"; break; case EventTypeSystemDefined: str = "EventTypeSystemDefined"; break; case EventTypeApplicationDefined: str = "EventTypeApplicationDefined"; break; case EventTypePeriodic: str = "EventTypePeriodic"; break; case EventTypeCursorUpdate: str = "EventTypeCursorUpdate"; break; case EventTypeScrollWheel: if(obj->EventScrollWheel) { double deltaY = [event scrollingDeltaY]; if ([event hasPreciseScrollingDeltas]) deltaY = 0.1; if (deltaY > 0.0 || deltaY < 0) obj->EventScrollWheel(obj, (float)deltaY); } break; case EventTypeTabletPoint: str = "EventTypeTabletPoint"; break; case EventTypeTabletProximity: str = "EventTypeTabletProximity"; break; case EventTypeOtherMouseDown: if(obj->EventMouseKey) { OpenGLView view = obj->view; NSRect contentRect = [view frame]; NSPoint pos = [event locationInWindow]; obj->EventMouseKey(obj, MouseKeyOther, MouseEventDown, (int)pos.x, (int)(contentRect.size.height - pos.y)); } break; case EventTypeOtherMouseUp: if(obj->EventMouseKey) { OpenGLView view = obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; obj->EventMouseKey(obj, MouseKeyOther, MouseEventUp, (int)pos.x, (int)(rect.size.height - pos.y)); } break; case EventTypeOtherMouseDragged: if(obj->EventMouseDragged) { float x, y; OpenGLView* view = obj->view; NSRect rect = [view frame]; NSPoint pos = [event locationInWindow]; x = pos.x; y = rect.size.height - pos.y; if(x < 0 || y < 0 || x > rect.size.width || y > rect.size.height) obj->EventMouseDragged(obj, MouseKeyOther, 0, (int)x, (int)y); else obj->EventMouseDragged(obj, MouseKeyOther, 1, (int)x, (int)y); } break; default: str = "EventTypeUnknown"; break; } if(str) printf("%s\n", str); }