Skip to content

Commit

Permalink
Enable deadkey handling on MacOS.
Browse files Browse the repository at this point in the history
We replace the old, somewhat flaky direct reads from NSEvent with the
use of UCKeyTranslate.

It is still not perfect, so we do a bunch fo hacks to get the various
keys repeating and emitting the correct CHAR events.
  • Loading branch information
SiegeLordEx authored and SiegeLord committed Nov 14, 2024
1 parent 28b4b86 commit ce2a209
Showing 1 changed file with 58 additions and 14 deletions.
72 changes: 58 additions & 14 deletions src/macosx/keybd.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "allegro5/internal/aintern_keyboard.h"
#include "allegro5/platform/aintosx.h"

#import <Carbon/Carbon.h>

#ifndef ALLEGRO_MACOSX
#error Something is wrong with the makefile
#endif
Expand All @@ -49,6 +51,7 @@
static ALLEGRO_KEYBOARD* osx_get_keyboard(void);
static ALLEGRO_KEYBOARD keyboard;
static ALLEGRO_KEYBOARD_STATE kbdstate;
static UInt32 dead_key_state;



Expand Down Expand Up @@ -105,10 +108,8 @@ static void _handle_key_press(ALLEGRO_DISPLAY* dpy, int unicode, int scancode,
if (!is_repeat) {
_al_event_source_emit_event(&keyboard.es, &event);
}
if (unicode > 0) {
/* Apple maps function, arrow, and other keys to Unicode points. */
/* http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT */
if (unicode >= 0xF700 && unicode <= 0xF747) {
if (unicode != 0) {
if (unicode < 0) {
unicode = 0;
}
event.keyboard.type = ALLEGRO_EVENT_KEY_CHAR;
Expand Down Expand Up @@ -266,17 +267,60 @@ void _al_osx_keyboard_handler(int pressed, NSEvent *event, ALLEGRO_DISPLAY* dpy)
/* Translate OS X modifier flags to Allegro modifier flags */
int key_shifts = translate_modifier_flags([event modifierFlags]);

if (pressed) {
NSString* raw_characters = [event charactersIgnoringModifiers];
NSString* upper_characters = [event characters];
const unichar raw_character = ([raw_characters length] > 0) ? [raw_characters characterAtIndex: 0] : 0;
const unichar upper_character =([upper_characters length] > 0) ? [upper_characters characterAtIndex: 0] : 0;
if (pressed) {
/* https://stackoverflow.com/a/22677690 */
TISInputSourceRef keyboard_input = TISCopyCurrentKeyboardInputSource();
CFDataRef layout_data = TISGetInputSourceProperty(keyboard_input, kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout *layout = (const UCKeyboardLayout *)CFDataGetBytePtr(layout_data);

CGEventFlags modifier_flags = [event modifierFlags];
UInt32 modifier_key_state = (modifier_flags >> 16) & 0xff;

UniChar unicode_string[5];
unicode_string[4] = 0;
UniCharCount unicode_length;

UCKeyTranslate(layout,
[event keyCode],
kUCKeyActionDown,
modifier_key_state,
LMGetKbdType(),
0,
&dead_key_state,
4,
&unicode_length,
unicode_string);

int32_t unichar = 0;
if (unicode_length > 0) {
ALLEGRO_USTR *ustr = al_ustr_new_from_utf16(unicode_string);
unichar = al_ustr_get(ustr, 0);
if (unichar < 0)
unichar = 0;
/* For some reason, pad enter sends a ^C. */
if (scancode == ALLEGRO_KEY_PAD_ENTER && unichar == 3)
unichar = '\r';
/* Single out the few printable characters under 32 */
if (unichar < ' ' && (unichar != '\r' && unichar != '\t' && unichar != '\b'))
unichar = 0;
al_ustr_free(ustr);
}
CFRelease(keyboard_input);

NSString *raw_characters = [event charactersIgnoringModifiers];
NSString *characters = [event characters];
UniChar raw_character = ([raw_characters length] > 0) ? [raw_characters characterAtIndex: 0] : 0;
UniChar character = ([characters length] > 0) ? [characters characterAtIndex: 0] : 0;
/* Apple maps function, arrow, and other keys to Unicode points.
We want to generate CHAR events for them, so we'll override the translation logic.
_handle_key_press will set the unichar back to 0 for these keys. */
if (unichar == 0 && character >= 0xF700 && character <= 0xF747)
unichar = -1;
bool is_repeat = pressed ? ([event isARepeat] == YES) : false;
/* Special processing to send character 1 for CTRL-A, 2 for CTRL-B etc. */
if ((key_shifts & ALLEGRO_KEYMOD_CTRL) && (isalpha(raw_character)))
_handle_key_press(dpy, tolower(raw_character) - 'a' + 1, scancode, key_shifts, is_repeat);
else
_handle_key_press(dpy, upper_character, scancode, key_shifts, is_repeat);
unichar = tolower(raw_character) - 'a' + 1;
_handle_key_press(dpy, unichar, scancode, key_shifts, is_repeat);
}
else {
_handle_key_release(dpy, key_shifts, scancode);
Expand All @@ -301,15 +345,15 @@ void _al_osx_keyboard_modifiers(unsigned int modifiers, ALLEGRO_DISPLAY* dpy)
changed = (modifiers ^ old_modifiers) & mod_info[i][0];
if (changed) {
if (modifiers & mod_info[i][0]) {
_handle_key_press(dpy, -1, mod_info[i][2], key_shifts, false);
_handle_key_press(dpy, 0, mod_info[i][2], key_shifts, false);
if (i == 0) {
/* Caps lock requires special handling */
_handle_key_release(dpy, key_shifts, mod_info[0][2]);
}
}
else {
if (i == 0) {
_handle_key_press(dpy, -1, mod_info[0][2], key_shifts, false);
_handle_key_press(dpy, 0, mod_info[0][2], key_shifts, false);
}

_handle_key_release(dpy, key_shifts, mod_info[i][2]);
Expand Down

0 comments on commit ce2a209

Please sign in to comment.