]> git.tdb.fi Git - libs/gui.git/blobdiff - source/input/keys.cpp
Include the matching header first in .cpp files
[libs/gui.git] / source / input / keys.cpp
index 37a376aaa6c662eb391aaa4704148f5adcb8e8dd..9b3349ac443346ca6e6e5e5867a9c9434e74cc54 100644 (file)
-#include <map>
-#ifdef WIN32
-#include <windows.h>
-#else
-#include <X11/X.h>
-#include <X11/keysym.h>
-#endif
-#include <msp/core/except.h>
 #include "keys.h"
+#include <map>
+#include <stdexcept>
+#include <msp/strings/format.h>
 
 using namespace std;
 
-namespace {
-
-unsigned keymap[Msp::Input::N_KEYS_]=
-{
-#ifndef WIN32
-       0, 0, 0, 0, 0, 0, 0, 0,
-       XK_BackSpace, XK_Tab, XK_Return, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, XK_Escape, 0, 0, 0, 0,
-
-       XK_space, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, XK_plus, XK_comma, XK_minus, XK_period, XK_slash,
-       XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6, XK_7,
-       XK_8, XK_9, 0, XK_semicolon, XK_less, XK_equal, 0, 0,
-
-       0, XK_a, XK_b, XK_c, XK_d, XK_e, XK_f, XK_g,
-       XK_h, XK_i, XK_j, XK_k, XK_l, XK_m, XK_n, XK_o,
-       XK_p, XK_q, XK_r, XK_s, XK_t, XK_u, XK_v, XK_w,
-       XK_x, XK_y, XK_z, XK_bracketleft, XK_backslash, XK_bracketright, 0, 0,
-
-       XK_grave, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-
-       XK_adiaeresis, XK_odiaeresis, XK_udiaeresis, XK_aring, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-
-       XK_Left, XK_Right, XK_Up, XK_Down, 0, 0, 0, 0,
-       XK_Home, XK_End, XK_Page_Up, XK_Page_Down, XK_Insert, XK_Delete, 0, 0,
-       XK_F1, XK_F2, XK_F3, XK_F4, XK_F5, XK_F6, XK_F7, XK_F8,
-       XK_F9, XK_F10, XK_F11, XK_F12, 0, 0, 0, 0,
-
-       XK_Shift_L, XK_Shift_R, XK_Control_L, XK_Control_R, XK_Alt_L, XK_Alt_R, XK_Super_L, XK_Super_R,
-       XK_Caps_Lock, XK_Scroll_Lock, XK_Num_Lock, 0, 0, 0, 0, 0,
-       XK_KP_0, XK_KP_1, XK_KP_2, XK_KP_3, XK_KP_4, XK_KP_5, XK_KP_6, XK_KP_7,
-       XK_KP_8, XK_KP_9, XK_KP_Add, XK_KP_Subtract, XK_KP_Multiply, XK_KP_Divide, XK_KP_Separator, 0,
-
-       XK_Pause, XK_Print, XK_Menu, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-#else
-       0, 0, 0, 0, 0, 0, 0, 0,
-       VK_BACK, VK_TAB, VK_RETURN, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,
-
-       VK_SPACE, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       '0', '1', '2', '3', '4', '5', '6', '7',
-       '8', '9', 0, 0, 0, 0, 0, 0,
-
-       0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
-       'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
-       'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
-       'X', 'Y', 'Z', 0, 0, 0, 0, 0,
-
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-
-       VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, 0, 0, 0, 0,
-       VK_HOME, VK_END, VK_PRIOR, VK_NEXT, VK_INSERT, VK_DELETE, 0, 0,
-       0, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5, VK_F6, VK_F7,
-       VK_F8, VK_F9, VK_F10, VK_F11, VK_F12, 0, 0, 0,
-
-       VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, 0, 0, VK_LWIN, VK_RWIN,
-       VK_CAPITAL, VK_SCROLL, VK_NUMLOCK, 0, 0, 0, 0, 0,
-       VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
-       VK_NUMPAD8, VK_NUMPAD9, VK_ADD, VK_SUBTRACT, VK_MULTIPLY, VK_DIVIDE, VK_SEPARATOR, 0,
-
-       VK_PAUSE, VK_SNAPSHOT, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-       0, 0, 0, 0, 0, 0, 0, 0,
-#endif
-};
-
-unsigned modmap[Msp::Input::N_MODS_]=
-{
-#ifndef WIN32
-       ShiftMask, ControlMask, Mod1Mask, Mod4Mask
-#else
-       1, 2, 4, 8
-#endif
-};
-
-}
-
 namespace Msp {
 namespace Input {
 
+extern unsigned sys_keymap[];
+
 unsigned key_from_sys(unsigned code)
 {
-       static bool init_done=false;
+       static bool init_done = false;
        static map<unsigned, unsigned> reverse_map;
 
        if(!init_done)
        {
                for(unsigned i=0; i<N_KEYS_; ++i)
-                       if(keymap[i])
-                               reverse_map[keymap[i]]=i;
+                       if(sys_keymap[i])
+                               reverse_map[sys_keymap[i]] = i;
 
-               init_done=true;
+               init_done = true;
        }
 
-       map<unsigned, unsigned>::const_iterator i=reverse_map.find(code);
+       auto i = reverse_map.find(code);
        if(i!=reverse_map.end())
                return i->second;
 
@@ -135,17 +34,352 @@ unsigned key_from_sys(unsigned code)
 unsigned key_to_sys(unsigned key)
 {
        if(key>=N_KEYS_)
-               throw InvalidParameterValue("Key out of range");
-       return keymap[key];
+               throw invalid_argument("key_to_sys");
+       return sys_keymap[key];
 }
 
-unsigned mod_from_sys(unsigned mod)
+void operator>>(const LexicalConverter &conv, Key &key)
 {
-       unsigned result = 0;
-       for(unsigned i=0; i<N_MODS_; ++i)
-               if(mod&modmap[i])
-                       result|=1<<i;
-       return result;
+       const string &str = conv.get();
+       if(str.size()==1)
+       {
+               switch(str[0])
+               {
+               case '0': { key = KEY_0; return; }
+               case '1': { key = KEY_1; return; }
+               case '2': { key = KEY_2; return; }
+               case '3': { key = KEY_3; return; }
+               case '4': { key = KEY_4; return; }
+               case '5': { key = KEY_5; return; }
+               case '6': { key = KEY_6; return; }
+               case '7': { key = KEY_7; return; }
+               case '8': { key = KEY_8; return; }
+               case '9': { key = KEY_9; return; }
+               case 'A': { key = KEY_A; return; }
+               case 'B': { key = KEY_B; return; }
+               case 'C': { key = KEY_C; return; }
+               case 'D': { key = KEY_D; return; }
+               case 'E': { key = KEY_E; return; }
+               case 'F': { key = KEY_F; return; }
+               case 'G': { key = KEY_G; return; }
+               case 'H': { key = KEY_H; return; }
+               case 'I': { key = KEY_I; return; }
+               case 'J': { key = KEY_J; return; }
+               case 'K': { key = KEY_K; return; }
+               case 'L': { key = KEY_L; return; }
+               case 'M': { key = KEY_M; return; }
+               case 'N': { key = KEY_N; return; }
+               case 'O': { key = KEY_O; return; }
+               case 'P': { key = KEY_P; return; }
+               case 'Q': { key = KEY_Q; return; }
+               case 'R': { key = KEY_R; return; }
+               case 'S': { key = KEY_S; return; }
+               case 'T': { key = KEY_T; return; }
+               case 'U': { key = KEY_U; return; }
+               case 'V': { key = KEY_V; return; }
+               case 'W': { key = KEY_W; return; }
+               case 'X': { key = KEY_X; return; }
+               case 'Y': { key = KEY_Y; return; }
+               case 'Z': { key = KEY_Z; return; }
+               }
+       }
+       else if(str.size()>1)
+       {
+               switch(str[0])
+               {
+               case 'A':
+                       if(!str.compare(1, string::npos, "DIAERESIS")) { key = KEY_ADIAERESIS; return; }
+                       if(!str.compare(1, string::npos, "LT_L")) { key = KEY_ALT_L; return; }
+                       if(!str.compare(1, string::npos, "LT_R")) { key = KEY_ALT_R; return; }
+                       if(!str.compare(1, string::npos, "POSTROPHE")) { key = KEY_APOSTROPHE; return; }
+                       if(!str.compare(1, string::npos, "RING")) { key = KEY_ARING; return; }
+                       break;
+               case 'B':
+                       if(!str.compare(1, string::npos, "ACK")) { key = KEY_BACK; return; }
+                       if(!str.compare(1, string::npos, "ACKSLASH")) { key = KEY_BACKSLASH; return; }
+                       if(!str.compare(1, string::npos, "ACKSPACE")) { key = KEY_BACKSPACE; return; }
+                       if(!str.compare(1, string::npos, "RACKET_L")) { key = KEY_BRACKET_L; return; }
+                       if(!str.compare(1, string::npos, "RACKET_R")) { key = KEY_BRACKET_R; return; }
+                       break;
+               case 'C':
+                       if(!str.compare(1, string::npos, "APS_LOCK")) { key = KEY_CAPS_LOCK; return; }
+                       if(!str.compare(1, string::npos, "OMMA")) { key = KEY_COMMA; return; }
+                       if(!str.compare(1, string::npos, "TRL_L")) { key = KEY_CTRL_L; return; }
+                       if(!str.compare(1, string::npos, "TRL_R")) { key = KEY_CTRL_R; return; }
+                       break;
+               case 'D':
+                       if(!str.compare(1, string::npos, "ELETE")) { key = KEY_DELETE; return; }
+                       if(!str.compare(1, string::npos, "OWN")) { key = KEY_DOWN; return; }
+                       break;
+               case 'E':
+                       if(!str.compare(1, string::npos, "ND")) { key = KEY_END; return; }
+                       if(!str.compare(1, string::npos, "NTER")) { key = KEY_ENTER; return; }
+                       if(!str.compare(1, string::npos, "QUAL")) { key = KEY_EQUAL; return; }
+                       if(!str.compare(1, string::npos, "SC")) { key = KEY_ESC; return; }
+                       break;
+               case 'F':
+                       if(!str.compare(1, string::npos, "1")) { key = KEY_F1; return; }
+                       if(!str.compare(1, string::npos, "2")) { key = KEY_F2; return; }
+                       if(!str.compare(1, string::npos, "3")) { key = KEY_F3; return; }
+                       if(!str.compare(1, string::npos, "4")) { key = KEY_F4; return; }
+                       if(!str.compare(1, string::npos, "5")) { key = KEY_F5; return; }
+                       if(!str.compare(1, string::npos, "6")) { key = KEY_F6; return; }
+                       if(!str.compare(1, string::npos, "7")) { key = KEY_F7; return; }
+                       if(!str.compare(1, string::npos, "8")) { key = KEY_F8; return; }
+                       if(!str.compare(1, string::npos, "9")) { key = KEY_F9; return; }
+                       if(!str.compare(1, string::npos, "10")) { key = KEY_F10; return; }
+                       if(!str.compare(1, string::npos, "11")) { key = KEY_F11; return; }
+                       if(!str.compare(1, string::npos, "12")) { key = KEY_F12; return; }
+                       break;
+               case 'G':
+                       if(!str.compare(1, string::npos, "RAVE")) { key = KEY_GRAVE; return; }
+                       break;
+               case 'H':
+                       if(!str.compare(1, string::npos, "OME")) { key = KEY_HOME; return; }
+                       break;
+               case 'I':
+                       if(!str.compare(1, string::npos, "NSERT")) { key = KEY_INSERT; return; }
+                       break;
+               case 'K':
+                       if(str[1]=='P')
+                       {
+                               if(!str.compare(2, string::npos, "0")) { key = KEY_KP0; return; }
+                               if(!str.compare(2, string::npos, "1")) { key = KEY_KP1; return; }
+                               if(!str.compare(2, string::npos, "2")) { key = KEY_KP2; return; }
+                               if(!str.compare(2, string::npos, "3")) { key = KEY_KP3; return; }
+                               if(!str.compare(2, string::npos, "4")) { key = KEY_KP4; return; }
+                               if(!str.compare(2, string::npos, "5")) { key = KEY_KP5; return; }
+                               if(!str.compare(2, string::npos, "6")) { key = KEY_KP6; return; }
+                               if(!str.compare(2, string::npos, "7")) { key = KEY_KP7; return; }
+                               if(!str.compare(2, string::npos, "8")) { key = KEY_KP8; return; }
+                               if(!str.compare(2, string::npos, "9")) { key = KEY_KP9; return; }
+                               if(!str.compare(2, string::npos, "_ADD")) { key = KEY_KP_ADD; return; }
+                               if(!str.compare(2, string::npos, "_DIVIDE")) { key = KEY_KP_DIVIDE; return; }
+                               if(!str.compare(2, string::npos, "_MULTIPLY")) { key = KEY_KP_MULTIPLY; return; }
+                               if(!str.compare(2, string::npos, "_SEPARATOR")) { key = KEY_KP_SEPARATOR; return; }
+                               if(!str.compare(2, string::npos, "_SUBTRACT")) { key = KEY_KP_SUBTRACT; return; }
+                       }
+                       break;
+               case 'L':
+                       if(!str.compare(1, string::npos, "EFT")) { key = KEY_LEFT; return; }
+                       if(!str.compare(1, string::npos, "ESS")) { key = KEY_LESS; return; }
+                       break;
+               case 'M':
+                       if(!str.compare(1, string::npos, "ENU")) { key = KEY_MENU; return; }
+                       if(!str.compare(1, string::npos, "INUS")) { key = KEY_MINUS; return; }
+                       break;
+               case 'N':
+                       if(!str.compare(1, string::npos, "ONE")) { key = KEY_NONE; return; }
+                       if(!str.compare(1, string::npos, "UM_LOCK")) { key = KEY_NUM_LOCK; return; }
+                       break;
+               case 'O':
+                       if(!str.compare(1, string::npos, "DIAERESIS")) { key = KEY_ODIAERESIS; return; }
+                       break;
+               case 'P':
+                       if(!str.compare(1, string::npos, "AUSE")) { key = KEY_PAUSE; return; }
+                       if(!str.compare(1, string::npos, "ERIOD")) { key = KEY_PERIOD; return; }
+                       if(!str.compare(1, string::npos, "GUP")) { key = KEY_PGUP; return; }
+                       if(!str.compare(1, string::npos, "GDN")) { key = KEY_PGDN; return; }
+                       if(!str.compare(1, string::npos, "LUS")) { key = KEY_PLUS; return; }
+                       if(!str.compare(1, string::npos, "RINT_SCREEN")) { key = KEY_PRINT_SCREEN; return; }
+                       break;
+               case 'R':
+                       if(!str.compare(1, string::npos, "IGHT")) { key = KEY_RIGHT; return; }
+                       break;
+               case 'S':
+                       if(!str.compare(1, string::npos, "CROLL_LOCK")) { key = KEY_SCROLL_LOCK; return; }
+                       if(!str.compare(1, string::npos, "EMICOLON")) { key = KEY_SEMICOLON; return; }
+                       if(!str.compare(1, string::npos, "HIFT_L")) { key = KEY_SHIFT_L; return; }
+                       if(!str.compare(1, string::npos, "HIFT_R")) { key = KEY_SHIFT_R; return; }
+                       if(!str.compare(1, string::npos, "LASH")) { key = KEY_SLASH; return; }
+                       if(!str.compare(1, string::npos, "PACE")) { key = KEY_SPACE; return; }
+                       if(!str.compare(1, string::npos, "UPER_R")) { key = KEY_SUPER_R; return; }
+                       if(!str.compare(1, string::npos, "UPER_L")) { key = KEY_SUPER_L; return; }
+                       break;
+               case 'T':
+                       if(!str.compare(1, string::npos, "AB")) { key = KEY_TAB; return; }
+                       break;
+               case 'U':
+                       if(!str.compare(1, string::npos, "P")) { key = KEY_UP; return; }
+                       break;
+               case 'V':
+                       if(!str.compare(1, string::npos, "OLUME_DOWN")) { key = KEY_VOLUME_DOWN; return; }
+                       if(!str.compare(1, string::npos, "OLUME_UP")) { key = KEY_VOLUME_UP; return; }
+                       break;
+               }
+       }
+
+       throw lexical_error(format("conversion of '%s' to Key", str));
+}
+
+void operator<<(LexicalConverter &conv, Key key)
+{
+       switch(key)
+       {
+       case KEY_NONE: conv.result("NONE"); break;
+       case KEY_BACKSPACE: conv.result("BACKSPACE"); break;
+       case KEY_TAB: conv.result("TAB"); break;
+       case KEY_ENTER: conv.result("ENTER"); break;
+       case KEY_ESC: conv.result("ESC"); break;
+       case KEY_SPACE: conv.result("SPACE"); break;
+       case KEY_APOSTROPHE: conv.result("APOSTROPHE"); break;
+       case KEY_PLUS: conv.result("PLUS"); break;
+       case KEY_COMMA: conv.result("COMMA"); break;
+       case KEY_MINUS: conv.result("MINUS"); break;
+       case KEY_PERIOD: conv.result("PERIOD"); break;
+       case KEY_SLASH: conv.result("SLASH"); break;
+       case KEY_0: conv.result("0"); break;
+       case KEY_1: conv.result("1"); break;
+       case KEY_2: conv.result("2"); break;
+       case KEY_3: conv.result("3"); break;
+       case KEY_4: conv.result("4"); break;
+       case KEY_5: conv.result("5"); break;
+       case KEY_6: conv.result("6"); break;
+       case KEY_7: conv.result("7"); break;
+       case KEY_8: conv.result("8"); break;
+       case KEY_9: conv.result("9"); break;
+       case KEY_SEMICOLON: conv.result("SEMICOLON"); break;
+       case KEY_LESS: conv.result("LESS"); break;
+       case KEY_EQUAL: conv.result("EQUAL"); break;
+       case KEY_A: conv.result("A"); break;
+       case KEY_B: conv.result("B"); break;
+       case KEY_C: conv.result("C"); break;
+       case KEY_D: conv.result("D"); break;
+       case KEY_E: conv.result("E"); break;
+       case KEY_F: conv.result("F"); break;
+       case KEY_G: conv.result("G"); break;
+       case KEY_H: conv.result("H"); break;
+       case KEY_I: conv.result("I"); break;
+       case KEY_J: conv.result("J"); break;
+       case KEY_K: conv.result("K"); break;
+       case KEY_L: conv.result("L"); break;
+       case KEY_M: conv.result("M"); break;
+       case KEY_N: conv.result("N"); break;
+       case KEY_O: conv.result("O"); break;
+       case KEY_P: conv.result("P"); break;
+       case KEY_Q: conv.result("Q"); break;
+       case KEY_R: conv.result("R"); break;
+       case KEY_S: conv.result("S"); break;
+       case KEY_T: conv.result("T"); break;
+       case KEY_U: conv.result("U"); break;
+       case KEY_V: conv.result("V"); break;
+       case KEY_W: conv.result("W"); break;
+       case KEY_X: conv.result("X"); break;
+       case KEY_Y: conv.result("Y"); break;
+       case KEY_Z: conv.result("Z"); break;
+       case KEY_BRACKET_L: conv.result("BRACKET_L"); break;
+       case KEY_BACKSLASH: conv.result("BACKSLASH"); break;
+       case KEY_BRACKET_R: conv.result("BRACKET_R"); break;
+       case KEY_GRAVE: conv.result("GRAVE"); break;
+       case KEY_ADIAERESIS: conv.result("ADIAERESIS"); break;
+       case KEY_ODIAERESIS: conv.result("ODIAERESIS"); break;
+       case KEY_UDIAERESIS: conv.result("UDIAERESIS"); break;
+       case KEY_ARING: conv.result("ARING"); break;
+       case KEY_LEFT: conv.result("LEFT"); break;
+       case KEY_RIGHT: conv.result("RIGHT"); break;
+       case KEY_UP: conv.result("UP"); break;
+       case KEY_DOWN: conv.result("DOWN"); break;
+       case KEY_HOME: conv.result("HOME"); break;
+       case KEY_END: conv.result("END"); break;
+       case KEY_PGUP: conv.result("PGUP"); break;
+       case KEY_PGDN: conv.result("PGDN"); break;
+       case KEY_INSERT: conv.result("INSERT"); break;
+       case KEY_DELETE: conv.result("DELETE"); break;
+       case KEY_F1: conv.result("F1"); break;
+       case KEY_F2: conv.result("F2"); break;
+       case KEY_F3: conv.result("F3"); break;
+       case KEY_F4: conv.result("F4"); break;
+       case KEY_F5: conv.result("F5"); break;
+       case KEY_F6: conv.result("F6"); break;
+       case KEY_F7: conv.result("F7"); break;
+       case KEY_F8: conv.result("F8"); break;
+       case KEY_F9: conv.result("F9"); break;
+       case KEY_F10: conv.result("F10"); break;
+       case KEY_F11: conv.result("F11"); break;
+       case KEY_F12: conv.result("F12"); break;
+       case KEY_SHIFT_L: conv.result("SHIFT_L"); break;
+       case KEY_SHIFT_R: conv.result("SHIFT_R"); break;
+       case KEY_CTRL_L: conv.result("CTRL_L"); break;
+       case KEY_CTRL_R: conv.result("CTRL_R"); break;
+       case KEY_ALT_L: conv.result("ALT_L"); break;
+       case KEY_ALT_R: conv.result("ALT_R"); break;
+       case KEY_SUPER_L: conv.result("SUPER_L"); break;
+       case KEY_SUPER_R: conv.result("SUPER_R"); break;
+       case KEY_CAPS_LOCK: conv.result("CAPS_LOCK"); break;
+       case KEY_SCROLL_LOCK: conv.result("SCROLL_LOCK"); break;
+       case KEY_NUM_LOCK: conv.result("NUM_LOCK"); break;
+       case KEY_KP0: conv.result("KP0"); break;
+       case KEY_KP1: conv.result("KP1"); break;
+       case KEY_KP2: conv.result("KP2"); break;
+       case KEY_KP3: conv.result("KP3"); break;
+       case KEY_KP4: conv.result("KP4"); break;
+       case KEY_KP5: conv.result("KP5"); break;
+       case KEY_KP6: conv.result("KP6"); break;
+       case KEY_KP7: conv.result("KP7"); break;
+       case KEY_KP8: conv.result("KP8"); break;
+       case KEY_KP9: conv.result("KP9"); break;
+       case KEY_KP_ADD: conv.result("KP_ADD"); break;
+       case KEY_KP_SUBTRACT: conv.result("KP_SUBTRACT"); break;
+       case KEY_KP_MULTIPLY: conv.result("KP_MULTIPLY"); break;
+       case KEY_KP_DIVIDE: conv.result("KP_DIVIDE"); break;
+       case KEY_KP_SEPARATOR: conv.result("KP_SEPARATOR"); break;
+       case KEY_PAUSE: conv.result("PAUSE"); break;
+       case KEY_PRINT_SCREEN: conv.result("PRINT_SCREEN"); break;
+       case KEY_MENU: conv.result("MENU"); break;
+       case KEY_BACK: conv.result("BACK"); break;
+       case KEY_VOLUME_UP: conv.result("VOLUME_UP"); break;
+       case KEY_VOLUME_DOWN: conv.result("VOLUME_DOWN"); break;
+       default: conv.result(format("Key(%#x)", static_cast<int>(key)));
+       }
+}
+
+void operator>>(const LexicalConverter &conv, MouseAxis &axis)
+{
+       if(conv.get()=="X")
+               axis = MOUSE_X_AXIS;
+       else if(conv.get()=="Y")
+               axis = MOUSE_Y_AXIS;
+       else
+               throw lexical_error(format("conversion of '%s' to MouseAxis", conv.get()));
+}
+
+void operator<<(LexicalConverter &conv, MouseAxis axis)
+{
+       switch(axis)
+       {
+       case MOUSE_X_AXIS: conv.result("X"); break;
+       case MOUSE_Y_AXIS: conv.result("Y"); break;
+       default: conv.result(format("MouseAxis(%#x)", static_cast<int>(axis)));
+       }
+}
+
+void operator>>(const LexicalConverter &conv, MouseButton &btn)
+{
+       if(conv.get()=="LEFT")
+               btn = MOUSE_LEFT;
+       else if(conv.get()=="MIDDLE")
+               btn = MOUSE_MIDDLE;
+       else if(conv.get()=="RIGHT")
+               btn = MOUSE_RIGHT;
+       else if(conv.get()=="WHEEL_UP")
+               btn = MOUSE_WHEEL_UP;
+       else if(conv.get()=="WHEEL_DOWN")
+               btn = MOUSE_WHEEL_DOWN;
+       else
+               throw lexical_error(format("conversion of '%s' to MouseButton", conv.get()));
+}
+
+void operator<<(LexicalConverter &conv, MouseButton btn)
+{
+       switch(btn)
+       {
+       case MOUSE_LEFT: conv.result("LEFT"); break;
+       case MOUSE_MIDDLE: conv.result("MIDDLE"); break;
+       case MOUSE_RIGHT: conv.result("RIGHT"); break;
+       case MOUSE_WHEEL_UP: conv.result("WHEEL_UP"); break;
+       case MOUSE_WHEEL_DOWN: conv.result("WHEEL_DOWN"); break;
+       default: conv.result(format("MouseButton(%#x)", static_cast<int>(btn)));
+       }
 }
 
 } // namespace Input