ecore_cocoa: fix keyboad event handling

This patch allows to interpret correctly several types of key combinations:
  - alt keys : € œ ¬
  - dead keys : ä ë
  - dead keys (bis, they are handled differently) : ~ ã
  - control keys: ^C ^A
  - page up/ page down

@fix

Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
This commit is contained in:
pierre lamot 2015-02-19 16:34:33 +01:00 committed by Cedric BAIL
parent d9830a199f
commit ae4389a7bd
2 changed files with 79 additions and 75 deletions

View File

@ -240,8 +240,8 @@ static const struct _ecore_cocoa_keys_s keystable[] =
{ NSInsertFunctionKey, "Insert", "" },
{ NSHomeFunctionKey, "Home", "" },
{ NSEndFunctionKey, "End", "" },
{ NSPageUpFunctionKey, "Page_Up", "" },
{ NSPageDownFunctionKey, "Page_Down", "" },
{ NSPageUpFunctionKey, "Prior", "" },
{ NSPageDownFunctionKey, "Next", "" },
{ NSDeleteFunctionKey, "Delete", "\010"},
{ NSF1FunctionKey, "F1", "" },

View File

@ -86,7 +86,7 @@ _ecore_cocoa_event_modifiers(unsigned int mod)
if(mod & NSShiftKeyMask) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
if(mod & NSControlKeyMask) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
if(mod & NSAlternateKeyMask) modifiers |= ECORE_EVENT_MODIFIER_ALT;
if(mod & NSAlternateKeyMask) modifiers |= ECORE_EVENT_MODIFIER_ALTGR;
if(mod & NSCommandKeyMask) modifiers |= ECORE_EVENT_MODIFIER_WIN;
if(mod & NSNumericPadKeyMask) modifiers |= ECORE_EVENT_LOCK_NUM;
@ -94,6 +94,63 @@ _ecore_cocoa_event_modifiers(unsigned int mod)
return modifiers;
}
static inline Ecore_Event_Key*
_ecore_cocoa_event_key(NSEvent *event, int keyType)
{
static Eina_Bool compose = EINA_FALSE;
static NSText *edit;
unsigned int i;
Ecore_Event_Key *ev;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSString *keychar = [event charactersIgnoringModifiers];
NSString *keycharRaw = [event characters];
ev = calloc(1, sizeof (Ecore_Event_Key));
if (!ev) return NULL;
if (compose && keyType == NSKeyDown)
{
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
compose=EINA_FALSE;
}
ev->modifiers = _ecore_cocoa_event_modifiers([event modifierFlags]);
ev->keycode = event.keyCode;
ev->string = [keycharRaw cStringUsingEncoding:NSUTF8StringEncoding];
ev->compose = ev->string;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
if ([keychar length] > 0)
{
for (i = 0; i < sizeof (keystable) / sizeof (struct _ecore_cocoa_keys_s); ++i)
{
if (keystable[i].code == [keychar characterAtIndex:0])
{
ev->keyname = keystable[i].name;
ev->key = ev->keyname;
break;
}
}
}
if ([keycharRaw length] == 0 && keyType == NSKeyDown)
{
compose=EINA_TRUE;
edit = [[event window] fieldEditor:YES forObject:nil];
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
free(ev);
return NULL;
}
return ev;
}
static inline Eina_Bool
_nsevent_window_is_type_of(NSEvent *event, Class class)
{
@ -116,8 +173,6 @@ ecore_cocoa_feed_events(void *anEvent)
NSEvent *event = anEvent;
unsigned int time = (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff);
Eina_Bool pass = EINA_FALSE;
static Eina_Bool compose = EINA_FALSE;
static NSText *edit;
switch ([event type])
{
@ -138,77 +193,24 @@ ecore_cocoa_feed_events(void *anEvent)
case NSKeyDown:
{
Ecore_Event_Key *ev;
unsigned int i;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSString *keychar = [event characters];
ev = calloc(1, sizeof (Ecore_Event_Key));
if (!ev) return pass;
ev = _ecore_cocoa_event_key(event, NSKeyDown);
if (ev == NULL) return EINA_TRUE;
ev->timestamp = time;
ev->modifiers = _ecore_cocoa_event_modifiers([event modifierFlags]);
if (compose)
{
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
compose=EINA_FALSE;
}
if ([keychar length] > 0)
{
for (i = 0; i < sizeof (keystable) / sizeof (struct _ecore_cocoa_keys_s); ++i)
{
if (keystable[i].code == [keychar characterAtIndex:0])
{
DBG("Key pressed: %s %d\n", keystable[i].name, [keychar characterAtIndex:0]);
ev->keyname = keystable[i].name;
ev->key = keystable[i].name;
ev->string = keystable[i].compose;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
return pass;
}
}
}
else
{
compose=EINA_TRUE;
edit = [[event window] fieldEditor:YES forObject:nil];
[edit interpretKeyEvents:[NSArray arrayWithObject:event]];
}
ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
break;
}
case NSKeyUp:
{
Ecore_Event_Key *ev;
unsigned int i;
EcoreCocoaWindow *window = (EcoreCocoaWindow *)[event window];
NSString *keychar = [event characters];
DBG("Key Up\n");
ev = _ecore_cocoa_event_key(event, NSKeyUp);
if (ev == NULL) return EINA_TRUE;
ev = calloc(1, sizeof (Ecore_Event_Key));
if (!ev) return pass;
ev->timestamp = time;
ev->modifiers = _ecore_cocoa_event_modifiers([event modifierFlags]);
if ([keychar length] > 0)
{
for (i = 0; i < sizeof (keystable) / sizeof (struct _ecore_cocoa_keys_s); ++i)
{
if (keystable[i].code == [keychar characterAtIndex:0])
{
ev->keyname = keystable[i].name;
ev->key = keystable[i].name;
ev->string = keystable[i].compose;
ev->window = (Ecore_Window)window.ecore_window_data;
ev->event_window = ev->window;
ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
return pass;
}
}
}
ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
break;
}
@ -222,13 +224,6 @@ ecore_cocoa_feed_events(void *anEvent)
evDown = calloc(1, sizeof (Ecore_Event_Key));
if (!evDown) return pass;
evUp = calloc(1, sizeof (Ecore_Event_Key));
if (!evUp)
{
free(evDown);
return pass;
}
// Turn special key flags on
if (flags & NSShiftKeyMask)
evDown->key = "Shift_L";
@ -243,13 +238,22 @@ ecore_cocoa_feed_events(void *anEvent)
if (evDown->key)
{
evDown->keyname = evDown->key;
evDown->timestamp = time;
evDown->string = "";
evDown->string = NULL;
ecore_event_add(ECORE_EVENT_KEY_DOWN, evDown, NULL, NULL);
old_flags = flags;
break;
}
free(evDown);
evUp = calloc(1, sizeof (Ecore_Event_Key));
if (!evUp)
{
return pass;
}
int changed_flags = flags ^ old_flags;
// Turn special key flags off
@ -266,8 +270,9 @@ ecore_cocoa_feed_events(void *anEvent)
if (evUp->key)
{
evUp->keyname = evDown->key;
evUp->timestamp = time;
evUp->string = "";
evUp->string = NULL;
ecore_event_add(ECORE_EVENT_KEY_UP, evUp, NULL, NULL);
old_flags = flags;
break;
@ -361,4 +366,3 @@ ecore_cocoa_titlebar_height_get(void)
}
return height;
}