win_input.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "win_local.h"
  23. #define DINPUT_BUFFERSIZE 256
  24. #define CHAR_FIRSTREPEAT 200
  25. #define CHAR_REPEAT 100
  26. typedef struct MYDATA {
  27. LONG lX; // X axis goes here
  28. LONG lY; // Y axis goes here
  29. LONG lZ; // Z axis goes here
  30. BYTE bButtonA; // One button goes here
  31. BYTE bButtonB; // Another button goes here
  32. BYTE bButtonC; // Another button goes here
  33. BYTE bButtonD; // Another button goes here
  34. } MYDATA;
  35. static DIOBJECTDATAFORMAT rgodf[] = {
  36. { &GUID_XAxis, FIELD_OFFSET(MYDATA, lX), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
  37. { &GUID_YAxis, FIELD_OFFSET(MYDATA, lY), DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
  38. { &GUID_ZAxis, FIELD_OFFSET(MYDATA, lZ), 0x80000000 | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0,},
  39. { 0, FIELD_OFFSET(MYDATA, bButtonA), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
  40. { 0, FIELD_OFFSET(MYDATA, bButtonB), DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
  41. { 0, FIELD_OFFSET(MYDATA, bButtonC), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
  42. { 0, FIELD_OFFSET(MYDATA, bButtonD), 0x80000000 | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0,},
  43. };
  44. //==========================================================================
  45. static const unsigned char s_scantokey[256] = {
  46. // 0 1 2 3 4 5 6 7
  47. // 8 9 A B C D E F
  48. 0, 27, '1', '2', '3', '4', '5', '6',
  49. '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 0
  50. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  51. 'o', 'p', '[', ']', K_ENTER,K_CTRL, 'a', 's', // 1
  52. 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
  53. '\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2
  54. 'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
  55. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  56. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  57. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  58. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
  59. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  60. 0, 0, 0, 0, 0, 0, 0, 0,
  61. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  62. 0, 0, 0, 0, 0, 0, 0, 0,
  63. 0, 0, 0, 0, 0, 0, 0, 0, // 7
  64. // shifted
  65. 0, 27, '!', '@', '#', '$', '%', '^',
  66. '&', '*', '(', ')', '_', '+', K_BACKSPACE, 9, // 0
  67. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  68. 'o', 'p', '[', ']', K_ENTER,K_CTRL, 'a', 's', // 1
  69. 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
  70. '\'', '~', K_SHIFT, '\\', 'z', 'x', 'c', 'v', // 2
  71. 'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
  72. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  73. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  74. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  75. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, 0, K_F11,
  76. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  77. 0, 0, 0, 0, 0, 0, 0, 0,
  78. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  79. 0, 0, 0, 0, 0, 0, 0, 0,
  80. 0, 0, 0, 0, 0, 0, 0, 0 // 7
  81. };
  82. static const unsigned char s_scantokey_german[256] = {
  83. // 0 1 2 3 4 5 6 7
  84. // 8 9 A B C D E F
  85. 0, 27, '1', '2', '3', '4', '5', '6',
  86. '7', '8', '9', '0', '?', '\'', K_BACKSPACE, 9, // 0
  87. 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
  88. 'o', 'p', '=', '+', K_ENTER,K_CTRL, 'a', 's', // 1
  89. 'd', 'f', 'g', 'h', 'j', 'k', 'l', '[',
  90. ']', '`', K_SHIFT, '#', 'y', 'x', 'c', 'v', // 2
  91. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  92. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  93. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  94. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  95. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  96. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  97. 0, 0, 0, 0, 0, 0, 0, 0,
  98. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  99. 0, 0, 0, 0, 0, 0, 0, 0,
  100. 0, 0, 0, 0, 0, 0, 0, 0, // 7
  101. // shifted
  102. 0, 27, '1', '2', '3', '4', '5', '6',
  103. '7', '8', '9', '0', '?', '\'', K_BACKSPACE, 9, // 0
  104. 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i',
  105. 'o', 'p', '=', '+', K_ENTER,K_CTRL, 'a', 's', // 1
  106. 'd', 'f', 'g', 'h', 'j', 'k', 'l', '[',
  107. ']', '`', K_SHIFT, '#', 'y', 'x', 'c', 'v', // 2
  108. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  109. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  110. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  111. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  112. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  113. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  114. 0, 0, 0, 0, 0, 0, 0, 0,
  115. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  116. 0, 0, 0, 0, 0, 0, 0, 0,
  117. 0, 0, 0, 0, 0, 0, 0, 0 // 7
  118. };
  119. static const unsigned char s_scantokey_french[256] = {
  120. // 0 1 2 3 4 5 6 7
  121. // 8 9 A B C D E F
  122. 0, 27, '1', '2', '3', '4', '5', '6',
  123. '7', '8', '9', '0', ')', '=', K_BACKSPACE, 9, // 0
  124. 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
  125. 'o', 'p', '^', '$', K_ENTER,K_CTRL, 'q', 's', // 1
  126. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
  127. 'ù', '`', K_SHIFT, '*', 'w', 'x', 'c', 'v', // 2
  128. 'b', 'n', ',', ';', ':', '!', K_SHIFT, K_KP_STAR,
  129. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  130. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  131. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  132. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  133. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  134. 0, 0, 0, 0, 0, 0, 0, 0,
  135. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  136. 0, 0, 0, 0, 0, 0, 0, 0,
  137. 0, 0, 0, 0, 0, 0, 0, 0, // 7
  138. // shifted
  139. 0, 27, '&', 'é', '\"', '\'', '(', '-',
  140. 'è', '_', 'ç', 'à', '°', '+', K_BACKSPACE, 9, // 0
  141. 'a', 'z', 'e', 'r', 't', 'y', 'u', 'i',
  142. 'o', 'p', '^', '$', K_ENTER,K_CTRL, 'q', 's', // 1
  143. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
  144. 'ù', 0, K_SHIFT, '*', 'w', 'x', 'c', 'v', // 2
  145. 'b', 'n', ',', ';', ':', '!', K_SHIFT, K_KP_STAR,
  146. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  147. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  148. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  149. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  150. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  151. 0, 0, 0, 0, 0, 0, 0, 0,
  152. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  153. 0, 0, 0, 0, 0, 0, 0, 0,
  154. 0, 0, 0, 0, 0, 0, 0, 0 // 7
  155. };
  156. static const unsigned char s_scantokey_spanish[256] = {
  157. // 0 1 2 3 4 5 6 7
  158. // 8 9 A B C D E F
  159. 0, 27, '1', '2', '3', '4', '5', '6',
  160. '7', '8', '9', '0', '\'', '¡', K_BACKSPACE, 9, // 0
  161. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  162. 'o', 'p', '`', '+', K_ENTER,K_CTRL, 'a', 's', // 1
  163. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ñ',
  164. '´', 'º', K_SHIFT, 'ç', 'z', 'x', 'c', 'v', // 2
  165. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  166. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  167. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  168. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  169. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  170. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  171. 0, 0, 0, 0, 0, 0, 0, 0,
  172. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  173. 0, 0, 0, 0, 0, 0, 0, 0,
  174. 0, 0, 0, 0, 0, 0, 0, 0, // 7
  175. // shifted
  176. 0, 27, '!', '\"', '·', '$', '%', '&',
  177. '/', '(', ')', '=', '?', '¿', K_BACKSPACE, 9, // 0
  178. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  179. 'o', 'p', '^', '*', K_ENTER,K_CTRL, 'a', 's', // 1
  180. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'Ñ',
  181. '¨', 'ª', K_SHIFT, 'Ç', 'z', 'x', 'c', 'v', // 2
  182. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  183. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  184. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  185. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  186. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  187. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  188. 0, 0, 0, 0, 0, 0, 0, 0,
  189. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  190. 0, 0, 0, 0, 0, 0, 0, 0,
  191. 0, 0, 0, 0, 0, 0, 0, 0 // 7
  192. };
  193. static const unsigned char s_scantokey_italian[256] = {
  194. // 0 1 2 3 4 5 6 7
  195. // 8 9 A B C D E F
  196. 0, 27, '1', '2', '3', '4', '5', '6',
  197. '7', '8', '9', '0', '\'', 'ì', K_BACKSPACE, 9, // 0
  198. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  199. 'o', 'p', 'è', '+', K_ENTER,K_CTRL, 'a', 's', // 1
  200. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ò',
  201. 'à', '\\', K_SHIFT, 'ù', 'z', 'x', 'c', 'v', // 2
  202. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  203. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  204. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  205. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  206. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  207. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  208. 0, 0, 0, 0, 0, 0, 0, 0,
  209. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  210. 0, 0, 0, 0, 0, 0, 0, 0,
  211. 0, 0, 0, 0, 0, 0, 0, 0, // 7
  212. // shifted
  213. 0, 27, '!', '\"', '£', '$', '%', '&',
  214. '/', '(', ')', '=', '?', '^', K_BACKSPACE, 9, // 0
  215. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  216. 'o', 'p', 'é', '*', K_ENTER,K_CTRL, 'a', 's', // 1
  217. 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ç',
  218. '°', '|', K_SHIFT, '§', 'z', 'x', 'c', 'v', // 2
  219. 'b', 'n', 'm', ',', '.', '-', K_SHIFT, K_KP_STAR,
  220. K_ALT, ' ', K_CAPSLOCK,K_F1, K_F2, K_F3, K_F4, K_F5, // 3
  221. K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCROLL, K_HOME,
  222. K_UPARROW, K_PGUP, K_KP_MINUS,K_LEFTARROW,K_KP_5, K_RIGHTARROW,K_KP_PLUS,K_END, // 4
  223. K_DOWNARROW,K_PGDN, K_INS, K_DEL, 0, 0, '<', K_F11,
  224. K_F12, 0, 0, K_LWIN, K_RWIN, K_MENU, 0, 0, // 5
  225. 0, 0, 0, 0, 0, 0, 0, 0,
  226. 0, 0, 0, 0, 0, 0, 0, 0, // 6
  227. 0, 0, 0, 0, 0, 0, 0, 0,
  228. 0, 0, 0, 0, 0, 0, 0, 0 // 7
  229. };
  230. static const unsigned char *keyScanTable = s_scantokey;
  231. // this should be part of the scantables and the scan tables should be 512 bytes
  232. // (256 scan codes, shifted and unshifted). Changing everything to use 512 byte
  233. // scan tables now might introduce bugs in tested code. Since we only need to fix
  234. // the right-alt case for non-US keyboards, we're just using a special-case table
  235. // for it. Eventually, the tables above should be fixed to handle all possible
  236. // scan codes instead of just the first 128.
  237. static unsigned char rightAltKey = K_ALT;
  238. #define NUM_OBJECTS (sizeof(rgodf) / sizeof(rgodf[0]))
  239. static DIDATAFORMAT df = {
  240. sizeof(DIDATAFORMAT), // this structure
  241. sizeof(DIOBJECTDATAFORMAT), // size of object data format
  242. DIDF_RELAXIS, // absolute axis coordinates
  243. sizeof(MYDATA), // device data size
  244. NUM_OBJECTS, // number of objects
  245. rgodf, // and here they are
  246. };
  247. #ifndef USE_SDL
  248. /*
  249. ============================================================
  250. DIRECT INPUT KEYBOARD CONTROL
  251. ============================================================
  252. */
  253. bool IN_StartupKeyboard( void ) {
  254. HRESULT hr;
  255. bool bExclusive;
  256. bool bForeground;
  257. bool bImmediate;
  258. bool bDisableWindowsKey;
  259. DWORD dwCoopFlags;
  260. if (!win32.g_pdi) {
  261. common->Printf("keyboard: DirectInput has not been started\n");
  262. return false;
  263. }
  264. if (win32.g_pKeyboard) {
  265. win32.g_pKeyboard->Release();
  266. win32.g_pKeyboard = NULL;
  267. }
  268. // Detrimine where the buffer would like to be allocated
  269. bExclusive = false;
  270. bForeground = true;
  271. bImmediate = false;
  272. bDisableWindowsKey = true;
  273. if( bExclusive )
  274. dwCoopFlags = DISCL_EXCLUSIVE;
  275. else
  276. dwCoopFlags = DISCL_NONEXCLUSIVE;
  277. if( bForeground )
  278. dwCoopFlags |= DISCL_FOREGROUND;
  279. else
  280. dwCoopFlags |= DISCL_BACKGROUND;
  281. // Disabling the windows key is only allowed only if we are in foreground nonexclusive
  282. if( bDisableWindowsKey && !bExclusive && bForeground )
  283. dwCoopFlags |= DISCL_NOWINKEY;
  284. // Obtain an interface to the system keyboard device.
  285. if( FAILED( hr = win32.g_pdi->CreateDevice( GUID_SysKeyboard, &win32.g_pKeyboard, NULL ) ) ) {
  286. common->Printf("keyboard: couldn't find a keyboard device\n");
  287. return false;
  288. }
  289. // Set the data format to "keyboard format" - a predefined data format
  290. //
  291. // A data format specifies which controls on a device we
  292. // are interested in, and how they should be reported.
  293. //
  294. // This tells DirectInput that we will be passing an array
  295. // of 256 bytes to IDirectInputDevice::GetDeviceState.
  296. if( FAILED( hr = win32.g_pKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) )
  297. return false;
  298. // Set the cooperativity level to let DirectInput know how
  299. // this device should interact with the system and with other
  300. // DirectInput applications.
  301. hr = win32.g_pKeyboard->SetCooperativeLevel( win32.hWnd, dwCoopFlags );
  302. if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive ) {
  303. common->Printf("keyboard: SetCooperativeLevel() returned DIERR_UNSUPPORTED.\nFor security reasons, background exclusive keyboard access is not allowed.\n");
  304. return false;
  305. }
  306. if( FAILED(hr) ) {
  307. return false;
  308. }
  309. if( !bImmediate ) {
  310. // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  311. //
  312. // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  313. // If you want to read buffered data, you need to set a nonzero
  314. // buffer size.
  315. //
  316. // Set the buffer size to DINPUT_BUFFERSIZE (defined above) elements.
  317. //
  318. // The buffer size is a DWORD property associated with the device.
  319. DIPROPDWORD dipdw;
  320. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  321. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  322. dipdw.diph.dwObj = 0;
  323. dipdw.diph.dwHow = DIPH_DEVICE;
  324. dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
  325. if( FAILED( hr = win32.g_pKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) )
  326. return false;
  327. }
  328. // Acquire the newly created device
  329. win32.g_pKeyboard->Acquire();
  330. common->Printf( "keyboard: DirectInput initialized.\n");
  331. return true;
  332. }
  333. /*
  334. =======
  335. MapKey
  336. Map from windows to quake keynums
  337. FIXME: scan code tables should include the upper 128 scan codes instead
  338. of having to special-case them here. The current code makes it difficult
  339. to special-case conversions for non-US keyboards. Currently the only
  340. special-case is for right alt.
  341. =======
  342. */
  343. int IN_DIMapKey (int key) {
  344. if ( key>=128 ) {
  345. switch ( key ) {
  346. case DIK_HOME:
  347. return K_HOME;
  348. case DIK_UPARROW:
  349. return K_UPARROW;
  350. case DIK_PGUP:
  351. return K_PGUP;
  352. case DIK_LEFTARROW:
  353. return K_LEFTARROW;
  354. case DIK_RIGHTARROW:
  355. return K_RIGHTARROW;
  356. case DIK_END:
  357. return K_END;
  358. case DIK_DOWNARROW:
  359. return K_DOWNARROW;
  360. case DIK_PGDN:
  361. return K_PGDN;
  362. case DIK_INSERT:
  363. return K_INS;
  364. case DIK_DELETE:
  365. return K_DEL;
  366. case DIK_RMENU:
  367. return rightAltKey;
  368. case DIK_RCONTROL:
  369. return K_CTRL;
  370. case DIK_NUMPADENTER:
  371. return K_KP_ENTER;
  372. case DIK_NUMPADEQUALS:
  373. return K_KP_EQUALS;
  374. case DIK_PAUSE:
  375. return K_PAUSE;
  376. case DIK_DIVIDE:
  377. return K_KP_SLASH;
  378. case DIK_LWIN:
  379. return K_LWIN;
  380. case DIK_RWIN:
  381. return K_RWIN;
  382. case DIK_APPS:
  383. return K_MENU;
  384. case DIK_SYSRQ:
  385. return K_PRINT_SCR;
  386. default:
  387. return 0;
  388. }
  389. } else {
  390. switch (key) {
  391. case DIK_NUMPAD7:
  392. return K_KP_HOME;
  393. case DIK_NUMPAD8:
  394. return K_KP_UPARROW;
  395. case DIK_NUMPAD9:
  396. return K_KP_PGUP;
  397. case DIK_NUMPAD4:
  398. return K_KP_LEFTARROW;
  399. case DIK_NUMPAD5:
  400. return K_KP_5;
  401. case DIK_NUMPAD6:
  402. return K_KP_RIGHTARROW;
  403. case DIK_NUMPAD1:
  404. return K_KP_END;
  405. case DIK_NUMPAD2:
  406. return K_KP_DOWNARROW;
  407. case DIK_NUMPAD3:
  408. return K_KP_PGDN;
  409. case DIK_NUMPAD0:
  410. return K_KP_INS;
  411. case DIK_DECIMAL:
  412. return K_KP_DEL;
  413. case DIK_SUBTRACT:
  414. return K_KP_MINUS;
  415. case DIK_ADD:
  416. return K_KP_PLUS;
  417. case DIK_NUMLOCK:
  418. return K_KP_NUMLOCK;
  419. case DIK_MULTIPLY:
  420. return K_KP_STAR;
  421. default:
  422. return keyScanTable[key];
  423. }
  424. }
  425. }
  426. /*
  427. ==========================
  428. IN_DeactivateKeyboard
  429. ==========================
  430. */
  431. void IN_DeactivateKeyboard( void ) {
  432. if (!win32.g_pKeyboard) {
  433. return;
  434. }
  435. win32.g_pKeyboard->Unacquire( );
  436. }
  437. /*
  438. ============================================================
  439. DIRECT INPUT MOUSE CONTROL
  440. ============================================================
  441. */
  442. /*
  443. ========================
  444. IN_InitDirectInput
  445. ========================
  446. */
  447. void IN_InitDirectInput( void ) {
  448. HRESULT hr;
  449. common->Printf( "Initializing DirectInput...\n" );
  450. if ( win32.g_pdi != NULL ) {
  451. win32.g_pdi->Release(); // if the previous window was destroyed we need to do this
  452. win32.g_pdi = NULL;
  453. }
  454. // Register with the DirectInput subsystem and get a pointer
  455. // to a IDirectInput interface we can use.
  456. // Create the base DirectInput object
  457. if ( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&win32.g_pdi, NULL ) ) ) {
  458. common->Printf ("DirectInputCreate failed\n");
  459. }
  460. }
  461. /*
  462. ========================
  463. IN_InitDIMouse
  464. ========================
  465. */
  466. bool IN_InitDIMouse( void ) {
  467. HRESULT hr;
  468. if ( win32.g_pdi == NULL) {
  469. return false;
  470. }
  471. // obtain an interface to the system mouse device.
  472. hr = win32.g_pdi->CreateDevice( GUID_SysMouse, &win32.g_pMouse, NULL);
  473. if (FAILED(hr)) {
  474. common->Printf ("mouse: Couldn't open DI mouse device\n");
  475. return false;
  476. }
  477. // Set the data format to "mouse format" - a predefined data format
  478. //
  479. // A data format specifies which controls on a device we
  480. // are interested in, and how they should be reported.
  481. //
  482. // This tells DirectInput that we will be passing a
  483. // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
  484. if( FAILED( hr = win32.g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) ) {
  485. common->Printf ("mouse: Couldn't set DI mouse format\n");
  486. return false;
  487. }
  488. // set the cooperativity level.
  489. hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
  490. if (FAILED(hr)) {
  491. common->Printf ("mouse: Couldn't set DI coop level\n");
  492. return false;
  493. }
  494. // IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
  495. //
  496. // DirectInput uses unbuffered I/O (buffer size = 0) by default.
  497. // If you want to read buffered data, you need to set a nonzero
  498. // buffer size.
  499. //
  500. // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
  501. //
  502. // The buffer size is a DWORD property associated with the device.
  503. DIPROPDWORD dipdw;
  504. dipdw.diph.dwSize = sizeof(DIPROPDWORD);
  505. dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  506. dipdw.diph.dwObj = 0;
  507. dipdw.diph.dwHow = DIPH_DEVICE;
  508. dipdw.dwData = DINPUT_BUFFERSIZE; // Arbitary buffer size
  509. if( FAILED( hr = win32.g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) {
  510. common->Printf ("mouse: Couldn't set DI buffersize\n");
  511. return false;
  512. }
  513. IN_ActivateMouse();
  514. // clear any pending samples
  515. Sys_PollMouseInputEvents();
  516. common->Printf( "mouse: DirectInput initialized.\n");
  517. return true;
  518. }
  519. /*
  520. ==========================
  521. IN_ActivateMouse
  522. ==========================
  523. */
  524. void IN_ActivateMouse( void ) {
  525. int i;
  526. HRESULT hr;
  527. if ( !win32.in_mouse.GetBool() || win32.mouseGrabbed || !win32.g_pMouse ) {
  528. return;
  529. }
  530. win32.mouseGrabbed = true;
  531. for ( i = 0; i < 10; i++ ) {
  532. if ( ::ShowCursor( false ) < 0 ) {
  533. break;
  534. }
  535. }
  536. // we may fail to reacquire if the window has been recreated
  537. hr = win32.g_pMouse->Acquire();
  538. if (FAILED(hr)) {
  539. return;
  540. }
  541. // set the cooperativity level.
  542. hr = win32.g_pMouse->SetCooperativeLevel( win32.hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
  543. }
  544. /*
  545. ==========================
  546. IN_DeactivateMouse
  547. ==========================
  548. */
  549. void IN_DeactivateMouse( void ) {
  550. int i;
  551. if (!win32.g_pMouse || !win32.mouseGrabbed ) {
  552. return;
  553. }
  554. win32.g_pMouse->Unacquire();
  555. for ( i = 0; i < 10; i++ ) {
  556. if ( ::ShowCursor( true ) >= 0 ) {
  557. break;
  558. }
  559. }
  560. win32.mouseGrabbed = false;
  561. }
  562. /*
  563. ==========================
  564. IN_DeactivateMouseIfWindowed
  565. ==========================
  566. */
  567. void IN_DeactivateMouseIfWindowed( void ) {
  568. if ( !win32.cdsFullscreen ) {
  569. IN_DeactivateMouse();
  570. }
  571. }
  572. /*
  573. ============================================================
  574. MOUSE CONTROL
  575. ============================================================
  576. */
  577. /*
  578. ===========
  579. Sys_ShutdownInput
  580. ===========
  581. */
  582. void Sys_ShutdownInput( void ) {
  583. IN_DeactivateMouse();
  584. IN_DeactivateKeyboard();
  585. if ( win32.g_pKeyboard ) {
  586. win32.g_pKeyboard->Release();
  587. win32.g_pKeyboard = NULL;
  588. }
  589. if ( win32.g_pMouse ) {
  590. win32.g_pMouse->Release();
  591. win32.g_pMouse = NULL;
  592. }
  593. if ( win32.g_pdi ) {
  594. win32.g_pdi->Release();
  595. win32.g_pdi = NULL;
  596. }
  597. }
  598. /*
  599. ===========
  600. Sys_InitInput
  601. ===========
  602. */
  603. void Sys_InitInput( void ) {
  604. common->Printf ("\n------- Input Initialization -------\n");
  605. IN_InitDirectInput();
  606. if ( win32.in_mouse.GetBool() ) {
  607. IN_InitDIMouse();
  608. // don't grab the mouse on initialization
  609. Sys_GrabMouseCursor( false );
  610. } else {
  611. common->Printf ("Mouse control not active.\n");
  612. }
  613. IN_StartupKeyboard();
  614. common->Printf ("------------------------------------\n");
  615. win32.in_mouse.ClearModified();
  616. }
  617. #endif
  618. /*
  619. ===========
  620. Sys_InitScanTable
  621. ===========
  622. */
  623. void Sys_InitScanTable( void ) {
  624. idStr lang = cvarSystem->GetCVarString( "sys_lang" );
  625. if ( lang.Length() == 0 ) {
  626. lang = "english";
  627. }
  628. if ( lang.Icmp( "english" ) == 0 ) {
  629. keyScanTable = s_scantokey;
  630. // the only reason that english right alt binds as K_ALT is so that
  631. // users who were using right-alt before the patch don't suddenly find
  632. // that only left-alt is working.
  633. rightAltKey = K_ALT;
  634. } else if ( lang.Icmp( "spanish" ) == 0 ) {
  635. keyScanTable = s_scantokey_spanish;
  636. rightAltKey = K_RIGHT_ALT;
  637. } else if ( lang.Icmp( "french" ) == 0 ) {
  638. keyScanTable = s_scantokey_french;
  639. rightAltKey = K_RIGHT_ALT;
  640. } else if ( lang.Icmp( "german" ) == 0 ) {
  641. keyScanTable = s_scantokey_german;
  642. rightAltKey = K_RIGHT_ALT;
  643. } else if ( lang.Icmp( "italian" ) == 0 ) {
  644. keyScanTable = s_scantokey_italian;
  645. rightAltKey = K_RIGHT_ALT;
  646. }
  647. }
  648. /*
  649. ==================
  650. Sys_GetScanTable
  651. ==================
  652. */
  653. const unsigned char *Sys_GetScanTable( void ) {
  654. return keyScanTable;
  655. }
  656. #ifndef USE_SDL
  657. /*
  658. ===============
  659. Sys_GetConsoleKey
  660. ===============
  661. */
  662. unsigned char Sys_GetConsoleKey( bool shifted ) {
  663. return keyScanTable[41 + ( shifted ? 128 : 0 )];
  664. }
  665. /*
  666. ==================
  667. IN_Frame
  668. Called every frame, even if not generating commands
  669. ==================
  670. */
  671. void IN_Frame( void ) {
  672. bool shouldGrab = true;
  673. if ( !win32.in_mouse.GetBool() ) {
  674. shouldGrab = false;
  675. }
  676. // if fullscreen, we always want the mouse
  677. if ( !win32.cdsFullscreen ) {
  678. if ( win32.mouseReleased ) {
  679. shouldGrab = false;
  680. }
  681. if ( win32.movingWindow ) {
  682. shouldGrab = false;
  683. }
  684. if ( !win32.activeApp ) {
  685. shouldGrab = false;
  686. }
  687. }
  688. if ( shouldGrab != win32.mouseGrabbed ) {
  689. if ( win32.mouseGrabbed ) {
  690. IN_DeactivateMouse();
  691. } else {
  692. IN_ActivateMouse();
  693. #if 0 // if we can't reacquire, try reinitializing
  694. if ( !IN_InitDIMouse() ) {
  695. win32.in_mouse.SetBool( false );
  696. return;
  697. }
  698. #endif
  699. }
  700. }
  701. }
  702. void Sys_GrabMouseCursor( bool grabIt ) {
  703. #ifndef ID_DEDICATED
  704. win32.mouseReleased = !grabIt;
  705. if ( !grabIt ) {
  706. // release it right now
  707. IN_Frame();
  708. }
  709. #endif
  710. }
  711. //=====================================================================================
  712. static DIDEVICEOBJECTDATA polled_didod[ DINPUT_BUFFERSIZE ]; // Receives buffered data
  713. static int diFetch;
  714. static byte toggleFetch[2][ 256 ];
  715. #if 1
  716. // I tried doing the full-state get to address a keyboard problem on one system,
  717. // but it didn't make any difference
  718. /*
  719. ====================
  720. Sys_PollKeyboardInputEvents
  721. ====================
  722. */
  723. int Sys_PollKeyboardInputEvents( void ) {
  724. DWORD dwElements;
  725. HRESULT hr;
  726. if( win32.g_pKeyboard == NULL ) {
  727. return 0;
  728. }
  729. dwElements = DINPUT_BUFFERSIZE;
  730. hr = win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
  731. polled_didod, &dwElements, 0 );
  732. if( hr != DI_OK )
  733. {
  734. // We got an error or we got DI_BUFFEROVERFLOW.
  735. //
  736. // Either way, it means that continuous contact with the
  737. // device has been lost, either due to an external
  738. // interruption, or because the buffer overflowed
  739. // and some events were lost.
  740. hr = win32.g_pKeyboard->Acquire();
  741. // nuke the garbage
  742. if (!FAILED(hr)) {
  743. //Bug 951: The following command really clears the garbage input.
  744. //The original will still process keys in the buffer and was causing
  745. //some problems.
  746. win32.g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), NULL, &dwElements, 0 );
  747. dwElements = 0;
  748. }
  749. // hr may be DIERR_OTHERAPPHASPRIO or other errors. This
  750. // may occur when the app is minimized or in the process of
  751. // switching, so just try again later
  752. }
  753. if( FAILED(hr) ) {
  754. return 0;
  755. }
  756. return dwElements;
  757. }
  758. #else
  759. /*
  760. ====================
  761. Sys_PollKeyboardInputEvents
  762. Fake events by getting the entire device state
  763. and checking transitions
  764. ====================
  765. */
  766. int Sys_PollKeyboardInputEvents( void ) {
  767. HRESULT hr;
  768. if( win32.g_pKeyboard == NULL ) {
  769. return 0;
  770. }
  771. hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
  772. if( hr != DI_OK )
  773. {
  774. // We got an error or we got DI_BUFFEROVERFLOW.
  775. //
  776. // Either way, it means that continuous contact with the
  777. // device has been lost, either due to an external
  778. // interruption, or because the buffer overflowed
  779. // and some events were lost.
  780. hr = win32.g_pKeyboard->Acquire();
  781. // nuke the garbage
  782. if (!FAILED(hr)) {
  783. hr = win32.g_pKeyboard->GetDeviceState( sizeof( toggleFetch[ diFetch ] ), toggleFetch[ diFetch ] );
  784. }
  785. // hr may be DIERR_OTHERAPPHASPRIO or other errors. This
  786. // may occur when the app is minimized or in the process of
  787. // switching, so just try again later
  788. }
  789. if( FAILED(hr) ) {
  790. return 0;
  791. }
  792. // build faked events
  793. int numChanges = 0;
  794. for ( int i = 0 ; i < 256 ; i++ ) {
  795. if ( toggleFetch[0][i] != toggleFetch[1][i] ) {
  796. polled_didod[ numChanges ].dwOfs = i;
  797. polled_didod[ numChanges ].dwData = toggleFetch[ diFetch ][i] ? 0x80 : 0;
  798. numChanges++;
  799. }
  800. }
  801. diFetch ^= 1;
  802. return numChanges;
  803. }
  804. #endif
  805. /*
  806. ====================
  807. Sys_PollKeyboardInputEvents
  808. ====================
  809. */
  810. int Sys_ReturnKeyboardInputEvent( const int n, int &ch, bool &state ) {
  811. ch = IN_DIMapKey( polled_didod[ n ].dwOfs );
  812. state = (polled_didod[ n ].dwData & 0x80) == 0x80;
  813. if ( ch == K_PRINT_SCR || ch == K_CTRL || ch == K_ALT || ch == K_RIGHT_ALT ) {
  814. // for windows, add a keydown event for print screen here, since
  815. // windows doesn't send keydown events to the WndProc for this key.
  816. // ctrl and alt are handled here to get around windows sending ctrl and
  817. // alt messages when the right-alt is pressed on non-US 102 keyboards.
  818. Sys_QueEvent( GetTickCount(), SE_KEY, ch, state, 0, NULL );
  819. }
  820. return ch;
  821. }
  822. void Sys_EndKeyboardInputEvents( void ) {
  823. }
  824. void Sys_QueMouseEvents( int dwElements ) {
  825. int i, value;
  826. for( i = 0; i < dwElements; i++ ) {
  827. if ( polled_didod[i].dwOfs >= DIMOFS_BUTTON0 && polled_didod[i].dwOfs <= DIMOFS_BUTTON7 ) {
  828. value = (polled_didod[i].dwData & 0x80) == 0x80;
  829. Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, K_MOUSE1 + ( polled_didod[i].dwOfs - DIMOFS_BUTTON0 ), value, 0, NULL );
  830. } else {
  831. switch (polled_didod[i].dwOfs) {
  832. case DIMOFS_X:
  833. value = polled_didod[i].dwData;
  834. Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_MOUSE, value, 0, 0, NULL );
  835. break;
  836. case DIMOFS_Y:
  837. value = polled_didod[i].dwData;
  838. Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_MOUSE, 0, value, 0, NULL );
  839. break;
  840. case DIMOFS_Z:
  841. value = ( (int) polled_didod[i].dwData ) / WHEEL_DELTA;
  842. int key = value < 0 ? K_MWHEELDOWN : K_MWHEELUP;
  843. value = abs( value );
  844. while( value-- > 0 ) {
  845. Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, key, true, 0, NULL );
  846. Sys_QueEvent( polled_didod[i].dwTimeStamp, SE_KEY, key, false, 0, NULL );
  847. }
  848. break;
  849. }
  850. }
  851. }
  852. }
  853. //=====================================================================================
  854. int Sys_PollMouseInputEvents( void ) {
  855. DWORD dwElements;
  856. HRESULT hr;
  857. if ( !win32.g_pMouse || !win32.mouseGrabbed ) {
  858. return 0;
  859. }
  860. dwElements = DINPUT_BUFFERSIZE;
  861. hr = win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
  862. if( hr != DI_OK ) {
  863. hr = win32.g_pMouse->Acquire();
  864. // clear the garbage
  865. if (!FAILED(hr)) {
  866. win32.g_pMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), polled_didod, &dwElements, 0 );
  867. }
  868. }
  869. if( FAILED(hr) ) {
  870. return 0;
  871. }
  872. Sys_QueMouseEvents( dwElements );
  873. return dwElements;
  874. }
  875. int Sys_ReturnMouseInputEvent( const int n, int &action, int &value ) {
  876. int diaction = polled_didod[n].dwOfs;
  877. if ( diaction >= DIMOFS_BUTTON0 && diaction <= DIMOFS_BUTTON7 ) {
  878. value = (polled_didod[n].dwData & 0x80) == 0x80;
  879. action = M_ACTION1 + ( diaction - DIMOFS_BUTTON0 );
  880. return 1;
  881. }
  882. switch( diaction ) {
  883. case DIMOFS_X:
  884. value = polled_didod[n].dwData;
  885. action = M_DELTAX;
  886. return 1;
  887. case DIMOFS_Y:
  888. value = polled_didod[n].dwData;
  889. action = M_DELTAY;
  890. return 1;
  891. case DIMOFS_Z:
  892. // mouse wheel actions are impulses, without a specific up / down
  893. value = ( (int) polled_didod[n].dwData ) / WHEEL_DELTA;
  894. action = M_DELTAZ;
  895. // a value of zero here should never happen
  896. if ( value == 0 ) {
  897. return 0;
  898. }
  899. return 1;
  900. }
  901. return 0;
  902. }
  903. void Sys_EndMouseInputEvents( void ) { }
  904. unsigned char Sys_MapCharForKey( int key ) {
  905. return (unsigned char)key;
  906. }
  907. /*
  908. ================
  909. Joystick Input Methods
  910. ================
  911. */
  912. void Sys_SetRumble( int device, int low, int hi ) {
  913. }
  914. int Sys_PollJoystickInputEvents( int deviceNum ) {
  915. return 0;
  916. }
  917. int Sys_ReturnJoystickInputEvent( const int n, int &action, int &value ) {
  918. return 0;
  919. }
  920. void Sys_EndJoystickInputEvents() {
  921. }
  922. #endif