Re: [AD] Keyconf problem?

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


> 
> Anyone feel up to this?
> 

Well, I'm in windows right now, and tried it. Attached is a quick
attempt to backport Peter's keyboardnu.c, and indeed, this was quite
simple to backport. It has lots of problems still, e.g. only ASCII,
and no combined keys supported. And I didn't test it at all except
with exkeys. But maybe there's some light at the end of the tunnel..
and we may be able to have proper keyboard handling under windows.

So, now.. I'll go back to linux :)
--- C:\Dokumente und Einstellungen\root\Lokale Einstellungen\Temp\TCV83.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	Mon Mar 07 23:44:26 2005
@@ -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,145 @@
 #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 ascii;
+   unsigned int modifiers;
+
+   mycode = hw_to_mycode[scancode];
+   if (mycode == 0)
+      return;
+
+   /* TODO: clean this up */
+   {
+      UINT vkey;
+      BYTE keystate[256];
+      BYTE chars[2];
+
+      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;
+      }
+
+      /* ascii */
+      if (ToAscii(vkey, scancode, keystate, (WORD *) chars, 0) == 1)
+	 ascii = chars[0];
+      else
+	 ascii = 0;
+   }
+
+   _handle_key_press(ascii, 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 +342,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 */
+	  && ((_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);
-      }
-      */
-
-      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 +574,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/