diff --git a/macarea/alt/area.h b/macarea/alt/area.h index 4575d5f0..16c72d57 100644 --- a/macarea/alt/area.h +++ b/macarea/alt/area.h @@ -2,6 +2,7 @@ #import #import #import "ui.h" +#import "uipriv_darwin.h" extern uiArea *newArea(uiAreaHandler *ah); diff --git a/macarea/alt/area.m b/macarea/alt/area.m index 85116a40..f1b73141 100644 --- a/macarea/alt/area.m +++ b/macarea/alt/area.m @@ -68,7 +68,13 @@ void addConstraint(NSView *view, NSString *constraint, NSDictionary *metrics, NS uiArea *libui_a; } - (id)initWithFrame:(NSRect)r area:(uiArea *)a; +- (uiModifiers)parseModifiers:(NSEvent *)e; - (void)doMouseEvent:(NSEvent *)e; +- (int)sendKeyEvent:(uiAreaKeyEvent *)ke; +- (int)doKeyDownUp:(NSEvent *)e up:(int)up; +- (int)doKeyDown:(NSEvent *)e; +- (int)doKeyUp:(NSEvent *)e; +- (int)doFlagsChanged:(NSEvent *)e; @end @interface areaView : NSView { @@ -116,6 +122,7 @@ struct uiArea { { CGContextRef c; uiAreaDrawParams dp; + areaView *av; c = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; dp.Context = newContext(c); @@ -130,7 +137,9 @@ struct uiArea { // TODO DPI - // TODO scroll position + av = (areaView *) [self superview]; + dp.HScrollPos = [av hscrollPos]; + dp.VScrollPos = [av vscrollPos]; (*(self->libui_a->ah->Draw))(self->libui_a->ah, self->libui_a, &dp); } @@ -145,6 +154,24 @@ struct uiArea { return YES; } +- (uiModifiers)parseModifiers:(NSEvent *)e +{ + NSEventModifierFlags mods; + uiModifiers m; + + m = 0; + mods = [e modifierFlags]; + if ((mods & NSControlKeyMask) != 0) + m |= uiModifierCtrl; + if ((mods & NSAlternateKeyMask) != 0) + m |= uiModifierAlt; + if ((mods & NSShiftKeyMask) != 0) + m |= uiModifierShift; + if ((mods & NSCommandKeyMask) != 0) + m |= uiModifierSuper; + return m; +} + // capture on drag is done automatically on OS X - (void)doMouseEvent:(NSEvent *)e { @@ -196,7 +223,7 @@ struct uiArea { break; } - me.Modifiers = 0; // TODO + me.Modifiers = [self parseModifiers:e]; pmb = [NSEvent pressedMouseButtons]; me.Held1To64 = 0; @@ -245,8 +272,90 @@ mouseEvent(otherMouseUp) // even if I invoke the task switcher and switch processes, the mouse grab will still be held until I let go of all buttons // therefore, no DragBroken() +- (int)sendKeyEvent:(uiAreaKeyEvent *)ke +{ + return (*(self->libui_a->ah->KeyEvent))(self->libui_a->ah, self->libui_a, ke); +} + +- (int)doKeyDownUp:(NSEvent *)e up:(int)up +{ + uiKeyEvent ke; + + ke.Key = 0; + ke.ExtKey = 0; + ke.Modifier = 0; + + ke.Modifiers = [self parseModifiers:e]; + + ke.Up = up; + + if (!fromKeycode([e keyCode], &ke)) + return 0; + return [self sendKeyEvent:&ke]; +} + +- (int)doKeyDown:(NSEvent *)e +{ + return [self doKeyDownUp:e up:0]; +} + +- (int)doKeyUp:(NSEvent *)e +{ + return [self doKeyDownUp:e up:1]; +} + +- (int)doFlagsChanged:(NSEvent *)e +{ + uiAreaKeyEvent ke; + uiModifiers whichmod; + + ke.Key = 0; + ke.ExtKey = 0; + + // Mac OS X sends this event on both key up and key down. + // Fortunately -[e keyCode] IS valid here, so we can simply map from key code to Modifiers, get the value of [e modifierFlags], and check if the respective bit is set or not — that will give us the up/down state + if (!keycodeModifier([e keyCode], &whichmod)) + return 0; + ke.Modifier = whichmod; + ke.Modifiers = [self parseModifiers:e]; + ke.Up = (ke.Modifiers & ke.Modifier) == 0; + // and then drop the current modifier from Modifiers + ke.Modifiers &= ~ke.Modifier; + return [self sendKeyEvent:&ke]; +} + @end +// called by subclasses of -[NSApplication sendEvent:] +// by default, NSApplication eats some key events +// this prevents that from happening with uiArea +// see http://stackoverflow.com/questions/24099063/how-do-i-detect-keyup-in-my-nsview-with-the-command-key-held and http://lists.apple.com/archives/cocoa-dev/2003/Oct/msg00442.html +int sendAreaEvents(NSEvent *e) +{ + NSEventType type; + id focused; + areaDrawingView *view; + + type = [e type]; + if (type != NSKeyDown && type != NSKeyUp && type != NSFlagsChanged) + return 0; + focused = [[e window] firstResponder]; + if (focused == nil) + return 0; + if (![focused isKindOfClass:[areaDrawingView class]]) + return 0; + view = (areaDrawingView *) focused; + switch (type) { + case NSKeyDown: + return [view doKeyDown:e]; + case NSKeyUp: + return [view doKeyUp:e]; + case NSFlagsChanged: + return [view doFlagsChanged:e]; + } + return 0; +} + @implementation areaView - (id)initWithFrame:(NSRect)r area:(uiArea *)a diff --git a/macarea/alt/main.m b/macarea/alt/main.m index a1a121ed..b4dffa9d 100644 --- a/macarea/alt/main.m +++ b/macarea/alt/main.m @@ -145,7 +145,7 @@ static int handlerKeyEvent(uiAreaHandler *ah, uiArea *a, uiAreaKeyEvent *e) k, (int) e->ExtKey, (int) e->Modifier, - (int) e->Modifiers; + (int) e->Modifiers, e->Up); return 0; } diff --git a/macarea/alt/uipriv_darwin.h b/macarea/alt/uipriv_darwin.h new file mode 100644 index 00000000..a4ccde37 --- /dev/null +++ b/macarea/alt/uipriv_darwin.h @@ -0,0 +1,6 @@ +// area.m +extern int sendAreaEvents(NSEvent *e); + +// events.m +extern BOOL fromKeycode(unsigned short keycode, uiAreaKeyEvent *ke); +extern BOOL keycodeModifier(unsigned short keycode, uiModifiers *mod);