Re: [AD] keyconf

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Heh, I just wrote a long paragraph describing some of the intriguing
facts I found out in the last days and especially today about things
like WM_CHAR, directinput, unicode in win98, tiny hidden notes in the
MSDN docs, and other things, but deleted it again :) Instead, just,
attached is a version of the dinput keyboard which supports dead keys.
The trick to make it work was simply not calling TranslateMessage.

Hm, and I also have an almost working WM_CHAR driver now (the reason
was explained in the deleted story above :P), so maybe we can have two
drivers, a dinput one and a WM_CHAR one.
Index: src/win/wkeybd.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/win/wkeybd.c,v
retrieving revision 1.28
diff -u -r1.28 wkeybd.c
--- src/win/wkeybd.c	14 Mar 2005 11:29:15 -0000	1.28
+++ src/win/wkeybd.c	18 Mar 2005 19:39:28 -0000
@@ -1,6 +1,6 @@
-/*         ______   ___    ___ 
- *        /\  _  \ /\_ \  /\_ \ 
- *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
@@ -10,7 +10,7 @@
  *
  *      Windows keyboard driver.
  *
- *      By Stefan Schimanski.
+ *      By Stefan Schimanski, hacked up by Peter Wang and Elias Pschernig.
  *
  *      See readme.txt for copyright information.
  */
@@ -64,36 +64,6 @@
    _pckey_scancode_to_name
 };
 
-/* Map Windows keyboard IDs to Allegro ID strings */
-typedef struct {
-    unsigned int code;
-    char* name;
-} language_map_t;
-
-static language_map_t language_map[] = {
-    { 0x0813, "BE" },
-    { 0x0416, "BR" },
-    { 0x1009, "CF" },
-    { 0x0807, "CH" },
-    { 0x0405, "CZ" },
-    { 0x0407, "DE" },
-    { 0x0406, "DK" },
-    { 0x040a, "ES" },
-    { 0x040b, "FI" },
-    { 0x040c, "FR" },
-    { 0x0410, "IT" },
-    { 0x0414, "NO" },
-    { 0x0415, "PL" },
-    { 0x0416, "PT" },
-    { 0x0816, "PT" },
-    { 0x0419, "RU" },
-    { 0x041d, "SE" },
-    { 0x041b, "SK" },
-    { 0x0424, "SK" },
-    { 0x0809, "UK" },
-    { 0x0409, "US" },
-    { 0, NULL }    
-};
 
 #define DINPUT_BUFFERSIZE 256
 static HANDLE key_input_event = NULL;
@@ -102,6 +72,75 @@
 static LPDIRECTINPUTDEVICE key_dinput_device = NULL;
 
 
+/* lookup table for converting DIK_* scancodes into Allegro KEY_* codes */
+/* this table was from pckeys.c  */
+static const unsigned char hw_to_mycode[256] = {
+   /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
+   /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
+   /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
+   /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
+   /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
+   /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
+   /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
+   /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
+   /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
+   /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
+   /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
+   /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
+   /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
+   /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
+   /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
+   /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
+   /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
+   /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
+   /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
+   /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
+   /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
+   /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
+   /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
+   /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
+   /* 0x60 */ 0, 0, 0, 0,
+   /* 0x64 */ 0, 0, 0, 0,
+   /* 0x68 */ 0, 0, 0, 0,
+   /* 0x6C */ 0, 0, 0, 0,
+   /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
+   /* 0x74 */ 0, 0, 0, 0,
+   /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
+   /* 0x7C */ 0, KEY_YEN, 0, 0,
+   /* 0x80 */ 0, 0, 0, 0,
+   /* 0x84 */ 0, 0, 0, 0,
+   /* 0x88 */ 0, 0, 0, 0,
+   /* 0x8C */ 0, 0, 0, 0,
+   /* 0x90 */ 0, KEY_AT, KEY_COLON2, 0,
+   /* 0x94 */ KEY_KANJI, 0, 0, 0,
+   /* 0x98 */ 0, 0, 0, 0,
+   /* 0x9C */ KEY_ENTER_PAD, KEY_RCONTROL, 0, 0,
+   /* 0xA0 */ 0, 0, 0, 0,
+   /* 0xA4 */ 0, 0, 0, 0,
+   /* 0xA8 */ 0, 0, 0, 0,
+   /* 0xAC */ 0, 0, 0, 0,
+   /* 0xB0 */ 0, 0, 0, 0,
+   /* 0xB4 */ 0, KEY_SLASH_PAD, 0, KEY_PRTSCR,
+   /* 0xB8 */ KEY_ALTGR, 0, 0, 0,
+   /* 0xBC */ 0, 0, 0, 0,
+   /* 0xC0 */ 0, 0, 0, 0,
+   /* 0xC4 */ 0, KEY_PAUSE, 0, KEY_HOME,
+   /* 0xC8 */ KEY_UP, KEY_PGUP, 0, KEY_LEFT,
+   /* 0xCC */ 0, KEY_RIGHT, 0, KEY_END,
+   /* 0xD0 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
+   /* 0xD4 */ 0, 0, 0, 0,
+   /* 0xD8 */ 0, 0, 0, KEY_LWIN,
+   /* 0xDC */ KEY_RWIN, KEY_MENU, 0, 0,
+   /* 0xE0 */ 0, 0, 0, 0,
+   /* 0xE4 */ 0, 0, 0, 0,
+   /* 0xE8 */ 0, 0, 0, 0,
+   /* 0xEC */ 0, 0, 0, 0,
+   /* 0xF0 */ 0, 0, 0, 0,
+   /* 0xF4 */ 0, 0, 0, 0,
+   /* 0xF8 */ 0, 0, 0, 0,
+   /* 0xFC */ 0, 0, 0, 0
+};
+
 
 /* dinput_err_str:
  *  Returns a DirectInput error string.
@@ -142,6 +181,148 @@
 #define dinput_err_str(hr) "\0"
 #endif
 
+/* Update the key_shifts.
+ */
+static void update_shifts(BYTE * keystate)
+{
+   /* TODO: There must be a more efficient way to maintain key_modifiers? */
+   /* Can't we just deprecate key_shifts, now that pckeys.c is gone? EP */
+   unsigned int modifiers = 0;
+
+   if ((keystate[VK_LSHIFT] & 0x80) || (keystate[VK_RSHIFT] & 0x80))
+      modifiers |= KB_SHIFT_FLAG;
+   if ((keystate[VK_LCONTROL] & 0x80) || (keystate[VK_RCONTROL] & 0x80))
+      modifiers |= KB_CTRL_FLAG;
+   if (keystate[VK_LMENU] & 0x80 || keystate[VK_RMENU] & 0x80)
+      modifiers |= KB_ALT_FLAG;
+   if (keystate[VK_SCROLL] & 1)
+      modifiers |= KB_SCROLOCK_FLAG;
+   if (keystate[VK_NUMLOCK] & 1)
+      modifiers |= KB_NUMLOCK_FLAG;
+   if (keystate[VK_CAPITAL] & 1)
+      modifiers |= KB_CAPSLOCK_FLAG;
+
+   _key_shifts = modifiers;
+
+}
+
+
+
+/* handle_key_press: [input thread]
+ *  Does stuff when a key is pressed.
+ */
+static void handle_key_press(unsigned char scancode)
+{
+   int mycode;
+   int unicode;
+   unsigned int modifiers;
+   int n;
+
+   mycode = hw_to_mycode[scancode];
+   if (mycode == 0)
+      return;
+
+   /* TODO: clean this up */
+   {
+      UINT vkey;
+      BYTE keystate[256];
+      WCHAR chars[16];
+
+      vkey = MapVirtualKey(scancode, 1);
+      GetKeyboardState(keystate);
+
+      update_shifts(keystate);
+
+      /* what's life without a few special cases */
+      if (keystate[VK_NUMLOCK] & 1) {
+         switch (scancode) {
+            case DIK_NUMPAD0:
+               vkey = VK_NUMPAD0;
+               break;
+            case DIK_NUMPAD1:
+               vkey = VK_NUMPAD1;
+               break;
+            case DIK_NUMPAD2:
+               vkey = VK_NUMPAD2;
+               break;
+            case DIK_NUMPAD3:
+               vkey = VK_NUMPAD3;
+               break;
+            case DIK_NUMPAD4:
+               vkey = VK_NUMPAD4;
+               break;
+            case DIK_NUMPAD5:
+               vkey = VK_NUMPAD5;
+               break;
+            case DIK_NUMPAD6:
+               vkey = VK_NUMPAD6;
+               break;
+            case DIK_NUMPAD7:
+               vkey = VK_NUMPAD7;
+               break;
+            case DIK_NUMPAD8:
+               vkey = VK_NUMPAD8;
+               break;
+            case DIK_NUMPAD9:
+               vkey = VK_NUMPAD9;
+               break;
+            case DIK_DECIMAL:
+               vkey = VK_DECIMAL;
+               break;
+         }
+      }
+      /* and a few more */
+      switch (scancode) {
+         case DIK_DIVIDE:
+            vkey = VK_DIVIDE;
+            break;
+         case DIK_MULTIPLY:
+            vkey = VK_MULTIPLY;
+            break;
+         case DIK_SUBTRACT:
+            vkey = VK_SUBTRACT;
+            break;
+         case DIK_ADD:
+            vkey = VK_ADD;
+            break;
+         case DIK_NUMPADENTER:
+            vkey = VK_RETURN;
+            break;
+      }
+
+      /* Nice, seems Windows has a function to just get the unicode character. */
+      n = ToUnicode(vkey, scancode, keystate, chars, sizeof chars, 0);
+      if (n == 1)
+      {
+         unicode = chars[0];
+      }
+      else
+         unicode = 0;
+   }
+   _handle_key_press(unicode, mycode);
+}
+
+
+
+/* handle_key_release: [input thread]
+ *  Does stuff when a key is released.  The keyboard event source
+ *  should be locked.
+ */
+static void handle_key_release(unsigned char scancode)
+{
+   int mycode = hw_to_mycode[scancode];
+   if (mycode == 0)
+      return;
+
+   {
+      BYTE keystate[256];
+      GetKeyboardState(keystate);
+      update_shifts(keystate);
+   }
+
+   _handle_key_release(mycode);
+}
+
 
 
 /* key_dinput_handle_scancode: [input thread]
@@ -170,44 +351,13 @@
           && ((_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG))
           && three_finger_flag) {
          _TRACE("Terminating application\n");
-         ExitProcess(0);  /* unsafe */
-      }
-
-      /* emulate PAUSE scancode sequence */
-      if (scancode == DIK_PAUSE) {
-	 int i;
-
-	 /* DirectInput appears to get DIK_PAUSED events when the app
-	  * loses focus, with pressed = false.  Don't pass these fake
-	  * events on, or they will end up in the readkey() buffer
-	  * when the app regains focus.  I didn't find any reference
-	  * to any such behaviour on the net, though... --pw
-	  */
-	 if (!_key[KEY_PAUSE] && !pressed) /* hacky */
-	    return;
-
-	 _handle_pckey(0xE1);
-	 for (i=0; i < 5; i++)
-	    _handle_pckey(0);
-
-         return;
+         ExitProcess(0);        /* unsafe */
       }
 
-      /* dirty hack to let Allegro for Windows use the DOS/Linux way of handling CapsLock */
-      /* Disabled - it doesn't seem to be nescessary anymore (?) */
-      /*
-      if (((scancode == DIK_CAPITAL) || (scancode == DIK_LSHIFT) || (scancode == DIK_RSHIFT))
-          && pressed
-          && (_key_shifts & KB_CAPSLOCK_FLAG)) {
-         keybd_event(VK_CAPITAL, 0, 0, 0);
-         keybd_event(VK_CAPITAL, 0, KEYEVENTF_KEYUP, 0);
-      }
-      */
-
-      if (scancode & 0x80)
-	 _handle_pckey(0xE0);
-
-      _handle_pckey((scancode & 0x7F) | (pressed ? 0 : 0x80));
+      if (pressed)
+         handle_key_press(scancode);
+      else
+         handle_key_release(scancode);
    }
 }
 
@@ -430,28 +580,6 @@
  */
 static int key_directx_init(void)
 {
-   char buffer[KL_NAMELENGTH+1];
-   unsigned int lang_id;
-   int i;
-   
-   /* Detect default keyboard layout */
-   if (GetKeyboardLayoutName(buffer)) {
-      lang_id = strtol(buffer, NULL, 16);
-      lang_id &= 0xffff;
-      for (i=0; language_map[i].code; i++) {
-         if (language_map[i].code == lang_id) {
-            _keyboard_layout = language_map[i].name;
-            break;
-         }
-      }
-   }
-   
-   /* Because DirectInput uses the same scancodes as the pc keyboard
-    * controller, the DirectX keyboard driver passes them into the
-    * pckeys translation routines.
-    */
-   _pckeys_init();
-
    /* keyboard input is handled by the window thread */
    key_input_processed_event = CreateEvent(NULL, FALSE, FALSE, NULL);
 
Index: src/win/wwnd.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/win/wwnd.c,v
retrieving revision 1.86
diff -u -r1.86 wwnd.c
--- src/win/wwnd.c	11 Mar 2005 19:13:40 -0000	1.86
+++ src/win/wwnd.c	18 Mar 2005 19:37:11 -0000
@@ -456,7 +456,6 @@
          /* messages are waiting in the queue */
          while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
             if (GetMessage(&msg, NULL, 0, 0)) {
-               TranslateMessage(&msg);
                DispatchMessage(&msg);
             }
             else {


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/