mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-04 05:50:15 +00:00
Modify Allegro to use WM_KEYUP/DOWN messages instead of DirectInput.
This commit is contained in:
parent
57b54ad050
commit
a877d52048
@ -4,3 +4,5 @@ patched for ASE by David Capello.
|
||||
Changes:
|
||||
- Mouse driver for Windows was modified to use WM_MOUSEMOVE instead of
|
||||
DirectInput (like in Allegro 5).
|
||||
- Keyboard driver for Windows was modified to use WM_KEYDOWN/UP messages
|
||||
instead of DirectInput (like in Allegro 5).
|
||||
|
@ -120,10 +120,6 @@ AL_FUNC(int, _win_input_register_event, (HANDLE event_id, void (*event_handler)(
|
||||
AL_FUNC(void, _win_input_unregister_event, (HANDLE event_id));
|
||||
|
||||
|
||||
/* keyboard routines */
|
||||
AL_FUNC(int, key_dinput_acquire, (void));
|
||||
AL_FUNC(int, key_dinput_unacquire, (void));
|
||||
|
||||
|
||||
/* mouse routines */
|
||||
AL_VAR(HCURSOR, _win_hcursor);
|
||||
|
@ -77,12 +77,6 @@ AL_VAR(SYSTEM_DRIVER, system_directx);
|
||||
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/************ keyboard drivers *************/
|
||||
/*******************************************/
|
||||
#define KEYBOARD_DIRECTX AL_ID('D','X',' ',' ')
|
||||
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/*************** gfx drivers ***************/
|
||||
|
@ -82,8 +82,6 @@ typedef struct WIN_GFX_DRIVER {
|
||||
|
||||
AL_VAR(WIN_GFX_DRIVER *, win_gfx_driver);
|
||||
|
||||
AL_FUNC(void, win_grab_input, (void));
|
||||
|
||||
|
||||
/* external window support */
|
||||
AL_FUNC(HWND, win_get_window, (void));
|
||||
|
@ -237,9 +237,6 @@ static void finalize_fullscreen_init(void)
|
||||
|
||||
/* set the default switching policy */
|
||||
set_display_switch_mode(SWITCH_AMNESIA);
|
||||
|
||||
/* grab input devices */
|
||||
win_grab_input();
|
||||
}
|
||||
|
||||
|
||||
|
@ -404,9 +404,6 @@ static struct BITMAP *init_directx_ovl(int w, int h, int v_w, int v_h, int color
|
||||
/* set default switching policy */
|
||||
set_display_switch_mode(SWITCH_PAUSE);
|
||||
|
||||
/* grab input devices */
|
||||
win_grab_input();
|
||||
|
||||
_exit_critical();
|
||||
|
||||
return gfx_directx_forefront_bitmap;
|
||||
|
@ -772,9 +772,6 @@ static struct BITMAP *init_directx_win(int w, int h, int v_w, int v_h, int color
|
||||
/* set default switching policy */
|
||||
set_display_switch_mode(SWITCH_PAUSE);
|
||||
|
||||
/* grab input devices */
|
||||
win_grab_input();
|
||||
|
||||
_exit_critical();
|
||||
|
||||
return gfx_directx_forefront_bitmap;
|
||||
|
@ -113,8 +113,6 @@ void _win_switch_in(void)
|
||||
|
||||
_win_app_foreground = TRUE;
|
||||
|
||||
key_dinput_acquire();
|
||||
|
||||
if (win_gfx_driver && win_gfx_driver->switch_in)
|
||||
win_gfx_driver->switch_in();
|
||||
|
||||
@ -145,8 +143,6 @@ void _win_switch_out(void)
|
||||
|
||||
_win_app_foreground = FALSE;
|
||||
|
||||
key_dinput_unacquire();
|
||||
|
||||
if (win_gfx_driver && win_gfx_driver->switch_out)
|
||||
win_gfx_driver->switch_out();
|
||||
|
||||
|
@ -513,9 +513,6 @@ static struct BITMAP *gfx_gdi_init(int w, int h, int v_w, int v_h, int color_dep
|
||||
/* set the default switching policy */
|
||||
set_display_switch_mode(SWITCH_PAUSE);
|
||||
|
||||
/* grab input devices */
|
||||
win_grab_input();
|
||||
|
||||
_exit_critical();
|
||||
|
||||
return gdi_screen;
|
||||
|
@ -1,32 +1,15 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Windows keyboard driver.
|
||||
*
|
||||
* By Stefan Schimanski, hacked up by Peter Wang and Elias Pschernig.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
/*
|
||||
Mouse driver for ASE
|
||||
by David Capello
|
||||
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x0300
|
||||
Based on code of Stefan Schimanski, Peter Wang, Elias Pschernig,
|
||||
and Milan Mimica.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintwin.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#include <process.h>
|
||||
#include <dinput.h>
|
||||
#endif
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
@ -36,130 +19,86 @@
|
||||
#define PREFIX_E "al-wkey ERROR: "
|
||||
|
||||
|
||||
#define DINPUT_BUFFERSIZE 256
|
||||
static HANDLE key_input_event = NULL;
|
||||
static HANDLE key_input_processed_event = NULL;
|
||||
static LPDIRECTINPUT key_dinput = NULL;
|
||||
static LPDIRECTINPUTDEVICE key_dinput_device = NULL;
|
||||
|
||||
#define KEY_UNKNOWN KEY_MAX
|
||||
|
||||
|
||||
/* 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
|
||||
};
|
||||
|
||||
/* Used in scancode_to_name. */
|
||||
static LONG reverse_mapping[KEY_MAX];
|
||||
|
||||
|
||||
/* dinput_err_str:
|
||||
* Returns a DirectInput error string.
|
||||
*/
|
||||
#ifdef DEBUGMODE
|
||||
static char* dinput_err_str(long err)
|
||||
/* lookup table for converting virtualkey VK_* codes into Allegro KEY_* codes */
|
||||
/* Last unknown key sequence: 39*/
|
||||
static const unsigned char hw_to_mycode[256] =
|
||||
{
|
||||
static char err_str[64];
|
||||
/* 0x00 */ 0, KEY_UNKNOWN+0, KEY_UNKNOWN+1, KEY_UNKNOWN+2,
|
||||
/* 0x04 */ KEY_UNKNOWN+3, KEY_UNKNOWN+4, KEY_UNKNOWN+5, 0,
|
||||
/* 0x08 */ KEY_BACKSPACE, KEY_TAB, 0, 0,
|
||||
/* 0x0C */ KEY_UNKNOWN+39, KEY_ENTER, 0, 0,
|
||||
/* 0x10 */ 0/*L or R shift*/, 0/*L or R ctrl*/, 0/*L or R alt*/, KEY_PAUSE,
|
||||
/* 0x14 */ KEY_CAPSLOCK, KEY_KANA, 0, KEY_UNKNOWN+6,
|
||||
/* 0x18 */ KEY_UNKNOWN+7, KEY_KANJI, 0, KEY_ESC,
|
||||
/* 0x1C */ KEY_CONVERT, KEY_NOCONVERT, KEY_UNKNOWN+8, KEY_UNKNOWN+9,
|
||||
/* 0x20 */ KEY_SPACE, KEY_PGUP, KEY_PGDN, KEY_END,
|
||||
/* 0x24 */ KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT,
|
||||
/* 0x28 */ KEY_DOWN, KEY_UNKNOWN+10, KEY_UNKNOWN+11, KEY_UNKNOWN+12,
|
||||
/* 0x2C */ KEY_PRTSCR, KEY_INSERT, KEY_DEL, KEY_UNKNOWN+13,
|
||||
/* 0x30 */ KEY_0, KEY_1, KEY_2, KEY_3,
|
||||
/* 0x34 */ KEY_4, KEY_5, KEY_6, KEY_7,
|
||||
/* 0x38 */ KEY_8, KEY_9, 0, 0,
|
||||
/* 0x3C */ 0, 0, 0, 0,
|
||||
/* 0x40 */ 0, KEY_A, KEY_B, KEY_C,
|
||||
/* 0x44 */ KEY_D, KEY_E, KEY_F, KEY_G,
|
||||
/* 0x48 */ KEY_H, KEY_I, KEY_J, KEY_K,
|
||||
/* 0x4C */ KEY_L, KEY_M, KEY_N, KEY_O,
|
||||
/* 0x50 */ KEY_P, KEY_Q, KEY_R, KEY_S,
|
||||
/* 0x54 */ KEY_T, KEY_U, KEY_V, KEY_W,
|
||||
/* 0x58 */ KEY_X, KEY_Y, KEY_Z, KEY_LWIN,
|
||||
/* 0x5C */ KEY_RWIN, KEY_UNKNOWN+14, 0, 0,
|
||||
/* 0x60 */ KEY_0_PAD, KEY_1_PAD, KEY_2_PAD, KEY_3_PAD,
|
||||
/* 0x64 */ KEY_4_PAD, KEY_5_PAD, KEY_6_PAD, KEY_7_PAD,
|
||||
/* 0x68 */ KEY_8_PAD, KEY_9_PAD, KEY_ASTERISK, KEY_PLUS_PAD,
|
||||
/* 0x6C */ KEY_UNKNOWN+15, KEY_MINUS_PAD, KEY_UNKNOWN+16, KEY_SLASH_PAD,
|
||||
/* 0x70 */ KEY_F1, KEY_F2, KEY_F3, KEY_F4,
|
||||
/* 0x74 */ KEY_F5, KEY_F6, KEY_F7, KEY_F8,
|
||||
/* 0x78 */ KEY_F9, KEY_F10, KEY_F11, KEY_F12,
|
||||
/* 0x7C */ KEY_UNKNOWN+17, KEY_UNKNOWN+18, KEY_UNKNOWN+19, KEY_UNKNOWN+20,
|
||||
/* 0x80 */ KEY_UNKNOWN+21, KEY_UNKNOWN+22, KEY_UNKNOWN+23, KEY_UNKNOWN+24,
|
||||
/* 0x84 */ KEY_UNKNOWN+25, KEY_UNKNOWN+26, KEY_UNKNOWN+27, KEY_UNKNOWN+28,
|
||||
/* 0x88 */ 0, 0, 0, 0,
|
||||
/* 0x8C */ 0, 0, 0, 0,
|
||||
/* 0x90 */ KEY_NUMLOCK, KEY_SCRLOCK, 0, 0,
|
||||
/* 0x94 */ 0, 0, 0, 0,
|
||||
/* 0x98 */ 0, 0, 0, 0,
|
||||
/* 0x9C */ 0, 0, 0, 0,
|
||||
/* 0xA0 */ KEY_LSHIFT, KEY_RSHIFT, KEY_LCONTROL, KEY_RCONTROL,
|
||||
/* 0xA4 */ KEY_ALT, KEY_ALTGR, 0, 0,
|
||||
/* 0xA8 */ 0, 0, 0, 0,
|
||||
/* 0xAC */ 0, 0, 0, 0,
|
||||
/* 0xB0 */ 0, 0, 0, 0,
|
||||
/* 0xB4 */ 0, 0, 0, 0,
|
||||
/* 0xB8 */ 0, 0, KEY_SEMICOLON, KEY_EQUALS,
|
||||
/* 0xBC */ KEY_COMMA, KEY_MINUS, KEY_STOP, KEY_SLASH,
|
||||
/* 0xC0 */ KEY_TILDE, 0, 0, 0,
|
||||
/* 0xC4 */ 0, 0, 0, 0,
|
||||
/* 0xC8 */ 0, 0, 0, 0,
|
||||
/* 0xCC */ 0, 0, 0, 0,
|
||||
/* 0xD0 */ 0, 0, 0, 0,
|
||||
/* 0xD4 */ 0, 0, 0, 0,
|
||||
/* 0xD8 */ 0, 0, 0, KEY_OPENBRACE,
|
||||
/* 0xDC */ KEY_BACKSLASH, KEY_CLOSEBRACE, KEY_QUOTE, 0,
|
||||
/* 0xE0 */ 0, 0, KEY_BACKSLASH2, 0,
|
||||
/* 0xE4 */ 0, KEY_UNKNOWN+29, 0, 0,
|
||||
/* 0xE8 */ 0, 0, 0, 0,
|
||||
/* 0xEC */ 0, 0, 0, 0,
|
||||
/* 0xF0 */ 0, 0, 0, 0,
|
||||
/* 0xF4 */ 0, 0, KEY_UNKNOWN+30, KEY_UNKNOWN+31,
|
||||
/* 0xF8 */ KEY_UNKNOWN+32, KEY_UNKNOWN+33, KEY_UNKNOWN+34, KEY_UNKNOWN+35,
|
||||
/* 0xFC */ KEY_UNKNOWN+36, KEY_UNKNOWN+37, KEY_UNKNOWN+38, 0
|
||||
};
|
||||
|
||||
switch (err) {
|
||||
|
||||
case DIERR_NOTACQUIRED:
|
||||
_al_sane_strncpy(err_str, "the device is not acquired", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DIERR_INPUTLOST:
|
||||
_al_sane_strncpy(err_str, "access to the device was lost", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DIERR_INVALIDPARAM:
|
||||
_al_sane_strncpy(err_str, "the device does not have a selected data format", sizeof(err_str));
|
||||
break;
|
||||
|
||||
#ifdef DIERR_OTHERAPPHASPRIO
|
||||
/* this is not a legacy DirectX 3 error code */
|
||||
case DIERR_OTHERAPPHASPRIO:
|
||||
_al_sane_strncpy(err_str, "can't acquire the device in background", sizeof(err_str));
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
_al_sane_strncpy(err_str, "unknown error", sizeof(err_str));
|
||||
}
|
||||
|
||||
return err_str;
|
||||
}
|
||||
#else
|
||||
#define dinput_err_str(hr) "\0"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Update the key_shifts.
|
||||
*/
|
||||
static void update_shifts(BYTE * keystate)
|
||||
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 */
|
||||
@ -180,654 +119,147 @@ static void update_shifts(BYTE * keystate)
|
||||
modifiers |= KB_CAPSLOCK_FLAG;
|
||||
|
||||
_key_shifts = modifiers;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* handle_key_press: [input thread]
|
||||
/* _al_win_kbd_handle_key_press:
|
||||
* Does stuff when a key is pressed.
|
||||
*/
|
||||
static void handle_key_press(unsigned char scancode)
|
||||
void _al_win_kbd_handle_key_press(int scode, int vcode, BOOL repeated)
|
||||
{
|
||||
int mycode;
|
||||
int unicode;
|
||||
int n;
|
||||
UINT vkey;
|
||||
BYTE keystate[256];
|
||||
WCHAR chars[16];
|
||||
int my_code;
|
||||
int ccode;
|
||||
BYTE ks[256];
|
||||
WCHAR buf[8];
|
||||
|
||||
vkey = MapVirtualKey(scancode, 1);
|
||||
|
||||
GetKeyboardState(keystate);
|
||||
update_shifts(keystate);
|
||||
|
||||
/* TODO: shouldn't we base the mapping on vkey? */
|
||||
mycode = hw_to_mycode[scancode];
|
||||
if (mycode == 0)
|
||||
return;
|
||||
|
||||
/* MapVirtualKey always returns the arrow key VKEY, so adjust
|
||||
it if num lock is on */
|
||||
if (keystate[VK_NUMLOCK]) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* what's life without a few special cases */
|
||||
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;
|
||||
}
|
||||
|
||||
/* TODO: is there an advantage using ToUnicode? maybe it would allow
|
||||
* Chinese and so on characters? For now, always ToAscii is used. */
|
||||
//n = ToUnicode(vkey, scancode, keystate, chars, 16, 0);
|
||||
n = ToAscii(vkey, scancode, keystate, (WORD *)chars, 0);
|
||||
if (n == 1)
|
||||
{
|
||||
WCHAR wstr[2];
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCSTR)chars, n, wstr, 2);
|
||||
unicode = wstr[0];
|
||||
}
|
||||
if (!GetKeyboardState(&ks[0]))
|
||||
ccode = 0; /* shound't really happen */
|
||||
else if (ToUnicode(vcode, scode, ks, buf, 8, 0) == 1)
|
||||
ccode = buf[0];
|
||||
else
|
||||
{
|
||||
/* Don't generate key presses for modifier keys or dead keys */
|
||||
if (mycode >= KEY_MODIFIERS || n != 0)
|
||||
unicode = -1;
|
||||
ccode = 0;
|
||||
|
||||
/* Windows doesn't differentiate between the left and right versions
|
||||
of the modifiers. To compensate we read the current keyboard state
|
||||
and use that information to determine which key was actually
|
||||
pressed. We check the last known state of the modifier in question
|
||||
and if it is not down we know that is the key that was pressed. */
|
||||
if (vcode == VK_SHIFT || vcode == VK_CONTROL || vcode == VK_MENU) {
|
||||
if ((ks[VK_LCONTROL] & 0x80) && !key[KEY_LCONTROL])
|
||||
vcode = VK_LCONTROL;
|
||||
else if ((ks[VK_RCONTROL] & 0x80) && !key[KEY_RCONTROL])
|
||||
vcode = VK_RCONTROL;
|
||||
else if ((ks[VK_LSHIFT] & 0x80) && !key[KEY_LSHIFT])
|
||||
vcode = VK_LSHIFT;
|
||||
else if ((ks[VK_RSHIFT] & 0x80) && !key[KEY_RSHIFT])
|
||||
vcode = VK_RSHIFT;
|
||||
else if ((ks[VK_LMENU] & 0x80) && !key[KEY_ALT])
|
||||
vcode = VK_LMENU;
|
||||
else if ((ks[VK_RMENU] & 0x80) && !key[KEY_ALTGR])
|
||||
vcode = VK_RMENU;
|
||||
else
|
||||
unicode = 0;
|
||||
}
|
||||
|
||||
/* When alt key is pressed, any key always must return ASCII 0 in Allegro. */
|
||||
if (unicode > 0 && (keystate[VK_LMENU] & 0x80)) {
|
||||
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]
|
||||
* Handles a single scancode.
|
||||
*/
|
||||
static void key_dinput_handle_scancode(unsigned char scancode, int pressed)
|
||||
{
|
||||
HWND allegro_wnd = win_get_window();
|
||||
static int ignore_three_finger_flag = FALSE;
|
||||
/* ignore special Windows keys (alt+tab, alt+space, (ctrl|alt)+esc) */
|
||||
if (((scancode == DIK_TAB) && (_key_shifts & KB_ALT_FLAG))
|
||||
|| ((scancode == DIK_SPACE) && (_key_shifts & KB_ALT_FLAG))
|
||||
|| ((scancode == DIK_ESCAPE) && (_key_shifts & (KB_CTRL_FLAG | KB_ALT_FLAG))))
|
||||
return;
|
||||
|
||||
/* alt+F4 triggers a WM_CLOSE under Windows */
|
||||
if ((scancode == DIK_F4) && (_key_shifts & KB_ALT_FLAG)) {
|
||||
if (pressed)
|
||||
PostMessage(allegro_wnd, WM_CLOSE, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Special case KEY_PAUSE as flip-flop key. */
|
||||
if (scancode == DIK_PAUSE) {
|
||||
if (!pressed)
|
||||
return;
|
||||
if (key[KEY_PAUSE])
|
||||
pressed = 0;
|
||||
else
|
||||
pressed = 1;
|
||||
}
|
||||
|
||||
/* if not foreground, filter out press codes and handle only release codes */
|
||||
if (!wnd_sysmenu || !pressed) {
|
||||
/* three-finger salute for killing the program */
|
||||
if (three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG)) {
|
||||
if (scancode == 0x00) {
|
||||
/* when pressing CTRL-ALT-DEL, Windows launches CTRL-ALT-EVERYTHING */
|
||||
ignore_three_finger_flag = TRUE;
|
||||
}
|
||||
else if (!ignore_three_finger_flag && (scancode == DIK_END || scancode == DIK_NUMPAD1)) {
|
||||
/* we can now safely assume the user hit CTRL-ALT-END as opposed to CTRL-ALT-DEL */
|
||||
_TRACE(PREFIX_I "Terminating application\n");
|
||||
abort();
|
||||
}
|
||||
else if (ignore_three_finger_flag && scancode == 0xff) {
|
||||
/* Windows is finished with CTRL-ALT-EVERYTHING - lets return to normality */
|
||||
ignore_three_finger_flag = FALSE;
|
||||
_key_shifts = 0;
|
||||
}
|
||||
}
|
||||
/* Ignore repeats for Caps Lock */
|
||||
if (vcode == VK_CAPITAL && repeated && key[KEY_CAPSLOCK])
|
||||
return;
|
||||
|
||||
if (pressed)
|
||||
handle_key_press(scancode);
|
||||
else
|
||||
handle_key_release(scancode);
|
||||
}
|
||||
my_code = hw_to_mycode[vcode];
|
||||
update_shifts(ks);
|
||||
|
||||
_handle_key_press(ccode, my_code);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_dinput_handle: [input thread]
|
||||
* Handles queued keyboard input.
|
||||
|
||||
/* _al_win_kbd_handle_key_release:
|
||||
* Does stuff when a key is released.
|
||||
*/
|
||||
static void key_dinput_handle(void)
|
||||
void _al_win_kbd_handle_key_release(int vcode)
|
||||
{
|
||||
static DIDEVICEOBJECTDATA scancode_buffer[DINPUT_BUFFERSIZE];
|
||||
unsigned long int waiting_scancodes;
|
||||
HRESULT hr;
|
||||
unsigned long int i;
|
||||
int my_code;
|
||||
BYTE ks[256];
|
||||
|
||||
/* the whole buffer is free */
|
||||
waiting_scancodes = DINPUT_BUFFERSIZE;
|
||||
/* We need to read the latest key states so we can tell which
|
||||
modifier was released. */
|
||||
GetKeyboardState(&ks[0]);
|
||||
|
||||
/* fill the buffer */
|
||||
hr = IDirectInputDevice_GetDeviceData(key_dinput_device,
|
||||
sizeof(DIDEVICEOBJECTDATA),
|
||||
scancode_buffer,
|
||||
&waiting_scancodes,
|
||||
0);
|
||||
if (vcode == VK_SHIFT && key[KEY_LSHIFT] && !(ks[VK_LSHIFT] & 0x80))
|
||||
vcode = VK_LSHIFT;
|
||||
else if (vcode == VK_SHIFT && key[KEY_RSHIFT] && !(ks[VK_RSHIFT] & 0x80))
|
||||
vcode = VK_RSHIFT;
|
||||
else if (vcode == VK_CONTROL && key[KEY_LCONTROL] && !(ks[VK_LCONTROL] & 0x80))
|
||||
vcode = VK_LCONTROL;
|
||||
else if (vcode == VK_CONTROL && key[KEY_RCONTROL] && !(ks[VK_RCONTROL] & 0x80))
|
||||
vcode = VK_RCONTROL;
|
||||
else if (vcode == VK_MENU && key[KEY_ALT] && !(ks[VK_LMENU] & 0x80))
|
||||
vcode = VK_LMENU;
|
||||
else if (vcode == VK_MENU && key[KEY_ALTGR] && !(ks[VK_RMENU] & 0x80))
|
||||
vcode = VK_RMENU;
|
||||
else if(vcode == VK_MENU)
|
||||
return;
|
||||
|
||||
/* was device lost ? */
|
||||
if ((hr == DIERR_NOTACQUIRED) || (hr == DIERR_INPUTLOST)) {
|
||||
/* reacquire device */
|
||||
_TRACE(PREFIX_W "keyboard device not acquired or lost\n");
|
||||
wnd_schedule_proc(key_dinput_acquire);
|
||||
}
|
||||
else if (FAILED(hr)) { /* other error? */
|
||||
_TRACE(PREFIX_E "unexpected error while filling keyboard scancode buffer\n");
|
||||
}
|
||||
else {
|
||||
/* normally only this case should happen */
|
||||
for (i = 0; i < waiting_scancodes; i++) {
|
||||
key_dinput_handle_scancode((unsigned char) scancode_buffer[i].dwOfs,
|
||||
scancode_buffer[i].dwData & 0x80);
|
||||
}
|
||||
}
|
||||
my_code = hw_to_mycode[vcode];
|
||||
update_shifts(ks);
|
||||
|
||||
SetEvent(key_input_processed_event);
|
||||
_handle_key_release(my_code);
|
||||
|
||||
/* Windows only sends a WM_KEYUP message for the Shift keys when
|
||||
both have been released. If one of the Shift keys is still reported
|
||||
as down, we need to release it as well. */
|
||||
if (my_code == KEY_LSHIFT && key[KEY_RSHIFT])
|
||||
_al_win_kbd_handle_key_release(VK_RSHIFT);
|
||||
else if (my_code == KEY_RSHIFT && key[KEY_LSHIFT])
|
||||
_al_win_kbd_handle_key_release(VK_LSHIFT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_dinput_acquire: [window thread]
|
||||
* Acquires the keyboard device. This must be called after a
|
||||
* window switch for example if the device is in foreground
|
||||
* cooperative level.
|
||||
*/
|
||||
int key_dinput_acquire(void)
|
||||
static int key_winapi_init(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
BYTE keystate[256];
|
||||
|
||||
if (key_dinput_device) {
|
||||
/* Read the current Windows keyboard state */
|
||||
GetKeyboardState(keystate);
|
||||
update_shifts(keystate);
|
||||
|
||||
hr = IDirectInputDevice_Acquire(key_dinput_device);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "acquire keyboard failed: %s\n", dinput_err_str(hr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize keyboard state */
|
||||
SetEvent(key_input_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_dinput_unacquire: [window thread]
|
||||
* Unacquires the keyboard device.
|
||||
*/
|
||||
int key_dinput_unacquire(void)
|
||||
{
|
||||
int key;
|
||||
|
||||
if (key_dinput_device) {
|
||||
IDirectInputDevice_Unacquire(key_dinput_device);
|
||||
|
||||
/* release all keys */
|
||||
for (key=0; key<256; key++)
|
||||
if (key != KEY_PAUSE)
|
||||
key_dinput_handle_scancode((unsigned char) key, FALSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_dinput_exit: [primary thread]
|
||||
* Shuts down the DirectInput keyboard device.
|
||||
*/
|
||||
static int key_dinput_exit(void)
|
||||
{
|
||||
if (key_dinput_device) {
|
||||
/* unregister event handler first */
|
||||
_win_input_unregister_event(key_input_event);
|
||||
|
||||
/* unacquire device */
|
||||
wnd_call_proc(key_dinput_unacquire);
|
||||
|
||||
/* now it can be released */
|
||||
IDirectInputDevice_Release(key_dinput_device);
|
||||
key_dinput_device = NULL;
|
||||
}
|
||||
|
||||
/* release DirectInput interface */
|
||||
if (key_dinput) {
|
||||
IDirectInput_Release(key_dinput);
|
||||
key_dinput = NULL;
|
||||
}
|
||||
|
||||
/* close event handle */
|
||||
if (key_input_event) {
|
||||
CloseHandle(key_input_event);
|
||||
key_input_event = NULL;
|
||||
}
|
||||
BYTE ks[256];
|
||||
GetKeyboardState(&ks[0]);
|
||||
update_shifts(ks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get_reverse_mapping:
|
||||
* Build a table that maps Allegro "scancodes" to arguments to
|
||||
* GetKeyNameText() that will return the name of the key.
|
||||
* The format of the argument is given in the MSDN library, e.g. the
|
||||
* `lparam' argument for the WM_KEYDOWN message. Most importantly:
|
||||
* bits 16-23:
|
||||
* Specifies the scan code.
|
||||
* bit 24:
|
||||
* Specifies whether the key is an extended key, such as the right-hand
|
||||
* ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard.
|
||||
* The value is 1 if it is an extended key; otherwise, it is 0.
|
||||
*
|
||||
* We used to attempt to derive this table from `hw_to_mycode' but it is not
|
||||
* straight forward. For example to get the name of the right Ctrl key we
|
||||
* need to pass the same scancode as for the left Ctrl key, but with the
|
||||
* extended key flag set. The values below come from printing out the
|
||||
* value of the `lparam' argument for each WM_KEYDOWN message received.
|
||||
* There is code in wwnd.c to help someone else do this for more keys.
|
||||
*/
|
||||
static void get_reverse_mapping(void)
|
||||
static void key_winapi_exit(void)
|
||||
{
|
||||
#define REV reverse_mapping
|
||||
|
||||
REV[KEY_A] = 0x01E0000;
|
||||
REV[KEY_B] = 0x0300000;
|
||||
REV[KEY_C] = 0x02E0000;
|
||||
REV[KEY_D] = 0x0200000;
|
||||
REV[KEY_E] = 0x0120000;
|
||||
REV[KEY_F] = 0x0210000;
|
||||
REV[KEY_G] = 0x0220000;
|
||||
REV[KEY_H] = 0x0230000;
|
||||
REV[KEY_I] = 0x0170000;
|
||||
REV[KEY_J] = 0x0240000;
|
||||
REV[KEY_K] = 0x0250000;
|
||||
REV[KEY_L] = 0x0260000;
|
||||
REV[KEY_M] = 0x0320000;
|
||||
REV[KEY_N] = 0x0310000;
|
||||
REV[KEY_O] = 0x0180000;
|
||||
REV[KEY_P] = 0x0190000;
|
||||
REV[KEY_Q] = 0x0100000;
|
||||
REV[KEY_R] = 0x0130000;
|
||||
REV[KEY_S] = 0x01F0000;
|
||||
REV[KEY_T] = 0x0140000;
|
||||
REV[KEY_U] = 0x0160000;
|
||||
REV[KEY_V] = 0x02F0000;
|
||||
REV[KEY_W] = 0x0110000;
|
||||
REV[KEY_X] = 0x02D0000;
|
||||
REV[KEY_Y] = 0x0150000;
|
||||
REV[KEY_Z] = 0x02C0000;
|
||||
REV[KEY_0] = 0x00B0000;
|
||||
REV[KEY_1] = 0x0020000;
|
||||
REV[KEY_2] = 0x0030000;
|
||||
REV[KEY_3] = 0x0040000;
|
||||
REV[KEY_4] = 0x0050000;
|
||||
REV[KEY_5] = 0x0060000;
|
||||
REV[KEY_6] = 0x0070000;
|
||||
REV[KEY_7] = 0x0080000;
|
||||
REV[KEY_8] = 0x0090000;
|
||||
REV[KEY_9] = 0x00A0000;
|
||||
REV[KEY_0_PAD] = 0x0520000;
|
||||
REV[KEY_1_PAD] = 0x04F0000;
|
||||
REV[KEY_2_PAD] = 0x0500000;
|
||||
REV[KEY_3_PAD] = 0x0510000;
|
||||
REV[KEY_4_PAD] = 0x04B0000;
|
||||
REV[KEY_5_PAD] = 0x04C0000;
|
||||
REV[KEY_6_PAD] = 0x04D0000;
|
||||
REV[KEY_7_PAD] = 0x0470000;
|
||||
REV[KEY_8_PAD] = 0x0480000;
|
||||
REV[KEY_9_PAD] = 0x0490000;
|
||||
REV[KEY_F1] = 0x03B0000;
|
||||
REV[KEY_F2] = 0x03C0000;
|
||||
REV[KEY_F3] = 0x03D0000;
|
||||
REV[KEY_F4] = 0x03E0000;
|
||||
REV[KEY_F5] = 0x03F0000;
|
||||
REV[KEY_F6] = 0x0400000;
|
||||
REV[KEY_F7] = 0x0410000;
|
||||
REV[KEY_F8] = 0x0420000;
|
||||
REV[KEY_F9] = 0x0430000;
|
||||
REV[KEY_F10] = 0x0440000;
|
||||
REV[KEY_F11] = 0x0570000;
|
||||
REV[KEY_F12] = 0x0580000;
|
||||
REV[KEY_ESC] = 0x0010000;
|
||||
REV[KEY_TILDE] = 0x0290000;
|
||||
REV[KEY_MINUS] = 0x00C0000;
|
||||
REV[KEY_EQUALS] = 0x00D0000;
|
||||
REV[KEY_BACKSPACE] = 0x00E0000;
|
||||
REV[KEY_TAB] = 0x00F0000;
|
||||
REV[KEY_OPENBRACE] = 0x01A0000;
|
||||
REV[KEY_CLOSEBRACE] = 0x01B0000;
|
||||
REV[KEY_ENTER] = 0x01C0000;
|
||||
REV[KEY_COLON] = 0x0270000;
|
||||
REV[KEY_QUOTE] = 0x0280000;
|
||||
REV[KEY_BACKSLASH] = 0x02B0000;
|
||||
/* KEY_BACKSLASH2 */
|
||||
REV[KEY_COMMA] = 0x0330000;
|
||||
REV[KEY_STOP] = 0x0340000;
|
||||
REV[KEY_SLASH] = 0x0350000;
|
||||
REV[KEY_SPACE] = 0x0390000;
|
||||
REV[KEY_INSERT] = 0x1520000;
|
||||
REV[KEY_DEL] = 0x1530000;
|
||||
REV[KEY_HOME] = 0x1470000;
|
||||
REV[KEY_END] = 0x14F0000;
|
||||
REV[KEY_PGUP] = 0x1490000;
|
||||
REV[KEY_PGDN] = 0x1510000;
|
||||
REV[KEY_LEFT] = 0x14B0000;
|
||||
REV[KEY_RIGHT] = 0x14D0000;
|
||||
REV[KEY_UP] = 0x1480000;
|
||||
REV[KEY_DOWN] = 0x1500000;
|
||||
REV[KEY_SLASH_PAD] = 0x1350000;
|
||||
REV[KEY_ASTERISK] = 0x0370000;
|
||||
REV[KEY_MINUS_PAD] = 0x04A0000;
|
||||
REV[KEY_PLUS_PAD] = 0x04E0000;
|
||||
REV[KEY_DEL_PAD] = 0x0530000;
|
||||
REV[KEY_ENTER_PAD] = 0x11C0000;
|
||||
/* XXX doesn't work
|
||||
REV[KEY_PRTSCR] = 0x570000;
|
||||
*/
|
||||
REV[KEY_PAUSE] = 0x0450000;
|
||||
/* XXX Japanese keys missing
|
||||
REV[KEY_ABNT_C1] =
|
||||
REV[KEY_YEN] =
|
||||
REV[KEY_KANA] =
|
||||
REV[KEY_CONVERT] =
|
||||
REV[KEY_NOCONVERT] =
|
||||
REV[KEY_AT] =
|
||||
REV[KEY_CIRCUMFLEX] =
|
||||
REV[KEY_COLON2] =
|
||||
REV[KEY_KANJI] =
|
||||
*/
|
||||
|
||||
REV[KEY_LSHIFT] = 0x02A0000;
|
||||
REV[KEY_RSHIFT] = 0x0360000;
|
||||
REV[KEY_LCONTROL] = 0x01D0000;
|
||||
REV[KEY_RCONTROL] = 0x11D0000;
|
||||
REV[KEY_ALT] = 0x0380000;
|
||||
REV[KEY_ALTGR] = 0x1380000;
|
||||
REV[KEY_LWIN] = 0x15B0000;
|
||||
REV[KEY_RWIN] = 0x15C0000;
|
||||
REV[KEY_MENU] = 0x15D0000;
|
||||
REV[KEY_SCRLOCK] = 0x0460000;
|
||||
REV[KEY_NUMLOCK] = 0x1450000;
|
||||
REV[KEY_CAPSLOCK] = 0x03A0000;
|
||||
|
||||
#undef REV
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_dinput_init: [primary thread]
|
||||
* Sets up the DirectInput keyboard device.
|
||||
*/
|
||||
static int key_dinput_init(void)
|
||||
#define KEYBOARD_WINAPI AL_ID('W','A','P','I')
|
||||
|
||||
static KEYBOARD_DRIVER keyboard_winapi =
|
||||
{
|
||||
HRESULT hr;
|
||||
HWND allegro_wnd = win_get_window();
|
||||
DIPROPDWORD property_buf_size =
|
||||
{
|
||||
/* the header */
|
||||
{
|
||||
sizeof(DIPROPDWORD), // diph.dwSize
|
||||
sizeof(DIPROPHEADER), // diph.dwHeaderSize
|
||||
0, // diph.dwObj
|
||||
DIPH_DEVICE, // diph.dwHow
|
||||
},
|
||||
|
||||
/* the data */
|
||||
DINPUT_BUFFERSIZE, // dwData
|
||||
};
|
||||
|
||||
/* Get DirectInput interface */
|
||||
hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput, &key_dinput);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
hr = IDirectInput_Initialize(key_dinput, allegro_inst, DIRECTINPUT_VERSION);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Create the keyboard device */
|
||||
hr = IDirectInput_CreateDevice(key_dinput, &GUID_SysKeyboard, &key_dinput_device, NULL);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Set data format */
|
||||
hr = IDirectInputDevice_SetDataFormat(key_dinput_device, &c_dfDIKeyboard);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Set buffer size */
|
||||
hr = IDirectInputDevice_SetProperty(key_dinput_device, DIPROP_BUFFERSIZE, &property_buf_size.diph);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Set cooperative level */
|
||||
hr = IDirectInputDevice_SetCooperativeLevel(key_dinput_device, allegro_wnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Enable event notification */
|
||||
key_input_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
hr = IDirectInputDevice_SetEventNotification(key_dinput_device, key_input_event);
|
||||
if (FAILED(hr))
|
||||
goto Error;
|
||||
|
||||
/* Register event handler */
|
||||
if (_win_input_register_event(key_input_event, key_dinput_handle) != 0)
|
||||
goto Error;
|
||||
|
||||
get_reverse_mapping();
|
||||
|
||||
/* Acquire the device */
|
||||
wnd_call_proc(key_dinput_acquire);
|
||||
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
key_dinput_exit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_directx_init: [primary thread]
|
||||
*/
|
||||
static int key_directx_init(void)
|
||||
{
|
||||
/* keyboard input is handled by the window thread */
|
||||
key_input_processed_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
if (key_dinput_init() != 0) {
|
||||
/* something has gone wrong */
|
||||
_TRACE(PREFIX_E "keyboard handler init failed\n");
|
||||
CloseHandle(key_input_processed_event);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* the keyboard handler has successfully set up */
|
||||
_TRACE(PREFIX_I "keyboard handler starts\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_directx_exit: [primary thread]
|
||||
*/
|
||||
static void key_directx_exit(void)
|
||||
{
|
||||
if (key_dinput_device) {
|
||||
/* command keyboard handler shutdown */
|
||||
_TRACE(PREFIX_I "keyboard handler exits\n");
|
||||
key_dinput_exit();
|
||||
|
||||
/* now we can free all resources */
|
||||
CloseHandle(key_input_processed_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* key_directx_wait_for_input: [primary thread]
|
||||
*/
|
||||
static void key_directx_wait_for_input(void)
|
||||
{
|
||||
WaitForSingleObject(key_input_processed_event, INFINITE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* static void key_directx_stop_wait: [primary thread]
|
||||
*/
|
||||
static void key_directx_stop_wait(void)
|
||||
{
|
||||
SetEvent(key_input_processed_event);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* scancode_to_name:
|
||||
* Converts the given scancode to a description of the key.
|
||||
*/
|
||||
static AL_CONST char *key_directx_scancode_to_name(const int scancode)
|
||||
{
|
||||
static char name[256];
|
||||
TCHAR str[256];
|
||||
WCHAR wstr[256];
|
||||
|
||||
ASSERT(scancode >= 0 && scancode < KEY_MAX);
|
||||
|
||||
if (GetKeyNameText(reverse_mapping[scancode], str, sizeof str)) {
|
||||
/* let Windows translate from the current encoding into UTF16 */
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr);
|
||||
/* translate from utf16 to Allegro's current encoding */
|
||||
uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name);
|
||||
/* why oh why doesn't everybody just use UTF8/16 */
|
||||
return name;
|
||||
}
|
||||
else
|
||||
return _keyboard_common_names[scancode];
|
||||
}
|
||||
|
||||
|
||||
|
||||
static KEYBOARD_DRIVER keyboard_directx =
|
||||
{
|
||||
KEYBOARD_DIRECTX,
|
||||
KEYBOARD_WINAPI,
|
||||
0,
|
||||
0,
|
||||
"DirectInput keyboard",
|
||||
"WinAPI keyboard",
|
||||
1,
|
||||
key_directx_init,
|
||||
key_directx_exit,
|
||||
NULL, NULL, NULL,
|
||||
key_directx_wait_for_input,
|
||||
key_directx_stop_wait,
|
||||
key_winapi_init,
|
||||
key_winapi_exit,
|
||||
NULL,
|
||||
key_directx_scancode_to_name
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
_DRIVER_INFO _keyboard_driver_list[] =
|
||||
{
|
||||
{KEYBOARD_DIRECTX, &keyboard_directx, TRUE},
|
||||
{KEYBOARD_WINAPI, &keyboard_winapi, TRUE},
|
||||
{0, NULL, 0}
|
||||
};
|
||||
|
@ -349,8 +349,6 @@ static void sys_directx_save_console_state(void)
|
||||
static void sys_directx_restore_console_state(void)
|
||||
{
|
||||
HWND allegro_wnd = win_get_window();
|
||||
/* unacquire input devices */
|
||||
wnd_schedule_proc(key_dinput_unacquire);
|
||||
|
||||
/* reset switch mode */
|
||||
_win_reset_switch_mode();
|
||||
|
@ -95,6 +95,9 @@ void _al_win_mouse_handle_button(HWND hwnd, int button, BOOL down, int x, int y,
|
||||
void _al_win_mouse_handle_wheel(HWND hwnd, int z, BOOL abs);
|
||||
void _al_win_mouse_handle_move(HWND hwnd, int x, int y);
|
||||
|
||||
/* In wkeybd.c */
|
||||
void _al_win_kbd_handle_key_press(int scode, int vcode, BOOL repeated);
|
||||
void _al_win_kbd_handle_key_release(int vcode);
|
||||
|
||||
|
||||
/* init_window_modules:
|
||||
@ -185,18 +188,6 @@ static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* See get_reverse_mapping() in wkeybd.c to see what this is for. */
|
||||
if (FALSE && (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)) {
|
||||
static char name[256];
|
||||
TCHAR str[256];
|
||||
WCHAR wstr[256];
|
||||
|
||||
GetKeyNameText(lparam, str, sizeof str);
|
||||
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr);
|
||||
uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name);
|
||||
_TRACE(PREFIX_I" key[%s] = 0x%08lx;\n", name, lparam & 0x1ff0000);
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
|
||||
case WM_CREATE:
|
||||
@ -294,17 +285,6 @@ static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam,
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
/* Disable the default message-based key handler
|
||||
* in order to prevent conflicts on NT kernels.
|
||||
*/
|
||||
if (!user_wnd_proc || _keyboard_installed)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
if (wparam == SC_MONITORPOWER || wparam == SC_SCREENSAVE) {
|
||||
if (_screensaver_policy == ALWAYS_DISABLED
|
||||
@ -393,6 +373,30 @@ static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam,
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SYSKEYDOWN: {
|
||||
int vcode = wparam;
|
||||
BOOL repeated = (lparam >> 30) & 0x1;
|
||||
_al_win_kbd_handle_key_press(0, vcode, repeated);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_KEYDOWN: {
|
||||
int vcode = wparam;
|
||||
int scode = (lparam >> 16) & 0xff;
|
||||
BOOL repeated = (lparam >> 30) & 0x1;
|
||||
/* We can't use TranslateMessage() because we don't know if it will
|
||||
produce a WM_CHAR or not. */
|
||||
_al_win_kbd_handle_key_press(scode, vcode, repeated);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
case WM_KEYUP: {
|
||||
int vcode = wparam;
|
||||
_al_win_kbd_handle_key_release(vcode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* pass message to default window proc */
|
||||
@ -786,13 +790,3 @@ void win_set_wnd_create_proc(HWND (*proc)(WNDPROC))
|
||||
{
|
||||
wnd_create_proc = proc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* win_grab_input:
|
||||
* Grabs the input devices.
|
||||
*/
|
||||
void win_grab_input(void)
|
||||
{
|
||||
wnd_schedule_proc(key_dinput_acquire);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user