mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-11-25 05:42:20 +00:00
1048 lines
37 KiB
C++
1048 lines
37 KiB
C++
|
/*
|
|||
|
===========================================================================
|
|||
|
|
|||
|
Doom 3 GPL Source Code
|
|||
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|||
|
|
|||
|
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
|||
|
|
|||
|
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
|||
|
it under the terms of the GNU General Public License as published by
|
|||
|
the Free Software Foundation, either version 3 of the License, or
|
|||
|
(at your option) any later version.
|
|||
|
|
|||
|
Doom 3 Source Code is distributed in the hope that it will be useful,
|
|||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|||
|
GNU General Public License for more details.
|
|||
|
|
|||
|
You should have received a copy of the GNU General Public License
|
|||
|
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
|
|||
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|||
|
|
|||
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|||
|
|
|||
|
===========================================================================
|
|||
|
*/
|
|||
|
|
|||
|
#include "../../idlib/precompiled.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#include "win_local.h"
|
|||
|
|
|||
|
|
|||
|
#define DINPUT_BUFFERSIZE 256
|
|||
|
|
|||
|
#define CHAR_FIRSTREPEAT 200
|
|||
|
#define CHAR_REPEAT 100
|
|||
|
|
|||
|
typedef struct MYDATA {
|
|||
|
LONG lX; // X axis goes here
|
|||
|
LONG lY; // Y axis goes here
|
|||
|
LONG lZ; // Z axis goes here
|
|||
|
BYTE bButtonA; // One button goes here
|
|||
|
BYTE bButtonB; // Another button goes here
|
|||
|
BYTE bButtonC; // Another button goes here
|
|||
|
BYTE bButtonD; // Another button goes here
|
|||
|
} MYDATA;
|
|||
|
|
|||
|
static DIOBJECTDATAFORMAT rgodf[] = {
|
|||
|
{ &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
|
|||
|
{ 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
|
|||
|
};
|
|||
|
|
|||
|
//==========================================================================
|
|||
|
|
|||
|
static const unsigned char s_scantokey[256] = {
|
|||
|
// 0 1 2 3 4 5 6 7
|
|||
|
// 8 9 A B C D E F
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '[', ']', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|||
|
'\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|||
|
// shifted
|
|||
|
0, 27, '!', '@', '#', '$', '%', '^',
|
|||
|
'&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '[', ']', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
|||
|
'\'', '~', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0 // 7
|
|||
|
};
|
|||
|
|
|||
|
static const unsigned char s_scantokey_german[256] = {
|
|||
|
// 0 1 2 3 4 5 6 7
|
|||
|
// 8 9 A B C D E F
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', '?', '\'', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
|
|||
|
'o', 'p', '=', '+', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '[',
|
|||
|
']', '`', K_SHIFT, '#', 'y', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|||
|
// shifted
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', '?', '\'', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
|
|||
|
'o', 'p', '=', '+', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '[',
|
|||
|
']', '`', K_SHIFT, '#', 'y', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0 // 7
|
|||
|
};
|
|||
|
|
|||
|
static const unsigned char s_scantokey_french[256] = {
|
|||
|
// 0 1 2 3 4 5 6 7
|
|||
|
// 8 9 A B C D E F
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', ')', '=', K_BACKSPACE, 9, // 0
|
|||
|
'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '^', '$', K_ENTER,K_CTRL, 'q', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
|
|||
|
'<EFBFBD>', '`', K_SHIFT, '*', 'w', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', ',', ';', ':', '!', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|||
|
// shifted
|
|||
|
0, 27, '&', '<EFBFBD>', '\"', '\'', '(', '-',
|
|||
|
'<EFBFBD>', '_', '<EFBFBD>', '<EFBFBD>', '<EFBFBD>', '+', K_BACKSPACE, 9, // 0
|
|||
|
'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '^', '$', K_ENTER,K_CTRL, 'q', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
|
|||
|
'<EFBFBD>', 0, K_SHIFT, '*', 'w', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', ',', ';', ':', '!', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0 // 7
|
|||
|
};
|
|||
|
|
|||
|
static const unsigned char s_scantokey_spanish[256] = {
|
|||
|
// 0 1 2 3 4 5 6 7
|
|||
|
// 8 9 A B C D E F
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', '\'', '<EFBFBD>', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '`', '+', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '<EFBFBD>',
|
|||
|
'<EFBFBD>', '<EFBFBD>', K_SHIFT, '<EFBFBD>', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|||
|
// shifted
|
|||
|
0, 27, '!', '\"', '<EFBFBD>', '$', '%', '&',
|
|||
|
'/', '(', ')', '=', '?', '<EFBFBD>', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '^', '*', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '<EFBFBD>',
|
|||
|
'<EFBFBD>', '<EFBFBD>', K_SHIFT, '<EFBFBD>', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0 // 7
|
|||
|
};
|
|||
|
|
|||
|
static const unsigned char s_scantokey_italian[256] = {
|
|||
|
// 0 1 2 3 4 5 6 7
|
|||
|
// 8 9 A B C D E F
|
|||
|
0, 27, '1', '2', '3', '4', '5', '6',
|
|||
|
'7', '8', '9', '0', '\'', '<EFBFBD>', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '<EFBFBD>', '+', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '<EFBFBD>',
|
|||
|
'<EFBFBD>', '\\', K_SHIFT, '<EFBFBD>', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 7
|
|||
|
// shifted
|
|||
|
0, 27, '!', '\"', '<EFBFBD>', '$', '%', '&',
|
|||
|
'/', '(', ')', '=', '?', '^', K_BACKSPACE, 9, // 0
|
|||
|
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
|||
|
'o', 'p', '<EFBFBD>', '*', K_ENTER,K_CTRL, 'a', 's', // 1
|
|||
|
'd', 'f', 'g', 'h', 'j', 'k', 'l', '<EFBFBD>',
|
|||
|
'<EFBFBD>', '|', K_SHIFT, '<EFBFBD>', 'z', 'x', 'c', 'v', // 2
|
|||
|
'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
|
|||
|
K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
|
|||
|
K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
|
|||
|
K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
|
|||
|
K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
|
|||
|
K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0, // 6
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|||
|
0, 0, 0, 0, 0, 0, 0, 0 // 7
|
|||
|
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
static const unsigned char *keyScanTable = s_scantokey;
|
|||
|
|
|||
|
// this should be part of the scantables and the scan tables should be 512 bytes
|
|||
|
// (256 scan codes, shifted and unshifted). Changing everything to use 512 byte
|
|||
|
// scan tables now might introduce bugs in tested code. Since we only need to fix
|
|||
|
// the right-alt case for non-US keyboards, we're just using a special-case table
|
|||
|
// for it. Eventually, the tables above should be fixed to handle all possible
|
|||
|
// scan codes instead of just the first 128.
|
|||
|
static unsigned char rightAltKey = K_ALT;
|
|||
|
|
|||
|
#define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0]))
|
|||
|
|
|||
|
static DIDATAFORMAT df = {
|
|||
|
sizeof(DIDATAFORMAT), // this structure
|
|||
|
sizeof(DIOBJECTDATAFORMAT), // size of object data format
|
|||
|
DIDF_RELAXIS, // absolute axis coordinates
|
|||
|
sizeof(MYDATA), // device data size
|
|||
|
NUM_OBJECTS, // number of objects
|
|||
|
rgodf, // and here they are
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
============================================================
|
|||
|
|
|||
|
DIRECT INPUT KEYBOARD CONTROL
|
|||
|
|
|||
|
============================================================
|
|||
|
*/
|
|||
|
|
|||
|
bool IN_StartupKeyboard( void ) {
|
|||
|
HRESULT hr;
|
|||
|
bool bExclusive;
|
|||
|
bool bForeground;
|
|||
|
bool bImmediate;
|
|||
|
bool bDisableWindowsKey;
|
|||
|
DWORD dwCoopFlags;
|
|||
|
|
|||
|
if (!win32.g_pdi) {
|
|||
|
common->Printf("keyboard: DirectInput has not been started\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (win32.g_pKeyboard) {
|
|||
|
win32.g_pKeyboard->Release();
|
|||
|
win32.g_pKeyboard = NULL;
|
|||
|
}
|
|||
|
|
|||
|
// Detrimine where the buffer would like to be allocated
|
|||
|
bExclusive = false;
|
|||
|
bForeground = true;
|
|||
|
bImmediate = false;
|
|||
|
bDisableWindowsKey = true;
|
|||
|
|
|||
|
if( bExclusive )
|
|||
|
dwCoopFlags = DISCL_EXCLUSIVE;
|
|||
|
else
|
|||
|
dwCoopFlags = DISCL_NONEXCLUSIVE;
|
|||
|
|
|||
|
if( bForeground )
|
|||
|
dwCoopFlags |= DISCL_FOREGROUND;
|
|||
|
else
|
|||
|
dwCoopFlags |= DISCL_BACKGROUND;
|
|||
|
|
|||
|
// Disabling the windows key is only allowed only if we are in foreground nonexclusive
|
|||
|
if( bDisableWindowsKey && !bExclusive && bForeground )
|
|||
|
dwCoopFlags |= DISCL_NOWINKEY;
|
|||
|
|
|||
|
// Obtain an interface to the system keyboard device.
|
|||
|
if( FAILED( hr = win32.g_pdi->CreateDevice( GUID_SysKeyboard, &win32.g_pKeyboard, NULL ) ) ) {
|
|||
|
common->Printf("keyboard: couldn't find a keyboard device\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// Set the data format to "keyboard format" - a predefined data format
|
|||
|
//
|
|||
|
// A data format specifies which controls on a device we
|
|||
|
// are interested in, and how they should be reported.
|
|||
|
//
|
|||
|
// This tells DirectInput that we will be passing an array
|
|||
|
// of 256 bytes to IDirectInputDevice::GetDeviceState.
|
|||
|
if( FAILED( hr = win32.g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
|
|||
|
return false;
|
|||
|
|
|||
|
// Set the cooperativity level to let DirectInput know how
|
|||
|
// this device should interact with the system and with other
|
|||
|
// DirectInput applications.
|
|||
|
hr = win32.g_pKeyboard->SetCooperativeLevel( win32.hWnd, dwCoopFlags );
|
|||
|
if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive ) {
|
|||
|
common->Printf("keyboard: SetCooperativeLevel() returned DIERR_UNSUPPORTED.\nFor security reasons, background exclusive keyboard access is not allowed.\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if( FAILED(hr) ) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if( !bImmediate ) {
|
|||
|
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
|
|||
|
//
|
|||
|
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
|
|||
|
// If you want to read buffered data, you need to set a nonzero
|
|||
|
// buffer size.
|
|||
|
//
|
|||
|
// Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
|
|||
|
//
|
|||
|
// The buffer size is a DWORD property associated with the device.
|
|||
|
DIPROPDWORD dipdw;
|
|||
|
|
|||
|
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
|||
|
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|||
|
dipdw.diph.dwObj = 0;
|
|||
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
|||
|
dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
|
|||
|
|
|||
|
if( FAILED( hr = win32.g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// Acquire the newly created device
|
|||
|
win32.g_pKeyboard->Acquire();
|
|||
|
|
|||
|
common->Printf( "keyboard: DirectInput initialized.\n");
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
=======
|
|||
|
MapKey
|
|||
|
|
|||
|
Map from windows to quake keynums
|
|||
|
|
|||
|
FIXME: scan code tables should include the upper 128 scan codes instead
|
|||
|
of having to special-case them here. The current code makes it difficult
|
|||
|
to special-case conversions for non-US keyboards. Currently the only
|
|||
|
special-case is for right alt.
|
|||
|
=======
|
|||
|
*/
|
|||
|
int IN_DIMapKey (int key) {
|
|||
|
if ( key>=128 ) {
|
|||
|
switch ( key ) {
|
|||
|
case DIK_HOME:
|
|||
|
return K_HOME;
|
|||
|
case DIK_UPARROW:
|
|||
|
return K_UPARROW;
|
|||
|
case DIK_PGUP:
|
|||
|
return K_PGUP;
|
|||
|
case DIK_LEFTARROW:
|
|||
|
return K_LEFTARROW;
|
|||
|
case DIK_RIGHTARROW:
|
|||
|
return K_RIGHTARROW;
|
|||
|
case DIK_END:
|
|||
|
return K_END;
|
|||
|
case DIK_DOWNARROW:
|
|||
|
return K_DOWNARROW;
|
|||
|
case DIK_PGDN:
|
|||
|
return K_PGDN;
|
|||
|
case DIK_INSERT:
|
|||
|
return K_INS;
|
|||
|
case DIK_DELETE:
|
|||
|
return K_DEL;
|
|||
|
case DIK_RMENU:
|
|||
|
return rightAltKey;
|
|||
|
case DIK_RCONTROL:
|
|||
|
return K_CTRL;
|
|||
|
case DIK_NUMPADENTER:
|
|||
|
return K_KP_ENTER;
|
|||
|
case DIK_NUMPADEQUALS:
|
|||
|
return K_KP_EQUALS;
|
|||
|
case DIK_PAUSE:
|
|||
|
return K_PAUSE;
|
|||
|
case DIK_DIVIDE:
|
|||
|
return K_KP_SLASH;
|
|||
|
case DIK_LWIN:
|
|||
|
return K_LWIN;
|
|||
|
case DIK_RWIN:
|
|||
|
return K_RWIN;
|
|||
|
case DIK_APPS:
|
|||
|
return K_MENU;
|
|||
|
case DIK_SYSRQ:
|
|||
|
return K_PRINT_SCR;
|
|||
|
default:
|
|||
|
return 0;
|
|||
|
}
|
|||
|
} else {
|
|||
|
switch (key) {
|
|||
|
case DIK_NUMPAD7:
|
|||
|
return K_KP_HOME;
|
|||
|
case DIK_NUMPAD8:
|
|||
|
return K_KP_UPARROW;
|
|||
|
case DIK_NUMPAD9:
|
|||
|
return K_KP_PGUP;
|
|||
|
case DIK_NUMPAD4:
|
|||
|
return K_KP_LEFTARROW;
|
|||
|
case DIK_NUMPAD5:
|
|||
|
return K_KP_5;
|
|||
|
case DIK_NUMPAD6:
|
|||
|
return K_KP_RIGHTARROW;
|
|||
|
case DIK_NUMPAD1:
|
|||
|
return K_KP_END;
|
|||
|
case DIK_NUMPAD2:
|
|||
|
return K_KP_DOWNARROW;
|
|||
|
case DIK_NUMPAD3:
|
|||
|
return K_KP_PGDN;
|
|||
|
case DIK_NUMPAD0:
|
|||
|
return K_KP_INS;
|
|||
|
case DIK_DECIMAL:
|
|||
|
return K_KP_DEL;
|
|||
|
case DIK_SUBTRACT:
|
|||
|
return K_KP_MINUS;
|
|||
|
case DIK_ADD:
|
|||
|
return K_KP_PLUS;
|
|||
|
case DIK_NUMLOCK:
|
|||
|
return K_KP_NUMLOCK;
|
|||
|
case DIK_MULTIPLY:
|
|||
|
return K_KP_STAR;
|
|||
|
default:
|
|||
|
return keyScanTable[key];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
==========================
|
|||
|
IN_DeactivateKeyboard
|
|||
|
==========================
|
|||
|
*/
|
|||
|
void IN_DeactivateKeyboard( void ) {
|
|||
|
if (!win32.g_pKeyboard) {
|
|||
|
return;
|
|||
|
}
|
|||
|
win32.g_pKeyboard->Unacquire( );
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
============================================================
|
|||
|
|
|||
|
DIRECT INPUT MOUSE CONTROL
|
|||
|
|
|||
|
============================================================
|
|||
|
*/
|
|||
|
|
|||
|
/*
|
|||
|
========================
|
|||
|
IN_InitDirectInput
|
|||
|
========================
|
|||
|
*/
|
|||
|
|
|||
|
void IN_InitDirectInput( void ) {
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
common->Printf( "Initializing DirectInput...\n" );
|
|||
|
|
|||
|
if ( win32.g_pdi != NULL ) {
|
|||
|
win32.g_pdi->Release(); // if the previous window was destroyed we need to do this
|
|||
|
win32.g_pdi = NULL;
|
|||
|
}
|
|||
|
|
|||
|
// Register with the DirectInput subsystem and get a pointer
|
|||
|
// to a IDirectInput interface we can use.
|
|||
|
// Create the base DirectInput object
|
|||
|
if ( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&win32.g_pdi, NULL ) ) ) {
|
|||
|
common->Printf ("DirectInputCreate failed\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
========================
|
|||
|
IN_InitDIMouse
|
|||
|
========================
|
|||
|
*/
|
|||
|
bool IN_InitDIMouse( void ) {
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
if ( win32.g_pdi == NULL) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// obtain an interface to the system mouse device.
|
|||
|
hr = win32.g_pdi->CreateDevice( GUID_SysMouse, &win32.g_pMouse, NULL);
|
|||
|
|
|||
|
if (FAILED(hr)) {
|
|||
|
common->Printf ("mouse: Couldn't open DI mouse device\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// Set the data format to "mouse format" - a predefined data format
|
|||
|
//
|
|||
|
// A data format specifies which controls on a device we
|
|||
|
// are interested in, and how they should be reported.
|
|||
|
//
|
|||
|
// This tells DirectInput that we will be passing a
|
|||
|
// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
|
|||
|
if( FAILED( hr = win32.g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) ) {
|
|||
|
common->Printf ("mouse: Couldn't set DI mouse format\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
// set the cooperativity level.
|
|||
|
hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
|||
|
|
|||
|
if (FAILED(hr)) {
|
|||
|
common->Printf ("mouse: Couldn't set DI coop level\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
|
|||
|
//
|
|||
|
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
|
|||
|
// If you want to read buffered data, you need to set a nonzero
|
|||
|
// buffer size.
|
|||
|
//
|
|||
|
// Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
|
|||
|
//
|
|||
|
// The buffer size is a DWORD property associated with the device.
|
|||
|
DIPROPDWORD dipdw;
|
|||
|
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
|
|||
|
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
|||
|
dipdw.diph.dwObj = 0;
|
|||
|
dipdw.diph.dwHow = DIPH_DEVICE;
|
|||
|
dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
|
|||
|
|
|||
|
if( FAILED( hr = win32.g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) {
|
|||
|
common->Printf ("mouse: Couldn't set DI buffersize\n");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
IN_ActivateMouse();
|
|||
|
|
|||
|
// clear any pending samples
|
|||
|
Sys_PollMouseInputEvents();
|
|||
|
|
|||
|
common->Printf( "mouse: DirectInput initialized.\n");
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
==========================
|
|||
|
IN_ActivateMouse
|
|||
|
==========================
|
|||
|
*/
|
|||
|
void IN_ActivateMouse( void ) {
|
|||
|
int i;
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
if ( !win32.in_mouse.GetBool() || win32.mouseGrabbed || !win32.g_pMouse ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
win32.mouseGrabbed = true;
|
|||
|
for ( i = 0; i < 10; i++ ) {
|
|||
|
if ( ::ShowCursor( false ) < 0 ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// we may fail to reacquire if the window has been recreated
|
|||
|
hr = win32.g_pMouse->Acquire();
|
|||
|
if (FAILED(hr)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// set the cooperativity level.
|
|||
|
hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
==========================
|
|||
|
IN_DeactivateMouse
|
|||
|
==========================
|
|||
|
*/
|
|||
|
void IN_DeactivateMouse( void ) {
|
|||
|
int i;
|
|||
|
|
|||
|
if (!win32.g_pMouse || !win32.mouseGrabbed ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
win32.g_pMouse->Unacquire();
|
|||
|
|
|||
|
for ( i = 0; i < 10; i++ ) {
|
|||
|
if ( ::ShowCursor( true ) >= 0 ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
win32.mouseGrabbed = false;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
==========================
|
|||
|
IN_DeactivateMouseIfWindowed
|
|||
|
==========================
|
|||
|
*/
|
|||
|
void IN_DeactivateMouseIfWindowed( void ) {
|
|||
|
if ( !win32.cdsFullscreen ) {
|
|||
|
IN_DeactivateMouse();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
============================================================
|
|||
|
|
|||
|
MOUSE CONTROL
|
|||
|
|
|||
|
============================================================
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
===========
|
|||
|
Sys_ShutdownInput
|
|||
|
===========
|
|||
|
*/
|
|||
|
void Sys_ShutdownInput( void ) {
|
|||
|
IN_DeactivateMouse();
|
|||
|
IN_DeactivateKeyboard();
|
|||
|
if ( win32.g_pKeyboard ) {
|
|||
|
win32.g_pKeyboard->Release();
|
|||
|
win32.g_pKeyboard = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( win32.g_pMouse ) {
|
|||
|
win32.g_pMouse->Release();
|
|||
|
win32.g_pMouse = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( win32.g_pdi ) {
|
|||
|
win32.g_pdi->Release();
|
|||
|
win32.g_pdi = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
===========
|
|||
|
Sys_InitInput
|
|||
|
===========
|
|||
|
*/
|
|||
|
void Sys_InitInput( void ) {
|
|||
|
common->Printf ("\n------- Input Initialization -------\n");
|
|||
|
IN_InitDirectInput();
|
|||
|
if ( win32.in_mouse.GetBool() ) {
|
|||
|
IN_InitDIMouse();
|
|||
|
// don't grab the mouse on initialization
|
|||
|
Sys_GrabMouseCursor( false );
|
|||
|
} else {
|
|||
|
common->Printf ("Mouse control not active.\n");
|
|||
|
}
|
|||
|
IN_StartupKeyboard();
|
|||
|
common->Printf ("------------------------------------\n");
|
|||
|
win32.in_mouse.ClearModified();
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
===========
|
|||
|
Sys_InitScanTable
|
|||
|
===========
|
|||
|
*/
|
|||
|
void Sys_InitScanTable( void ) {
|
|||
|
idStr lang = cvarSystem->GetCVarString( "sys_lang" );
|
|||
|
if ( lang.Length() == 0 ) {
|
|||
|
lang = "english";
|
|||
|
}
|
|||
|
if ( lang.Icmp( "english" ) == 0 ) {
|
|||
|
keyScanTable = s_scantokey;
|
|||
|
// the only reason that english right alt binds as K_ALT is so that
|
|||
|
// users who were using right-alt before the patch don't suddenly find
|
|||
|
// that only left-alt is working.
|
|||
|
rightAltKey = K_ALT;
|
|||
|
} else if ( lang.Icmp( "spanish" ) == 0 ) {
|
|||
|
keyScanTable = s_scantokey_spanish;
|
|||
|
rightAltKey = K_RIGHT_ALT;
|
|||
|
} else if ( lang.Icmp( "french" ) == 0 ) {
|
|||
|
keyScanTable = s_scantokey_french;
|
|||
|
rightAltKey = K_RIGHT_ALT;
|
|||
|
} else if ( lang.Icmp( "german" ) == 0 ) {
|
|||
|
keyScanTable = s_scantokey_german;
|
|||
|
rightAltKey = K_RIGHT_ALT;
|
|||
|
} else if ( lang.Icmp( "italian" ) == 0 ) {
|
|||
|
keyScanTable = s_scantokey_italian;
|
|||
|
rightAltKey = K_RIGHT_ALT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
==================
|
|||
|
Sys_GetScanTable
|
|||
|
==================
|
|||
|
*/
|
|||
|
const unsigned char *Sys_GetScanTable( void ) {
|
|||
|
return keyScanTable;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
===============
|
|||
|
Sys_GetConsoleKey
|
|||
|
===============
|
|||
|
*/
|
|||
|
unsigned char Sys_GetConsoleKey( bool shifted ) {
|
|||
|
return keyScanTable[41 + ( shifted ? 128 : 0 )];
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
==================
|
|||
|
IN_Frame
|
|||
|
|
|||
|
Called every frame, even if not generating commands
|
|||
|
==================
|
|||
|
*/
|
|||
|
void IN_Frame( void ) {
|
|||
|
bool shouldGrab = true;
|
|||
|
|
|||
|
if ( !win32.in_mouse.GetBool() ) {
|
|||
|
shouldGrab = false;
|
|||
|
}
|
|||
|
// if fullscreen, we always want the mouse
|
|||
|
if ( !win32.cdsFullscreen ) {
|
|||
|
if ( win32.mouseReleased ) {
|
|||
|
shouldGrab = false;
|
|||
|
}
|
|||
|
if ( win32.movingWindow ) {
|
|||
|
shouldGrab = false;
|
|||
|
}
|
|||
|
if ( !win32.activeApp ) {
|
|||
|
shouldGrab = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( shouldGrab != win32.mouseGrabbed ) {
|
|||
|
if ( win32.mouseGrabbed ) {
|
|||
|
IN_DeactivateMouse();
|
|||
|
} else {
|
|||
|
IN_ActivateMouse();
|
|||
|
|
|||
|
#if 0 // if we can't reacquire, try reinitializing
|
|||
|
if ( !IN_InitDIMouse() ) {
|
|||
|
win32.in_mouse.SetBool( false );
|
|||
|
return;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void Sys_GrabMouseCursor( bool grabIt ) {
|
|||
|
#ifndef ID_DEDICATED
|
|||
|
win32.mouseReleased = !grabIt;
|
|||
|
if ( !grabIt ) {
|
|||
|
// release it right now
|
|||
|
IN_Frame();
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//=====================================================================================
|
|||
|
|
|||
|
static DIDEVICEOBJECTDATA polled_didod[ DINPUT_BUFFERSIZE ]; // Receives buffered data
|
|||
|
|
|||
|
static int diFetch;
|
|||
|
static byte toggleFetch[2][ 256 ];
|
|||
|
|
|||
|
|
|||
|
#if 1
|
|||
|
// I tried doing the full-state get to address a keyboard problem on one system,
|
|||
|
// but it didn't make any difference
|
|||
|
|
|||
|
/*
|
|||
|
====================
|
|||
|
Sys_PollKeyboardInputEvents
|
|||
|
====================
|
|||
|
*/
|
|||
|
int Sys_PollKeyboardInputEvents( void ) {
|
|||
|
DWORD dwElements;
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
if( win32.g_pKeyboard == NULL ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
dwElements = DINPUT_BUFFERSIZE;
|
|||
|
hr = win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
|
|||
|
polled_didod, &dwElements, 0 );
|
|||
|
if( hr != DI_OK )
|
|||
|
{
|
|||
|
// We got an error or we got DI_BUFFEROVERFLOW.
|
|||
|
//
|
|||
|
// Either way, it means that continuous contact with the
|
|||
|
// device has been lost, either due to an external
|
|||
|
// interruption, or because the buffer overflowed
|
|||
|
// and some events were lost.
|
|||
|
hr = win32.g_pKeyboard->Acquire();
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// nuke the garbage
|
|||
|
if (!FAILED(hr)) {
|
|||
|
//Bug 951: The following command really clears the garbage input.
|
|||
|
//The original will still process keys in the buffer and was causing
|
|||
|
//some problems.
|
|||
|
win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), NULL, &dwElements, 0 );
|
|||
|
dwElements = 0;
|
|||
|
}
|
|||
|
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
|
|||
|
// may occur when the app is minimized or in the process of
|
|||
|
// switching, so just try again later
|
|||
|
}
|
|||
|
|
|||
|
if( FAILED(hr) ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
return dwElements;
|
|||
|
}
|
|||
|
|
|||
|
#else
|
|||
|
|
|||
|
/*
|
|||
|
====================
|
|||
|
Sys_PollKeyboardInputEvents
|
|||
|
|
|||
|
Fake events by getting the entire device state
|
|||
|
and checking transitions
|
|||
|
====================
|
|||
|
*/
|
|||
|
int Sys_PollKeyboardInputEvents( void ) {
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
if( win32.g_pKeyboard == NULL ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
|
|||
|
if( hr != DI_OK )
|
|||
|
{
|
|||
|
// We got an error or we got DI_BUFFEROVERFLOW.
|
|||
|
//
|
|||
|
// Either way, it means that continuous contact with the
|
|||
|
// device has been lost, either due to an external
|
|||
|
// interruption, or because the buffer overflowed
|
|||
|
// and some events were lost.
|
|||
|
hr = win32.g_pKeyboard->Acquire();
|
|||
|
|
|||
|
// nuke the garbage
|
|||
|
if (!FAILED(hr)) {
|
|||
|
hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
|
|||
|
}
|
|||
|
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
|
|||
|
// may occur when the app is minimized or in the process of
|
|||
|
// switching, so just try again later
|
|||
|
}
|
|||
|
|
|||
|
if( FAILED(hr) ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// build faked events
|
|||
|
int numChanges = 0;
|
|||
|
|
|||
|
for ( int i = 0 ; i < 256 ; i++ ) {
|
|||
|
if ( toggleFetch[0][i] != toggleFetch[1][i] ) {
|
|||
|
polled_didod[ numChanges ].dwOfs = i;
|
|||
|
polled_didod[ numChanges ].dwData = toggleFetch[ diFetch ][i] ? 0x80 : 0;
|
|||
|
numChanges++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
diFetch ^= 1;
|
|||
|
|
|||
|
return numChanges;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
/*
|
|||
|
====================
|
|||
|
Sys_PollKeyboardInputEvents
|
|||
|
====================
|
|||
|
*/
|
|||
|
int Sys_ReturnKeyboardInputEvent( const int n, int &ch, bool &state ) {
|
|||
|
ch = IN_DIMapKey( polled_didod[ n ].dwOfs );
|
|||
|
state = (polled_didod[ n ].dwData & 0x80) == 0x80;
|
|||
|
if ( ch == K_PRINT_SCR || ch == K_CTRL || ch == K_ALT || ch == K_RIGHT_ALT ) {
|
|||
|
// for windows, add a keydown event for print screen here, since
|
|||
|
// windows doesn't send keydown events to the WndProc for this key.
|
|||
|
// ctrl and alt are handled here to get around windows sending ctrl and
|
|||
|
// alt messages when the right-alt is pressed on non-US 102 keyboards.
|
|||
|
Sys_QueEvent( GetTickCount(), SE_KEY, ch, state, 0, NULL );
|
|||
|
}
|
|||
|
return ch;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void Sys_EndKeyboardInputEvents( void ) {
|
|||
|
}
|
|||
|
|
|||
|
void Sys_QueMouseEvents( int dwElements ) {
|
|||
|
int i, value;
|
|||
|
|
|||
|
for( i = 0; i < dwElements; i++ ) {
|
|||
|
if ( polled_didod[i].dwOfs >= DIMOFS_BUTTON0 && polled_didod[i].dwOfs <= DIMOFS_BUTTON7 ) {
|
|||
|
value = (polled_didod[i].dwData & 0x80) == 0x80;
|
|||
|
Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, K_MOUSE1 + ( polled_didod[i].dwOfs - DIMOFS_BUTTON0 ), value, 0, NULL );
|
|||
|
} else {
|
|||
|
switch (polled_didod[i].dwOfs) {
|
|||
|
case DIMOFS_X:
|
|||
|
value = polled_didod[i].dwData;
|
|||
|
Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_MOUSE, value, 0, 0, NULL );
|
|||
|
break;
|
|||
|
case DIMOFS_Y:
|
|||
|
value = polled_didod[i].dwData;
|
|||
|
Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_MOUSE, 0, value, 0, NULL );
|
|||
|
break;
|
|||
|
case DIMOFS_Z:
|
|||
|
value = ( (int) polled_didod[i].dwData ) / WHEEL_DELTA;
|
|||
|
int key = value < 0 ? K_MWHEELDOWN : K_MWHEELUP;
|
|||
|
value = abs( value );
|
|||
|
while( value-- > 0 ) {
|
|||
|
Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, key, true, 0, NULL );
|
|||
|
Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, key, false, 0, NULL );
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//=====================================================================================
|
|||
|
|
|||
|
int Sys_PollMouseInputEvents( void ) {
|
|||
|
DWORD dwElements;
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
if ( !win32.g_pMouse || !win32.mouseGrabbed ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
dwElements = DINPUT_BUFFERSIZE;
|
|||
|
hr = win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
|
|||
|
|
|||
|
if( hr != DI_OK ) {
|
|||
|
hr = win32.g_pMouse->Acquire();
|
|||
|
// clear the garbage
|
|||
|
if (!FAILED(hr)) {
|
|||
|
win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( FAILED(hr) ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
Sys_QueMouseEvents( dwElements );
|
|||
|
|
|||
|
return dwElements;
|
|||
|
}
|
|||
|
|
|||
|
int Sys_ReturnMouseInputEvent( const int n, int &action, int &value ) {
|
|||
|
int diaction = polled_didod[n].dwOfs;
|
|||
|
|
|||
|
if ( diaction >= DIMOFS_BUTTON0 && diaction <= DIMOFS_BUTTON7 ) {
|
|||
|
value = (polled_didod[n].dwData & 0x80) == 0x80;
|
|||
|
action = M_ACTION1 + ( diaction - DIMOFS_BUTTON0 );
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
switch( diaction ) {
|
|||
|
case DIMOFS_X:
|
|||
|
value = polled_didod[n].dwData;
|
|||
|
action = M_DELTAX;
|
|||
|
return 1;
|
|||
|
case DIMOFS_Y:
|
|||
|
value = polled_didod[n].dwData;
|
|||
|
action = M_DELTAY;
|
|||
|
return 1;
|
|||
|
case DIMOFS_Z:
|
|||
|
// mouse wheel actions are impulses, without a specific up / down
|
|||
|
value = ( (int) polled_didod[n].dwData ) / WHEEL_DELTA;
|
|||
|
action = M_DELTAZ;
|
|||
|
// a value of zero here should never happen
|
|||
|
if ( value == 0 ) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
void Sys_EndMouseInputEvents( void ) { }
|
|||
|
|
|||
|
unsigned char Sys_MapCharForKey( int key ) {
|
|||
|
return (unsigned char)key;
|
|||
|
}
|