Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Fixes issue #1259 - Added modifier key handling for macosx backend #1841

Merged
merged 3 commits into from

4 participants

@cimarronm
Collaborator

Add modifier key handling to key event handlers for macosx backend. Clean up code to use NS foundation constants for keys and simplified convertKeyEvent selector

@pelson
Collaborator

Thanks for submitting this @cimarronm - its great to have your contribution!

@mdehoon is our resident OSX backend expert, so it would be good to have his eyes on this change. I'll build this on my own machine this weekend to give it a whirl. @dmcdougall - I know you're also a ObjC wizz - any comments?

@mdehoon

@cimarronm , thanks for the contribution. I'll have a look over the next couple of days.

@dmcdougall
Collaborator

This will break builds for older Macs due to the use of NSDictionary literals. To support older Macs, an approach that's pre-ObjectiveC-2.0 friendly will be needed.

@dmcdougall
Collaborator

I've tried this and it seems to work, at least I tried to close the window using a keyboard shortcut and it worked. I had to use rather than , though. It'd be nice to have the keyboard shortcuts consistent with native OS X applications. Having said that, it is consistent with X window manager applications, and with the other backends, so I'd be happy for this to go in.

A portable approach to the dictionary literal issue could possibility utilise this. I think that would work with Objective-C pre 2.0. Perhaps @mdehoon would also be able to advise in this regard.

@cimarronm
Collaborator

I'll update my branch to not use objc2.0 literals for the pre 2.0 compiler support...code looks much cleaner with the new literals though ;-)

Also, to change to the native OS X feel for closing the window, you can change the keymap.quit to cmd+w (instead of default ctrl+w) in your matplotlibrc. If it makes sense, maybe we could modify the matplotlibrc template to default to cmd+w if the macosx backend is set upon build/install?

@pelson
Collaborator

@cimarronm - I think the order of the modifier keys is important: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_tkagg.py#L460

So if I press ctrl+alt+cmd<a key> the string should be the same on all backends. I believe (untested) as it stands, this change would return cmd+alt+ctrl+<a key>. If I'm correct, would you mind changing the order of your if statements?

I also believe that (at least on the TkAgg backend) pressing ctrl+shift+a actually results in an event with the following key ctrl+A - I'm not sure we had much choice about this with Tk. Ideally it would be nice to be consistent on this front, though I suspect that would mean a whole host of complexities relating to key mappings shudder. Perhaps save this one for another PR? @mdboom thoughts?

For reference see http://matplotlib.org/api/backend_bases_api.html#matplotlib.backend_bases.KeyEvent

@mdehoon

@dmcdougall , @cimarronm : With respect to the dictionary literal issue, it looks like @cimarronm 's updated code solves it. I'd like to try it on Mac OS X 10.5, just to make sure; I can do so in a few days when I have access to that machine.

With respect to cmd+w vs. ctrl+w for closing the window, I think that by default the Mac OS X backend should follow the native Mac OS X behavior, not the X windows behavior.

@pelson
Collaborator

With respect to cmd+w vs. ctrl+w for closing the window, I think that by default the Mac OS X backend should follow the native Mac OS X behavior, not the X windows behavior.

From memory, does cmd+w (or was it cmd+q) not close the window anyway on OSX?

@mdehoon

@pelson : cmd+w, cmd+q, ctrl+w, ctrl+q do nothing on OSX 10.8 with the current matplotlib.

@cimarronm
Collaborator

@pelson - The order should be correct. Each statement is appending so you would get ctrl+alt+cmd+. I just tested it to print out what I get when I press the modifiers together and get
1. (all except shift with a) ctrl+alt+cmd+a
2. (including shift) ctrl+alt+cmd+shift+A

Should I eliminate the shift modifier?

@pelson
Collaborator

@pelson - The order should be correct.

Apologies for that - I agree, it all looks good from that perspective.

If the key is coming through after being shifted (e.g. we have A and not a), then I think consistency suggests we can remove the shift key from the string altogether.

@mdehoon

I tried this on Mac OS X 10.5. It compiles and seems to work fine.

@dmcdougall dmcdougall merged commit 1c2e2be into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 63 additions and 53 deletions.
  1. +63 −53 src/_macosx.m
View
116 src/_macosx.m
@@ -391,7 +391,7 @@ - (const char*)convertKeyEvent:(NSEvent*)event;
- (void)keyDown:(NSEvent*)event;
- (void)keyUp:(NSEvent*)event;
- (void)scrollWheel:(NSEvent *)event;
-- (void)flagsChanged:(NSEvent*)event;
+//- (void)flagsChanged:(NSEvent*)event;
@end
@interface ScrollableButton : NSButton
@@ -5439,66 +5439,73 @@ - (void)removeRubberband
rubberband = NSZeroRect;
}
+
+
- (const char*)convertKeyEvent:(NSEvent*)event
{
- NSString* text = [event charactersIgnoringModifiers];
- unichar uc = [text characterAtIndex:0];
- int i = (int)uc;
- if ([event modifierFlags] & NSNumericPadKeyMask)
- {
- if (i > 256)
- {
- if (uc==NSLeftArrowFunctionKey) return "left";
- else if (uc==NSUpArrowFunctionKey) return "up";
- else if (uc==NSRightArrowFunctionKey) return "right";
- else if (uc==NSDownArrowFunctionKey) return "down";
- else if (uc==NSF1FunctionKey) return "f1";
- else if (uc==NSF2FunctionKey) return "f2";
- else if (uc==NSF3FunctionKey) return "f3";
- else if (uc==NSF4FunctionKey) return "f4";
- else if (uc==NSF5FunctionKey) return "f5";
- else if (uc==NSF6FunctionKey) return "f6";
- else if (uc==NSF7FunctionKey) return "f7";
- else if (uc==NSF8FunctionKey) return "f8";
- else if (uc==NSF9FunctionKey) return "f9";
- else if (uc==NSF10FunctionKey) return "f10";
- else if (uc==NSF11FunctionKey) return "f11";
- else if (uc==NSF12FunctionKey) return "f12";
- else if (uc==NSScrollLockFunctionKey) return "scroll_lock";
- else if (uc==NSBreakFunctionKey) return "break";
- else if (uc==NSInsertFunctionKey) return "insert";
- else if (uc==NSDeleteFunctionKey) return "delete";
- else if (uc==NSHomeFunctionKey) return "home";
- else if (uc==NSEndFunctionKey) return "end";
- else if (uc==NSPageUpFunctionKey) return "pageup";
- else if (uc==NSPageDownFunctionKey) return "pagedown";
- }
- else if ((char)uc == '.') return "dec";
- }
-
- switch (i)
- {
- case 127: return "backspace";
- case 13: return "enter";
- case 3: return "enter";
- case 27: return "escape";
- default:
- {
- static char s[2];
- s[0] = (char)uc;
- s[1] = '\0';
- return (const char*)s;
- }
- }
+ NSDictionary* specialkeymappings = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"left", [NSNumber numberWithUnsignedLong:NSLeftArrowFunctionKey],
+ @"right", [NSNumber numberWithUnsignedLong:NSRightArrowFunctionKey],
+ @"up", [NSNumber numberWithUnsignedLong:NSUpArrowFunctionKey],
+ @"down", [NSNumber numberWithUnsignedLong:NSDownArrowFunctionKey],
+ @"f1", [NSNumber numberWithUnsignedLong:NSF1FunctionKey],
+ @"f2", [NSNumber numberWithUnsignedLong:NSF2FunctionKey],
+ @"f3", [NSNumber numberWithUnsignedLong:NSF3FunctionKey],
+ @"f4", [NSNumber numberWithUnsignedLong:NSF4FunctionKey],
+ @"f5", [NSNumber numberWithUnsignedLong:NSF5FunctionKey],
+ @"f6", [NSNumber numberWithUnsignedLong:NSF6FunctionKey],
+ @"f7", [NSNumber numberWithUnsignedLong:NSF7FunctionKey],
+ @"f8", [NSNumber numberWithUnsignedLong:NSF8FunctionKey],
+ @"f9", [NSNumber numberWithUnsignedLong:NSF9FunctionKey],
+ @"f10", [NSNumber numberWithUnsignedLong:NSF10FunctionKey],
+ @"f11", [NSNumber numberWithUnsignedLong:NSF11FunctionKey],
+ @"f12", [NSNumber numberWithUnsignedLong:NSF12FunctionKey],
+ @"f13", [NSNumber numberWithUnsignedLong:NSF13FunctionKey],
+ @"f14", [NSNumber numberWithUnsignedLong:NSF14FunctionKey],
+ @"f15", [NSNumber numberWithUnsignedLong:NSF15FunctionKey],
+ @"f16", [NSNumber numberWithUnsignedLong:NSF16FunctionKey],
+ @"f17", [NSNumber numberWithUnsignedLong:NSF17FunctionKey],
+ @"f18", [NSNumber numberWithUnsignedLong:NSF18FunctionKey],
+ @"f19", [NSNumber numberWithUnsignedLong:NSF19FunctionKey],
+ @"scroll_lock", [NSNumber numberWithUnsignedLong:NSScrollLockFunctionKey],
+ @"break", [NSNumber numberWithUnsignedLong:NSBreakFunctionKey],
+ @"insert", [NSNumber numberWithUnsignedLong:NSInsertFunctionKey],
+ @"delete", [NSNumber numberWithUnsignedLong:NSDeleteFunctionKey],
+ @"home", [NSNumber numberWithUnsignedLong:NSHomeFunctionKey],
+ @"end", [NSNumber numberWithUnsignedLong:NSEndFunctionKey],
+ @"pagedown", [NSNumber numberWithUnsignedLong:NSPageDownFunctionKey],
+ @"pageup", [NSNumber numberWithUnsignedLong:NSPageUpFunctionKey],
+ @"backspace", [NSNumber numberWithUnsignedLong:NSDeleteCharacter],
+ @"enter", [NSNumber numberWithUnsignedLong:NSEnterCharacter],
+ @"tab", [NSNumber numberWithUnsignedLong:NSTabCharacter],
+ @"enter", [NSNumber numberWithUnsignedLong:NSCarriageReturnCharacter],
+ @"backtab", [NSNumber numberWithUnsignedLong:NSBackTabCharacter],
+ @"escape", [NSNumber numberWithUnsignedLong:27],
+ nil
+ ];
+
+ NSMutableString* returnkey = [NSMutableString string];
+ if ([event modifierFlags] & NSControlKeyMask)
+ [returnkey appendString:@"ctrl+" ];
+ if ([event modifierFlags] & NSAlternateKeyMask)
+ [returnkey appendString:@"alt+" ];
+ if ([event modifierFlags] & NSCommandKeyMask)
+ [returnkey appendString:@"cmd+" ];
+
+ unichar uc = [[event charactersIgnoringModifiers] characterAtIndex:0];
+ NSString* specialchar = [specialkeymappings objectForKey:[NSNumber numberWithUnsignedLong:uc]];
+ if (specialchar)
+ [returnkey appendString:specialchar];
+ else
+ [returnkey appendString:[event charactersIgnoringModifiers]];
- return NULL;
+ return [returnkey UTF8String];
}
- (void)keyDown:(NSEvent*)event
{
PyObject* result;
const char* s = [self convertKeyEvent: event];
- /* TODO: Handle ctrl, alt, super modifiers. qt4 has implemented these. */
PyGILState_STATE gstate = PyGILState_Ensure();
if (s==NULL)
{
@@ -5520,7 +5527,6 @@ - (void)keyUp:(NSEvent*)event
{
PyObject* result;
const char* s = [self convertKeyEvent: event];
- /* TODO: Handle ctrl, alt, super modifiers. qt4 has implemented these. */
PyGILState_STATE gstate = PyGILState_Ensure();
if (s==NULL)
{
@@ -5561,6 +5567,9 @@ - (void)scrollWheel:(NSEvent*)event
PyGILState_Release(gstate);
}
+/* This is all wrong. Address of pointer is being passed instead of pointer, keynames don't
+ match up with what the front-end and does the front-end even handle modifier keys by themselves?
+
- (void)flagsChanged:(NSEvent*)event
{
const char *s = NULL;
@@ -5580,6 +5589,7 @@ - (void)flagsChanged:(NSEvent*)event
PyGILState_Release(gstate);
}
+ */
@end
@implementation ScrollableButton
Something went wrong with that request. Please try again.