From 5e7e7bceba422000829d700df2d9cca0b0b79abe Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Sat, 9 Jun 2018 01:11:47 -0700 Subject: [PATCH] Linux keyboard input fixup --- platform_linux/linux_4ed.cpp | 249 ++++++++++++++++++++++++++++------- 1 file changed, 200 insertions(+), 49 deletions(-) diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 1d43b34a..958b1a0d 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -958,8 +958,7 @@ LinuxInputInit(Display *dpy, Window XWindow){ // Keyboard handling funcs // -global Key_Code keycode_lookup_table[255]; - +#if 0 internal void LinuxKeycodeInit(Display* dpy){ @@ -1018,7 +1017,9 @@ LinuxKeycodeInit(Display* dpy){ KeySym* syms = XGetKeyboardMapping(dpy, key_min, key_count, &syms_per_code); - if (!syms) return; + if (syms == 0){ + return; + } int key = key_min; for(int i = 0; i < key_count * syms_per_code; ++i){ @@ -1031,8 +1032,8 @@ LinuxKeycodeInit(Display* dpy){ } XFree(syms); - } +#endif internal void LinuxPushKey(Key_Code code, Key_Code chr, Key_Code chr_nocaps, b8 *mods) @@ -1337,41 +1338,41 @@ LinuxX11WindowInit(int argc, char** argv, int* window_width, int* window_height) internal void LinuxHandleX11Events(void) { - static XEvent PrevEvent = {}; + static XEvent prev_event = {}; b32 should_step = false; while (XPending(linuxvars.XDisplay)) { - XEvent Event; - XNextEvent(linuxvars.XDisplay, &Event); + XEvent event; + XNextEvent(linuxvars.XDisplay, &event); - if (XFilterEvent(&Event, None) == True){ + if (XFilterEvent(&event, None) == True){ continue; } - switch (Event.type){ + switch (event.type){ case KeyPress: { should_step = true; - b32 is_hold = (PrevEvent.type == KeyRelease && - PrevEvent.xkey.time == Event.xkey.time && - PrevEvent.xkey.keycode == Event.xkey.keycode); + b32 is_hold = (prev_event.type == KeyRelease && + prev_event.xkey.time == event.xkey.time && + prev_event.xkey.keycode == event.xkey.keycode); b8 mods[MDFR_INDEX_COUNT] = {}; mods[MDFR_HOLD_INDEX] = is_hold; - if (Event.xkey.state & ShiftMask) mods[MDFR_SHIFT_INDEX] = 1; - if (Event.xkey.state & ControlMask) mods[MDFR_CONTROL_INDEX] = 1; - if (Event.xkey.state & LockMask) mods[MDFR_CAPS_INDEX] = 1; - if (Event.xkey.state & Mod1Mask) mods[MDFR_ALT_INDEX] = 1; + if (event.xkey.state & ShiftMask) mods[MDFR_SHIFT_INDEX] = 1; + if (event.xkey.state & ControlMask) mods[MDFR_CONTROL_INDEX] = 1; + if (event.xkey.state & LockMask) mods[MDFR_CAPS_INDEX] = 1; + if (event.xkey.state & Mod1Mask) mods[MDFR_ALT_INDEX] = 1; - Event.xkey.state &= ~(ControlMask); + event.xkey.state &= ~(ControlMask); Status status; KeySym keysym = NoSymbol; u8 buff[32] = {}; - Xutf8LookupString(linuxvars.input_context, &Event.xkey, (char*)buff, sizeof(buff) - 1, &keysym, &status); + Xutf8LookupString(linuxvars.input_context, &event.xkey, (char*)buff, sizeof(buff) - 1, &keysym, &status); if (status == XBufferOverflow){ //TODO(inso): handle properly @@ -1380,14 +1381,26 @@ LinuxHandleX11Events(void) LOG("FIXME: XBufferOverflow from LookupString.\n"); } + // don't push modifiers + if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R){ + break; + } + u32 key = utf8_to_u32_unchecked(buff); u32 key_no_caps = key; - if (mods[MDFR_CAPS_INDEX] && status == XLookupBoth && Event.xkey.keycode){ + if (mods[MDFR_CAPS_INDEX] && status == XLookupBoth && event.xkey.keycode){ u8 buff_no_caps[32] = {0}; - Event.xkey.state &= ~(LockMask); + event.xkey.state &= ~(LockMask); - XLookupString(&Event.xkey, (char*)buff_no_caps, sizeof(buff_no_caps) - 1, NULL, NULL); + Xutf8LookupString(linuxvars.input_context, &event.xkey, (char*)buff_no_caps, sizeof(buff_no_caps) - 1, NULL, &status); + + if (status == XBufferOverflow){ + //TODO(inso): handle properly + Xutf8ResetIC(linuxvars.input_context); + XSetICFocus(linuxvars.input_context); + LOG("FIXME: XBufferOverflow from LookupString.\n"); + } if (*buff_no_caps){ key_no_caps = utf8_to_u32_unchecked(buff_no_caps); @@ -1397,17 +1410,156 @@ LinuxHandleX11Events(void) if (key == '\r') key = '\n'; if (key_no_caps == '\r') key_no_caps = '\n'; - // don't push modifiers - if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R){ - break; - } - if (keysym == XK_ISO_Left_Tab){ key = key_no_caps = '\t'; mods[MDFR_SHIFT_INDEX] = 1; } - Key_Code special_key = keycode_lookup_table[(u8)Event.xkey.keycode]; + //Key_Code special_key = keycode_lookup_table[keysym]; + + Key_Code special_key = 0; + switch (keysym){ + case XK_BackSpace: + { + special_key = key_back; + }break; + + case XK_Delete: + { + special_key = key_del; + }break; + + case XK_Up: + { + special_key = key_up; + }break; + + case XK_Down: + { + special_key = key_down; + }break; + + case XK_Left: + { + special_key = key_left; + }break; + + case XK_Right: + { + special_key = key_right; + }break; + + case XK_Insert: + { + special_key = key_insert; + }break; + + case XK_Home: + { + special_key = key_home; + }break; + + case XK_End: + { + special_key = key_end; + }break; + + case XK_Page_Up: + { + special_key = key_page_up; + }break; + + case XK_Page_Down: + { + special_key = key_page_down; + }break; + + case XK_Escape: + { + special_key = key_esc; + }break; + + case XK_F1: + { + special_key = key_f1; + }break; + + case XK_F2: + { + special_key = key_f2; + }break; + + case XK_F3: + { + special_key = key_f3; + }break; + + case XK_F4: + { + special_key = key_f4; + }break; + + case XK_F5: + { + special_key = key_f5; + }break; + + case XK_F6: + { + special_key = key_f6; + }break; + + case XK_F7: + { + special_key = key_f7; + }break; + + case XK_F8: + { + special_key = key_f8; + }break; + + case XK_F9: + { + special_key = key_f9; + }break; + + case XK_F10: + { + special_key = key_f10; + }break; + + case XK_F11: + { + special_key = key_f11; + }break; + + case XK_F12: + { + special_key = key_f12; + }break; + + case XK_F13: + { + special_key = key_f13; + }break; + + case XK_F14: + { + special_key = key_f14; + }break; + + case XK_F15: + { + special_key = key_f15; + }break; + + case XK_F16: + { + special_key = key_f16; + }break; + } + if (special_key){ LinuxPushKey(special_key, 0, 0, mods); @@ -1424,13 +1576,13 @@ LinuxHandleX11Events(void) case MotionNotify: { should_step = true; - linuxvars.input.mouse.x = Event.xmotion.x; - linuxvars.input.mouse.y = Event.xmotion.y; + linuxvars.input.mouse.x = event.xmotion.x; + linuxvars.input.mouse.y = event.xmotion.y; }break; case ButtonPress: { should_step = true; - switch(Event.xbutton.button){ + switch(event.xbutton.button){ case Button1: { linuxvars.input.mouse.press_l = 1; linuxvars.input.mouse.l = 1; @@ -1454,7 +1606,7 @@ LinuxHandleX11Events(void) case ButtonRelease: { should_step = true; - switch(Event.xbutton.button){ + switch(event.xbutton.button){ case Button1: { linuxvars.input.mouse.release_l = 1; linuxvars.input.mouse.l = 0; @@ -1485,8 +1637,8 @@ LinuxHandleX11Events(void) case ConfigureNotify: { should_step = true; - i32 w = Event.xconfigure.width; - i32 h = Event.xconfigure.height; + i32 w = event.xconfigure.width; + i32 h = event.xconfigure.height; if (w != target.width || h != target.height){ LinuxResizeTarget(w, h); @@ -1494,32 +1646,31 @@ LinuxHandleX11Events(void) }break; case MappingNotify: { - if (Event.xmapping.request == MappingModifier || Event.xmapping.request == MappingKeyboard){ - XRefreshKeyboardMapping(&Event.xmapping); - LinuxKeycodeInit(linuxvars.XDisplay); + if (event.xmapping.request == MappingModifier || event.xmapping.request == MappingKeyboard){ + XRefreshKeyboardMapping(&event.xmapping); + //LinuxKeycodeInit(linuxvars.XDisplay); } }break; case ClientMessage: { - if ((Atom)Event.xclient.data.l[0] == linuxvars.atom_WM_DELETE_WINDOW) { + if ((Atom)event.xclient.data.l[0] == linuxvars.atom_WM_DELETE_WINDOW) { should_step = true; linuxvars.keep_running = 0; } - else if ((Atom)Event.xclient.data.l[0] == linuxvars.atom__NET_WM_PING) { - Event.xclient.window = DefaultRootWindow(linuxvars.XDisplay); + else if ((Atom)event.xclient.data.l[0] == linuxvars.atom__NET_WM_PING) { + event.xclient.window = DefaultRootWindow(linuxvars.XDisplay); XSendEvent( linuxvars.XDisplay, - Event.xclient.window, + event.xclient.window, False, SubstructureRedirectMask | SubstructureNotifyMask, - &Event - ); + &event); } }break; // NOTE(inso): Someone wants us to give them the clipboard data. case SelectionRequest: { - XSelectionRequestEvent request = Event.xselectionrequest; + XSelectionRequestEvent request = event.xselectionrequest; XSelectionEvent response = {}; response.type = SelectionNotify; @@ -1584,14 +1735,14 @@ LinuxHandleX11Events(void) // NOTE(inso): Another program is now the clipboard owner. case SelectionClear: { - if (Event.xselectionclear.selection == linuxvars.atom_CLIPBOARD){ + if (event.xselectionclear.selection == linuxvars.atom_CLIPBOARD){ linuxvars.clipboard_outgoing.size = 0; } }break; // NOTE(inso): A program is giving us the clipboard data we asked for. case SelectionNotify: { - XSelectionEvent* e = (XSelectionEvent*)&Event; + XSelectionEvent* e = (XSelectionEvent*)&event; if (e->selection == linuxvars.atom_CLIPBOARD && e->target == linuxvars.atom_UTF8_STRING && e->property != None){ Atom type; int fmt; @@ -1619,8 +1770,8 @@ LinuxHandleX11Events(void) }break; default: { - if (Event.type == linuxvars.xfixes_selection_event){ - XFixesSelectionNotifyEvent* sne = (XFixesSelectionNotifyEvent*)&Event; + if (event.type == linuxvars.xfixes_selection_event){ + XFixesSelectionNotifyEvent* sne = (XFixesSelectionNotifyEvent*)&event; if (sne->subtype == XFixesSelectionNotify && sne->owner != linuxvars.XWindow){ XConvertSelection(linuxvars.XDisplay, linuxvars.atom_CLIPBOARD, linuxvars.atom_UTF8_STRING, linuxvars.atom_CLIPBOARD, linuxvars.XWindow, CurrentTime); } @@ -1628,7 +1779,7 @@ LinuxHandleX11Events(void) }break; } - PrevEvent = Event; + prev_event = event; } if (should_step){ @@ -1771,7 +1922,7 @@ main(int argc, char **argv){ linuxvars.input_style = input_result.best_style; linuxvars.input_context = input_result.xic; - LinuxKeycodeInit(linuxvars.XDisplay); + //LinuxKeycodeInit(linuxvars.XDisplay); Cursor xcursors[APP_MOUSE_CURSOR_COUNT] = { None,