Re: [AD] Keyconf problem?

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


Ok, just looked at it again, and simply replacing ToAscii with
ToUnicode solves the unicode problem. Patch updated. So I'd say, if
testing doesn't reveal additional problems, the patch would be ok for
4.2.0. In that case, I'll also add scancode_to_name and mark all
mentions of keyboard.dat/keyconf.exe in and so on in the docs as
DOS-only.

The problems that remain:
- no dead keys
- user/OS repeat settings are ignored

Both of which probably can't be solved with a DirectInput driver - so
the solution would be to write a driver who can utilize the WM_CHAR
messages or something like that.
--- C:\Dokumente und Einstellungen\root\Lokale Einstellungen\Temp\TCV12.tmp\wkeybd.1.27.c	Fri Dec 03 21:56:27 2004
+++ C:\Dokumente und Einstellungen\root\Eigene Dateien\prog\allegro-cvs\src\win\wkeybd.c	Tue Mar 08 14:20:33 2005
@@ -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.
  */
@@ -61,36 +61,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;
@@ -99,6 +69,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.
@@ -139,6 +178,150 @@
 #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)
+      {
+         /* Additional characters are dropped, since I'm not sure when exactly this occurs. */
+	 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]
@@ -164,47 +347,16 @@
 
       /* three-finger salute for killing the program */
       if (((scancode == DIK_END) || (scancode == DIK_NUMPAD1))
-          && ((_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;
-      }
-
-      /* 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);
+	  && ((_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG))
+	  && three_finger_flag) {
+	 _TRACE("Terminating application\n");
+	 ExitProcess(0);	/* unsafe */
       }
-      */
 
-      if (scancode & 0x80)
-	 _handle_pckey(0xE0);
-
-      _handle_pckey((scancode & 0x7F) | (pressed ? 0 : 0x80));
+      if (pressed)
+	 handle_key_press(scancode);
+      else
+	 handle_key_release(scancode);
    }
 }
 
@@ -427,28 +579,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);
 


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