Mercurial > projects > dynamin
changeset 24:43a88caead16
Implement keyDown and keyUp events with X.
author | Jordan Miner <jminer7@gmail.com> |
---|---|
date | Sat, 25 Jul 2009 15:01:46 -0500 |
parents | d55b5b998412 |
children | 0577e8738dc8 |
files | dynamin/c/xlib.d dynamin/gui/x_key.d dynamin/gui/x_window.d |
diffstat | 3 files changed, 179 insertions(+), 135 deletions(-) [+] |
line wrap: on
line diff
--- a/dynamin/c/xlib.d Sat Jul 25 14:58:43 2009 -0500 +++ b/dynamin/c/xlib.d Sat Jul 25 15:01:46 2009 -0500 @@ -357,6 +357,15 @@ //}}} //{{{ keyboard functions +int XRefreshKeyboardMapping( + XMappingEvent* event_map); + +int XQueryKeymap( + Display* display, + ubyte* keys_return); + +KeySym XLookupKeysym(XKeyEvent* key_event, int index); + KeyCode XKeysymToKeycode(Display* display, KeySym keysym); KeySym XKeycodeToKeysym(
--- a/dynamin/gui/x_key.d Sat Jul 25 14:58:43 2009 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -// Written in the D programming language -// www.digitalmars.com/d/ - - - -Key XKeyCodeToKey(int code) { - switch(code) { - case XK_parenright: - case XK_0: return Key.D0; - case XK_exclam: - case XK_1: return Key.D1; - case XK_at: - case XK_2: return Key.D2; - case XK_numbersign: - case XK_3: return Key.D3; - case XK_dollar: - case XK_4: return Key.D4; - case XK_percent: - case XK_5: return Key.D5; - case XK_asciicircum: - case XK_6: return Key.D6; - case XK_ampersand: - case XK_7: return Key.D7; - case XK_asterisk: - case XK_8: return Key.D8; - case XK_parenleft: - case XK_9: return Key.D9; - - case XK_F1: return Key.F1; - case XK_F2: return Key.F2; - case XK_F3: return Key.F3; - case XK_F4: return Key.F4; - case XK_F5: return Key.F5; - case XK_F6: return Key.F6; - case XK_F7: return Key.F7; - case XK_F8: return Key.F8; - case XK_F9: return Key.F9; - case XK_F10: return Key.F10; - case XK_F11: return Key.F11; - case XK_F12: return Key.F12; - - case XK_Escape: return Key.Escape; - case XK_Tab: return Key.Tab; - case XK_BackSpace: return Key.Backspace; - case XK_Return: return Key.Enter; - case XK_KP_Enter: return Key.Enter; - case XK_space: return Key.Space; - - case XK_KP_Left: - case XK_Left: return Key.Left; - case XK_KP_Right: - case XK_Right: return Key.Right; - case XK_KP_Up: - case XK_Up: return Key.Up; - case XK_KP_Down: - case XK_Down: return Key.Down; - - case XK_KP_Insert: - case XK_Insert: return Key.Insert; - case XK_KP_Delete: - case XK_Delete: return Key.Delete; - case XK_KP_Home: - case XK_Home: return Key.Home; - case XK_KP_End: - case XK_End: return Key.End; - case XK_KP_Prior: - case XK_Prior: return Key.PageUp; - case XK_KP_Next: - case XK_Next: return Key.PageDown; - - case XK_Sys_Req: return Key.PrintScreen; - case XK_Pause: return Key.Pause; - - case XK_Caps_Lock: return Key.CapsLock; - case XK_Num_Lock: return Key.NumLock; - case XK_Scroll_Lock: return Key.ScrollLock; - - case XK_KP_0: return Key.NumPad0; - case XK_KP_1: return Key.NumPad1; - case XK_KP_2: return Key.NumPad2; - case XK_KP_3: return Key.NumPad3; - case XK_KP_4: return Key.NumPad4; - case XK_KP_5: return Key.NumPad5; - case XK_KP_6: return Key.NumPad6; - case XK_KP_7: return Key.NumPad7; - case XK_KP_8: return Key.NumPad8; - case XK_KP_9: return Key.NumPad9; - case XK_KP_Divide: return Key.NumPadDivide; - case XK_KP_Multiply: return Key.NumPadMultiply; - case XK_KP_Subtract: return Key.NumPadSubtract; - case XK_KP_Add: return Key.NumPadAdd; - case XK_KP_Decimal: return Key.NumPadDecimal; - - case XK_grave: - case XK_asciitilde: return Key.Backquote; - case XK_minus: - case XK_underscore: return Key.Minus; - case XK_equal: - case XK_plus: return Key.Equals; - case XK_bracketleft: - case XK_braceleft: return Key.OpenBracket; - case XK_bracketright: - case XK_braceright: return Key.CloseBracket; - case XK_backslash: - case XK_bar: return Key.Backslash; - case XK_semicolon: - case XK_colon: return Key.Semicolon; - case XK_apostrophe: - case XK_quotedbl: return Key.Quote; - case XK_comma: - case XK_less: return Key.Comma; - case XK_period: - case XK_greater: return Key.Period; - case XK_slash: - case XK_question: return Key.Slash; - - //case XK_Menu: return Key.Menu; - - case XK_Shift_L: - case XK_Shift_R: return Key.Shift; - case XK_Control_L: - case XK_Control_R: return Key.Control; - case XK_Alt_L: - case XK_Alt_R: return Key.Alt; - - //case XK_: return Key.; - default: - if(code >= 0x41 && code <= 0x5A) // Key.A - Key.Z - return cast(Key)code; - if(code >= 0x61 && code <= 0x7A) // Key.A - Key.Z - return cast(Key)(code-32); - return 0; - } -} -
--- a/dynamin/gui/x_window.d Sat Jul 25 14:58:43 2009 -0500 +++ b/dynamin/gui/x_window.d Sat Jul 25 15:01:46 2009 -0500 @@ -29,6 +29,7 @@ public import dynamin.core.global; public import dynamin.core.math; public import dynamin.gui.window; +public import dynamin.gui.key; public import dynamin.c.xlib; public import dynamin.c.xlib : XWindow = Window; public import dynamin.c.xmu; @@ -210,6 +211,8 @@ } }+/ +Key prevKey = Key.None; + //{{{ ApplicationBackend template ApplicationBackend() { void backend_run(Window w) { @@ -265,6 +268,11 @@ scope args = new MouseEventArgs(buttonEv.x+c._borderSize.left, buttonEv.y+c._borderSize.top, button); func(args); } + bool isKeyDown(uint keycode) { + ubyte[32] keys; + XQueryKeymap(display, keys.ptr); + return cast(bool)( (keys[keycode / 8] >> (keycode % 8)) & 1 ); + } //}}} switch(ev.type) { case MapNotify: @@ -295,8 +303,33 @@ } break; case KeyPress: + auto sym = XLookupKeysym(&ev.xkey, 0); + if(sym == NoSymbol) + break; + // Since X gives no way to tell if a KeyPress is generated by + // auto-repeat, prevKey is used here to tell. + auto k = KeysymToKey(sym); + scope args = new KeyEventArgs(k, k == prevKey); + prevKey = k; + Control focused = c.focusedControl ? c.focusedControl : c; + focused.keyDown(args); break; case KeyRelease: + // When X does auto-repeat for a held down key, it sends + // a KeyPress and KeyRelease every time, even though the key is + // down constantly. Here we check if the key is down, and if so, + // not send a keyUp event. + if(isKeyDown(ev.xkey.keycode)) + break; + auto sym = XLookupKeysym(&ev.xkey, 0); + if(sym == NoSymbol) + break; + auto k = KeysymToKey(sym); + if(k == prevKey) + prevKey = Key.None; // can't repeat after released + scope args = new KeyEventArgs(k, false); + Control focused = c.focusedControl ? c.focusedControl : c; + focused.keyUp(args); break; case ButtonPress: //Button4 is wheel scroll up @@ -431,6 +464,9 @@ data.target, 8, PropModeReplace, data.data, data.length); XSendEvent(display, selEv.requestor, false, 0, &fullEv); break; + case MappingNotify: + XRefreshKeyboardMapping(&ev.xmapping); + break; default: break; } @@ -446,6 +482,140 @@ } //}}} +//{{{ KeysymToKey() +Key KeysymToKey(int sym) { + switch(sym) { + case XK_parenright: + case XK_0: return Key.D0; + case XK_exclam: + case XK_1: return Key.D1; + case XK_at: + case XK_2: return Key.D2; + case XK_numbersign: + case XK_3: return Key.D3; + case XK_dollar: + case XK_4: return Key.D4; + case XK_percent: + case XK_5: return Key.D5; + case XK_asciicircum: + case XK_6: return Key.D6; + case XK_ampersand: + case XK_7: return Key.D7; + case XK_asterisk: + case XK_8: return Key.D8; + case XK_parenleft: + case XK_9: return Key.D9; + + case XK_F1: return Key.F1; + case XK_F2: return Key.F2; + case XK_F3: return Key.F3; + case XK_F4: return Key.F4; + case XK_F5: return Key.F5; + case XK_F6: return Key.F6; + case XK_F7: return Key.F7; + case XK_F8: return Key.F8; + case XK_F9: return Key.F9; + case XK_F10: return Key.F10; + case XK_F11: return Key.F11; + case XK_F12: return Key.F12; + + case XK_Escape: return Key.Escape; + case XK_Tab: return Key.Tab; + case XK_BackSpace: return Key.Backspace; + case XK_Return: return Key.Enter; + case XK_KP_Enter: return Key.Enter; + case XK_space: return Key.Space; + + case XK_KP_Left: + case XK_Left: return Key.Left; + case XK_KP_Right: + case XK_Right: return Key.Right; + case XK_KP_Up: + case XK_Up: return Key.Up; + case XK_KP_Down: + case XK_Down: return Key.Down; + + case XK_KP_Insert: + case XK_Insert: return Key.Insert; + case XK_KP_Delete: + case XK_Delete: return Key.Delete; + case XK_KP_Home: + case XK_Home: return Key.Home; + case XK_KP_End: + case XK_End: return Key.End; + case XK_KP_Prior: + case XK_Prior: return Key.PageUp; + case XK_KP_Next: + case XK_Next: return Key.PageDown; + + case XK_Print: + case XK_Sys_Req: return Key.PrintScreen; + case XK_Pause: + case XK_Break: return Key.Pause; + + case XK_Caps_Lock: return Key.CapsLock; + case XK_Num_Lock: return Key.NumLock; + case XK_Scroll_Lock: return Key.ScrollLock; + + case XK_KP_0: return Key.NumPad0; + case XK_KP_1: return Key.NumPad1; + case XK_KP_2: return Key.NumPad2; + case XK_KP_3: return Key.NumPad3; + case XK_KP_4: return Key.NumPad4; + case XK_KP_5: return Key.NumPad5; + case XK_KP_6: return Key.NumPad6; + case XK_KP_7: return Key.NumPad7; + case XK_KP_8: return Key.NumPad8; + case XK_KP_9: return Key.NumPad9; + case XK_KP_Divide: return Key.NumPadDivide; + case XK_KP_Multiply: return Key.NumPadMultiply; + case XK_KP_Subtract: return Key.NumPadSubtract; + case XK_KP_Add: return Key.NumPadAdd; + case XK_KP_Decimal: return Key.NumPadDecimal; + + case XK_grave: + case XK_asciitilde: return Key.Backquote; + case XK_minus: + case XK_underscore: return Key.Minus; + case XK_equal: + case XK_plus: return Key.Equals; + case XK_bracketleft: + case XK_braceleft: return Key.OpenBracket; + case XK_bracketright: + case XK_braceright: return Key.CloseBracket; + case XK_backslash: + case XK_bar: return Key.Backslash; + case XK_semicolon: + case XK_colon: return Key.Semicolon; + case XK_apostrophe: + case XK_quotedbl: return Key.Quote; + case XK_comma: + case XK_less: return Key.Comma; + case XK_period: + case XK_greater: return Key.Period; + case XK_slash: + case XK_question: return Key.Slash; + + //case XK_Menu: return Key.Menu; + + case XK_Shift_L: + case XK_Shift_R: return Key.Shift; + case XK_Control_L: + case XK_Control_R: return Key.Control; + case XK_Alt_L: + case XK_Alt_R: return Key.Alt; + + //case XK_: return Key.; + default: + if(sym >= 0x41 && sym <= 0x5A) // Key.A - Key.Z + return cast(Key)sym; + if(sym >= 0x61 && sym <= 0x7A) // Key.A - Key.Z + return cast(Key)(sym-32); + return cast(Key)0; + } +} +//}}} + public import tango.stdc.time; template WindowBackend() { invariant {