diff --git a/include/Mw/LowLevel/Cocoa.h b/include/Mw/LowLevel/Cocoa.h index 91679db..35bc564 100644 --- a/include/Mw/LowLevel/Cocoa.h +++ b/include/Mw/LowLevel/Cocoa.h @@ -96,6 +96,7 @@ - (void)setX:(int)x Y:(int)y; - (void)setW:(int)w H:(int)h; - (int)pending; +- (void)eventProcess:(NSEvent *)ev; - (void)getNextEvent; - (void)setTitle:(const char *)title; - (void)drawPixmap:(MwLLPixmap)pixmap rect:(MwRect *)rect; @@ -120,6 +121,8 @@ - (NSWindow *)parentWindow; - (NSView *)getView; +- (NSWindow *)getWindow; +- (MilskoFakePointer *)getHandle; @end #define OBJC(x) x diff --git a/src/backend/cocoa.m b/src/backend/cocoa.m index 0b230eb..7c566a8 100644 --- a/src/backend/cocoa.m +++ b/src/backend/cocoa.m @@ -125,7 +125,9 @@ static CGPoint pointFlip(CGPoint point) { [p->window addChildWindow:c->window ordered:NSWindowAbove]; [c->window setHasShadow:MwFALSE]; } else { - // [c->application activateIgnoringOtherApps:true]; + [c->application setActivationPolicy:NSApplicationActivationPolicyRegular]; + [c->application activateIgnoringOtherApps:true]; + [c->window makeFirstResponder:c->view]; } c->view = [[MilskoCocoaView alloc] initWithFrame:c->rect]; @@ -229,144 +231,586 @@ static CGPoint pointFlip(CGPoint point) { [self->window setFrame:frame display:YES animate:false]; }; - (int)pending { - self->lastEvent = - [self->application nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue:YES]; if (_forceRender) { _forceRender = MwFALSE; return 1; } + + self->lastEvent = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; return self->lastEvent != NULL; }; + - (void)getNextEvent { - if (self->lastEvent != nil) { - NSWindow *win = [self->lastEvent window]; - NSWindow *parentWindow = [self parentWindow]; - MwLL h; + int i; + NSEvent *ev; - if ([win contentView].subviews.count == 0) { - NSLog(@"[WARNING] no subviews on this window, cannot process events.\n"); - return; - } + [self eventProcess:lastEvent]; - h = [((MilskoFakePointer *)[win contentView].subviews[0]) pointer]; - switch (self->lastEvent.type) { - case NSEventTypeLeftMouseDown: - case NSEventTypeRightMouseDown: - case NSEventTypeOtherMouseDown: - case NSEventTypeLeftMouseUp: - case NSEventTypeRightMouseUp: - case NSEventTypeOtherMouseUp: { - MwLLMouse mouse = {}; - MwBool isDown = MwTRUE; - CGPoint mousePoint = pointFlip([lastEvent locationInWindow]); - switch (self->lastEvent.type) { - case NSEventTypeLeftMouseUp: - isDown = MwFALSE; - case NSEventTypeLeftMouseDown: - mouse.button = MwLLMouseLeft; - break; - case NSEventTypeRightMouseUp: - isDown = MwFALSE; - case NSEventTypeRightMouseDown: - mouse.button = MwLLMouseRight; - break; - case NSEventTypeOtherMouseUp: - isDown = MwFALSE; - case NSEventTypeOtherMouseDown: - mouse.button = MwLLMouseMiddle; - break; - default: - break; - } - mouse.point.x = mousePoint.x; - mouse.point.y = mousePoint.y; + while ((ev = [self->window nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES])) { + [self eventProcess:ev]; + } +}; - if (isDown) { - MwLLDispatch(h, down, &mouse); - } else { - MwLLDispatch(h, up, &mouse); - } - break; - } - - break; - case NSEventTypeMouseMoved: { - MwPoint pos; - pos.x = [lastEvent locationInWindow].x; - pos.y = [win contentRectForFrameRect:win.frame].size.height - - [lastEvent locationInWindow].y; - MwLLDispatch(h, move, &pos); - break; - } - case NSEventTypeLeftMouseDragged: - MwLLDispatch(h, focus_in, NULL); - break; - case NSEventTypeRightMouseDragged: - MwLLDispatch(h, focus_out, NULL); - break; - case NSEventTypeMouseEntered: - break; - case NSEventTypeMouseExited: - break; - case NSEventTypeKeyDown: - [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; - break; - case NSEventTypeKeyUp: - [win interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; - break; - case NSEventTypeFlagsChanged: - break; - case NSEventTypeAppKitDefined: - break; - case NSEventTypeSystemDefined: - break; - case NSEventTypeApplicationDefined: - break; - case NSEventTypePeriodic: - break; - case NSEventTypeCursorUpdate: - break; - case NSEventTypeScrollWheel: - break; - case NSEventTypeTabletPoint: - break; - case NSEventTypeTabletProximity: - break; - break; - case NSEventTypeOtherMouseDragged: - break; - case NSEventTypeGesture: - break; - case NSEventTypeMagnify: - break; - case NSEventTypeSwipe: - break; - case NSEventTypeRotate: - break; - case NSEventTypeBeginGesture: - break; - case NSEventTypeEndGesture: - break; - case NSEventTypeSmartMagnify: - break; - case NSEventTypeQuickLook: - break; - case NSEventTypePressure: - break; - case NSEventTypeDirectTouch: - break; - case NSEventTypeChangeMode: - break; - }; - // printf("got event: %ld\n", self->lastEvent.type); - [self->application sendEvent:self->lastEvent]; +- (void)eventProcess:(NSEvent *)ev { + NSWindow *win = [ev window]; + NSWindow *parentWindow = [self parentWindow]; + MwLL h; + MwBool doSendEvent = MwTRUE; + if (!win) { + return; } - [self->view setNeedsDisplay:true]; -}; + if ([win contentView].subviews.count == 0) { + printf("no subviews on %p\n", win); + return; + } else { + h = [((MilskoFakePointer *)[win contentView].subviews[0]) pointer]; + } + + switch (ev.type) { + case NSEventTypeLeftMouseDown: + case NSEventTypeRightMouseDown: + case NSEventTypeOtherMouseDown: + case NSEventTypeLeftMouseUp: + case NSEventTypeRightMouseUp: + case NSEventTypeOtherMouseUp: { + MwLLMouse mouse = {}; + MwBool isDown = MwTRUE; + CGPoint mousePoint = pointFlip([ev locationInWindow]); + switch (ev.type) { + case NSEventTypeLeftMouseUp: + isDown = MwFALSE; + case NSEventTypeLeftMouseDown: + mouse.button = MwLLMouseLeft; + break; + case NSEventTypeRightMouseUp: + isDown = MwFALSE; + case NSEventTypeRightMouseDown: + mouse.button = MwLLMouseRight; + break; + case NSEventTypeOtherMouseUp: + isDown = MwFALSE; + case NSEventTypeOtherMouseDown: + mouse.button = MwLLMouseMiddle; + break; + default: + break; + } + mouse.point.x = mousePoint.x; + mouse.point.y = mousePoint.y; + + if (isDown) { + MwLLDispatch(h, down, &mouse); + } else { + MwLLDispatch(h, up, &mouse); + } + break; + } + case NSEventTypeLeftMouseDragged: + case NSEventTypeRightMouseDragged: + case NSEventTypeOtherMouseDragged: + case NSEventTypeMouseMoved: { + MwPoint pos; + pos.x = [ev locationInWindow].x; + pos.y = [win contentRectForFrameRect:win.frame].size.height - + [ev locationInWindow].y; + MwLLDispatch(h, move, &pos); + break; + } + case NSEventTypeMouseEntered: + MwLLDispatch(h, focus_in, NULL); + break; + case NSEventTypeMouseExited: + MwLLDispatch(h, focus_out, NULL); + break; + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: { + int ch; + enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C, + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightCommand = 0x36, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E + }; + // [view.nextResponder + // interpretKeyEvents:[NSArray arrayWithObject:lastEvent]]; + switch (ev.keyCode) { + case kVK_ANSI_A: + ch = 'a'; + break; + case kVK_ANSI_B: + ch = 'b'; + break; + case kVK_ANSI_C: + ch = 'c'; + break; + case kVK_ANSI_D: + ch = 'd'; + break; + case kVK_ANSI_E: + ch = 'e'; + break; + case kVK_ANSI_F: + ch = 'f'; + break; + case kVK_ANSI_G: + ch = 'g'; + break; + case kVK_ANSI_H: + ch = 'h'; + break; + case kVK_ANSI_I: + ch = 'i'; + break; + case kVK_ANSI_J: + ch = 'j'; + break; + case kVK_ANSI_K: + ch = 'k'; + break; + case kVK_ANSI_L: + ch = 'l'; + break; + case kVK_ANSI_M: + ch = 'm'; + break; + case kVK_ANSI_N: + ch = 'n'; + break; + case kVK_ANSI_O: + ch = 'o'; + break; + case kVK_ANSI_P: + ch = 'p'; + break; + case kVK_ANSI_Q: + ch = 'q'; + break; + case kVK_ANSI_R: + ch = 'r'; + break; + case kVK_ANSI_S: + ch = 's'; + break; + case kVK_ANSI_T: + ch = 't'; + break; + case kVK_ANSI_U: + ch = 'u'; + break; + case kVK_ANSI_V: + ch = 'v'; + break; + case kVK_ANSI_W: + ch = 'w'; + break; + case kVK_ANSI_X: + ch = 'x'; + break; + case kVK_ANSI_Y: + ch = 'y'; + break; + case kVK_ANSI_Z: + ch = 'z'; + break; + case kVK_ANSI_0: + ch = '0'; + break; + case kVK_ANSI_1: + ch = '1'; + break; + case kVK_ANSI_2: + ch = '2'; + break; + case kVK_ANSI_3: + ch = '3'; + break; + case kVK_ANSI_4: + ch = '4'; + break; + case kVK_ANSI_5: + ch = '5'; + break; + case kVK_ANSI_6: + ch = '6'; + break; + case kVK_ANSI_7: + ch = '7'; + break; + case kVK_ANSI_8: + ch = '8'; + break; + case kVK_ANSI_9: + ch = '9'; + break; + + // case kVK_ANSI_Keypad0: + // ch = MwLLKey; + // break; + // case kVK_ANSI_Keypad1: + // ch = keypad1; + // break; + // case kVK_ANSI_Keypad2: + // ch = keypad2; + // break; + // case kVK_ANSI_Keypad3: + // ch = keypad3; + // break; + // case kVK_ANSI_Keypad4: + // ch = keypad4; + // break; + // case kVK_ANSI_Keypad5: + // ch = keypad5; + // break; + // case kVK_ANSI_Keypad6: + // ch = keypad6; + // break; + // case kVK_ANSI_Keypad7: + // ch = keypad7; + // break; + // case kVK_ANSI_Keypad8: + // ch = keypad8; + // break; + // case kVK_ANSI_Keypad9: + // ch = keypad9; + // break; + // case kVK_ANSI_KeypadClear: + // ch = keypadClear; + // break; + // case kVK_ANSI_KeypadDivide: + // ch = keypadDivide; + // break; + // case kVK_ANSI_KeypadEnter: + // ch = keypadEnter; + // break; + // case kVK_ANSI_KeypadEquals: + // ch = keypadEquals; + // break; + // case kVK_ANSI_KeypadMinus: + // ch = keypadMinus; + // break; + // case kVK_ANSI_KeypadPlus: + // ch = keypadPlus; + // break; + // case kVK_PageDown: + // ch = MwLLKey; + // break; + // case kVK_PageUp: + // ch = pageUp; + // break; + // case kVK_End: + // ch = end; + // break; + // case kVK_Home: + // ch = home; + // break; + + // case kVK_F1: + // ch = f1; + // break; + // case kVK_F2: + // ch = f2; + // break; + // case kVK_F3: + // ch = f3; + // break; + // case kVK_F4: + // ch = f4; + // break; + // case kVK_F5: + // ch = f5; + // break; + // case kVK_F6: + // ch = f6; + // break; + // case kVK_F7: + // ch = f7; + // break; + // case kVK_F8: + // ch = f8; + // break; + // case kVK_F9: + // ch = f9; + // break; + // case kVK_F10: + // ch = f10; + // break; + // case kVK_F11: + // ch = f11; + // break; + // case kVK_F12: + // ch = f12; + // break; + // case kVK_F13: + // ch = f13; + // break; + // case kVK_F14: + // ch = f14; + // break; + // case kVK_F15: + // ch = f15; + // break; + // case kVK_F16: + // ch = f16; + // break; + // case kVK_F17: + // ch = f17; + // break; + // case kVK_F18: + // ch = f18; + // break; + // case kVK_F19: + // ch = f19; + // break; + // case kVK_F20: + // ch = f20; + // break; + // case kVK_ANSI_KeypadDecimal: + // ch = decimal; + // break; + + case kVK_ANSI_Quote: + ch = '\"'; + break; + case kVK_ANSI_Grave: + ch = '`'; + break; + case kVK_ANSI_Backslash: + ch = '/'; + break; + case kVK_ANSI_Comma: + ch = ','; + break; + // case kVK_Delete: + // ch = delete; + // break; + // case kVK_ANSI_Equal: + // ch = equals; + // break; + case kVK_Escape: + ch = MwLLKeyEscape; + break; + // case kVK_ANSI_LeftBracket: + // ch = leftBracket; + // break; + // case kVK_ANSI_Minus: + // ch = minus; + // break; + // case kVK_ANSI_KeypadMultiply: + // ch = multiply; + // break; + // case kVK_ANSI_Period: + // ch = period; + // break; + case kVK_Return: + ch = MwLLKeyEnter; + break; + // case kVK_ANSI_RightBracket: + // ch = rightBracket; + // break; + case kVK_ANSI_Semicolon: + ch = ';'; + break; + case kVK_ANSI_Slash: + ch = '\\'; + break; + case kVK_Space: + ch = ' '; + break; + // case kVK_Tab: + // ch = tab; + // break; + + // case kVK_Mute: + // ch = mute; + // break; + // case kVK_VolumeDown: + // ch = volumeDown; + // break; + // case kVK_VolumeUp: + // ch = volumeUp; + // break; + + // case kVK_Command: + // ch = MwLLKey; + // break; + // case kVK_RightCommand: + // ch = rightCommand; + // break; + case kVK_Control: + ch = MwLLKeyControl; + break; + case kVK_RightControl: + ch = MwLLKeyControl; + break; + // case kVK_Function: + // ch = function; + // break; + // case kVK_Option: + // ch = option; + // break; + // case kVK_RightOption: + // ch = rightOption; + // break; + case kVK_Shift: + ch = MwLLKeyLeftShift; + break; + case kVK_RightShift: + ch = MwLLKeyRightShift; + break; + + case kVK_DownArrow: + ch = MwLLKeyDown; + break; + case kVK_LeftArrow: + ch = MwLLKeyLeft; + break; + case kVK_RightArrow: + ch = MwLLKeyRight; + break; + case kVK_UpArrow: + ch = MwLLKeyUp; + break; + } + switch (ev.type) { + case NSEventTypeKeyDown: + MwLLDispatch(h, key, &ch); + break; + case NSEventTypeKeyUp: + MwLLDispatch(h, key_released, &ch); + break; + default: + break; + } + doSendEvent = MwFALSE; + break; + } + case NSEventTypeCursorUpdate: + break; + case NSEventTypeScrollWheel: + break; + default: + break; + }; + if (doSendEvent) { + [win sendEvent:ev]; + } +} - (void)setTitle:(const char *)title { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -465,6 +909,13 @@ static CGPoint pointFlip(CGPoint point) { - (NSView *)getView { return view; } +- (NSWindow *)getWindow { + return window; +} + +- (MilskoFakePointer *)getHandle { + return handle; +} @end @implementation MilskoCocoaView @@ -530,23 +981,6 @@ static CGPoint pointFlip(CGPoint point) { - (void)displayRect:(NSRect)rect { }; -@end - -@implementation MilskoFakePointer -- (void)setPointer:(void *)pointer { - self.frame = *(NSRect *)&pointer; - self->ptr = pointer; -}; -- (void *)pointer { - return self->ptr; -}; - -- (void)drawRect:(NSRect)dirtyRect { - /* explicitly do nothing */ -} - -- (void)destroy { -} @end @@ -567,11 +1001,37 @@ static CGPoint pointFlip(CGPoint point) { - (void)windowDidResize:(NSNotification *)notification { } +// This will close/terminate the application when the main window is closed. +- (void)windowWillClose:(NSNotification *)notification { + // MilskoCocoa *window = notification.object; + // MwLL handle = [window getHandle].pointer; + // MwLLDispatch(handle, close, NULL); + [NSApp terminate:nil]; +} + - (instancetype)initWithWin:(NSWindow *)win { self->w = win; return self; } +@end + +@implementation MilskoFakePointer +- (void)setPointer:(void *)pointer { + self.frame = *(NSRect *)&pointer; + self->ptr = pointer; +}; +- (void *)pointer { + return self->ptr; +}; + +- (void)drawRect:(NSRect)dirtyRect { + /* explicitly do nothing */ +} + +- (void)destroy { +} + @end static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { MwLL r; diff --git a/src/widget/opengl_cocoa.m b/src/widget/opengl_cocoa.m index 88e17e3..c33e375 100644 --- a/src/widget/opengl_cocoa.m +++ b/src/widget/opengl_cocoa.m @@ -1,3 +1,4 @@ +#include "Mw/BaseTypes.h" #include "Mw/Core.h" #include "Mw/StringDefs.h" #include @@ -28,10 +29,8 @@ static int create(MwWidget handle) { printf("%d %d\n", width, height); - MacOpenGLWidget *o = r = [[MacOpenGLWidget alloc] + handle->internal = [[MacOpenGLWidget alloc] initWithView:[handle->lowlevel->cocoa.real getView]]; - - handle->internal = r; handle->lowlevel->common.copy_buffer = 0; MwSetDefault(handle); @@ -96,6 +95,19 @@ static void func_handler(MwWidget handle, const char *name, void *out, [self->glc makeCurrentContext]; }; - (void)swapBuffer { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + 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]; + [pool release]; + [self->glc flushBuffer]; }; - (void *)getProcAddressWithName:(const char *)name {