Linux keyboard input fixup

This commit is contained in:
Allen Webster 2018-06-09 01:11:47 -07:00
parent 27da2172dc
commit 5e7e7bceba
1 changed files with 200 additions and 49 deletions

View File

@ -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,