Ulrich Weigand | 2b06758 | 1998-11-08 12:26:36 +0000 | [diff] [blame] | 1 | /* |
| 2 | * USER Input processing |
| 3 | * |
| 4 | * Copyright 1993 Bob Amstadt |
| 5 | * Copyright 1996 Albrecht Kleine |
| 6 | * Copyright 1997 David Faure |
| 7 | * Copyright 1998 Morten Welinder |
| 8 | * Copyright 1998 Ulrich Weigand |
| 9 | * |
| 10 | */ |
| 11 | |
| 12 | #include <stdlib.h> |
| 13 | #include <string.h> |
| 14 | #include <ctype.h> |
| 15 | #include <assert.h> |
| 16 | |
| 17 | #include "windows.h" |
| 18 | #include "win.h" |
| 19 | #include "gdi.h" |
| 20 | #include "heap.h" |
| 21 | #include "input.h" |
| 22 | #include "keyboard.h" |
| 23 | #include "mouse.h" |
| 24 | #include "message.h" |
| 25 | #include "debug.h" |
| 26 | #include "debugtools.h" |
| 27 | #include "struct32.h" |
| 28 | #include "winerror.h" |
| 29 | |
| 30 | static INT16 captureHT = HTCLIENT; |
| 31 | static HWND32 captureWnd = 0; |
| 32 | static BOOL32 InputEnabled = TRUE; |
| 33 | static BOOL32 SwappedButtons = FALSE; |
| 34 | |
| 35 | BOOL32 MouseButtonsStates[3]; |
| 36 | BOOL32 AsyncMouseButtonsStates[3]; |
| 37 | BYTE InputKeyStateTable[256]; |
| 38 | BYTE QueueKeyStateTable[256]; |
| 39 | BYTE AsyncKeyStateTable[256]; |
| 40 | |
| 41 | typedef union |
| 42 | { |
| 43 | struct |
| 44 | { |
| 45 | unsigned long count : 16; |
| 46 | unsigned long code : 8; |
| 47 | unsigned long extended : 1; |
| 48 | unsigned long unused : 2; |
| 49 | unsigned long win_internal : 2; |
| 50 | unsigned long context : 1; |
| 51 | unsigned long previous : 1; |
| 52 | unsigned long transition : 1; |
| 53 | } lp1; |
| 54 | unsigned long lp2; |
| 55 | } KEYLP; |
| 56 | |
| 57 | /*********************************************************************** |
| 58 | * keybd_event (USER32.583) |
| 59 | */ |
| 60 | void WINAPI keybd_event( BYTE bVk, BYTE bScan, |
| 61 | DWORD dwFlags, DWORD dwExtraInfo ) |
| 62 | { |
| 63 | DWORD posX, posY, time, extra; |
| 64 | WORD message; |
| 65 | KEYLP keylp; |
| 66 | keylp.lp2 = 0; |
| 67 | |
| 68 | if (!InputEnabled) return; |
| 69 | |
| 70 | /* |
| 71 | * If we are called by the Wine keyboard driver, use the additional |
| 72 | * info pointed to by the dwExtraInfo argument. |
| 73 | * Otherwise, we need to determine that info ourselves (probably |
| 74 | * less accurate, but we can't help that ...). |
| 75 | */ |
| 76 | if ( !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) ) |
| 77 | && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC ) |
| 78 | { |
| 79 | WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo; |
| 80 | posX = wke->posX; |
| 81 | posY = wke->posY; |
| 82 | time = wke->time; |
| 83 | extra = 0; |
| 84 | } |
| 85 | else |
| 86 | { |
| 87 | DWORD keyState; |
| 88 | time = GetTickCount(); |
| 89 | extra = dwExtraInfo; |
| 90 | |
| 91 | if ( !EVENT_QueryPointer( &posX, &posY, &keyState )) |
| 92 | return; |
| 93 | } |
| 94 | |
| 95 | |
| 96 | keylp.lp1.count = 1; |
| 97 | keylp.lp1.code = bScan; |
| 98 | keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0; |
| 99 | keylp.lp1.win_internal = 0; /* this has something to do with dialogs, |
| 100 | * don't remember where I read it - AK */ |
| 101 | /* it's '1' under windows, when a dialog box appears |
| 102 | * and you press one of the underlined keys - DF*/ |
| 103 | |
| 104 | if ( dwFlags & KEYEVENTF_KEYUP ) |
| 105 | { |
| 106 | BOOL32 sysKey = (InputKeyStateTable[VK_MENU] & 0x80) |
| 107 | && !(InputKeyStateTable[VK_CONTROL] & 0x80) |
| 108 | && !(dwFlags & KEYEVENTF_WINE_FORCEEXTENDED); /* for Alt from AltGr */ |
| 109 | |
| 110 | InputKeyStateTable[bVk] &= ~0x80; |
| 111 | keylp.lp1.previous = 1; |
| 112 | keylp.lp1.transition = 1; |
| 113 | message = sysKey ? WM_SYSKEYUP : WM_KEYUP; |
| 114 | } |
| 115 | else |
| 116 | { |
| 117 | keylp.lp1.previous = (InputKeyStateTable[bVk] & 0x80) != 0; |
| 118 | keylp.lp1.transition = 0; |
| 119 | |
| 120 | if (!(InputKeyStateTable[bVk] & 0x80)) |
| 121 | InputKeyStateTable[bVk] ^= 0x01; |
| 122 | InputKeyStateTable[bVk] |= 0x80; |
| 123 | |
| 124 | message = (InputKeyStateTable[VK_MENU] & 0x80) |
| 125 | && !(InputKeyStateTable[VK_CONTROL] & 0x80) |
| 126 | ? WM_SYSKEYDOWN : WM_KEYDOWN; |
| 127 | } |
| 128 | |
| 129 | if ( message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ) |
| 130 | keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */ |
| 131 | |
| 132 | |
| 133 | TRACE(key, " wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 ); |
| 134 | TRACE(key, " InputKeyState=%X\n", InputKeyStateTable[bVk] ); |
| 135 | |
| 136 | hardware_event( message, bVk, keylp.lp2, posX, posY, time, extra ); |
| 137 | } |
| 138 | |
| 139 | /*********************************************************************** |
| 140 | * mouse_event (USER32.584) |
| 141 | */ |
| 142 | void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, |
| 143 | DWORD cButtons, DWORD dwExtraInfo ) |
| 144 | { |
| 145 | DWORD posX, posY, keyState, time, extra; |
| 146 | |
| 147 | if (!InputEnabled) return; |
| 148 | |
| 149 | /* |
| 150 | * If we are called by the Wine mouse driver, use the additional |
| 151 | * info pointed to by the dwExtraInfo argument. |
| 152 | * Otherwise, we need to determine that info ourselves (probably |
| 153 | * less accurate, but we can't help that ...). |
| 154 | */ |
| 155 | if ( !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) ) |
| 156 | && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) |
| 157 | { |
| 158 | WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo; |
| 159 | keyState = wme->keyState; |
| 160 | time = wme->time; |
| 161 | extra = (DWORD)wme->hWnd; |
| 162 | |
| 163 | assert( dwFlags & MOUSEEVENTF_ABSOLUTE ); |
| 164 | posX = (dx * screenWidth) >> 16; |
| 165 | posY = (dy * screenHeight) >> 16; |
| 166 | } |
| 167 | else |
| 168 | { |
| 169 | time = GetTickCount(); |
| 170 | extra = dwExtraInfo; |
| 171 | |
| 172 | if ( !EVENT_QueryPointer( &posX, &posY, &keyState )) |
| 173 | return; |
| 174 | |
| 175 | if ( dwFlags & MOUSEEVENTF_MOVE ) |
| 176 | { |
| 177 | if ( dwFlags & MOUSEEVENTF_ABSOLUTE ) |
| 178 | { |
| 179 | posX = (dx * screenWidth) >> 16; |
| 180 | posY = (dy * screenHeight) >> 16; |
| 181 | } |
| 182 | else |
| 183 | { |
| 184 | posX += dx; |
| 185 | posY += dy; |
| 186 | } |
| 187 | /* We have to actually move the cursor */ |
| 188 | SetCursorPos32( posX, posY ); |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | if ( dwFlags & MOUSEEVENTF_MOVE ) |
| 193 | { |
| 194 | hardware_event( WM_MOUSEMOVE, |
| 195 | keyState, 0L, posX, posY, time, extra ); |
| 196 | } |
| 197 | if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) ) |
| 198 | { |
| 199 | MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE; |
| 200 | hardware_event( WM_LBUTTONDOWN, |
| 201 | keyState, 0L, posX, posY, time, extra ); |
| 202 | } |
| 203 | if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) ) |
| 204 | { |
| 205 | MouseButtonsStates[0] = FALSE; |
| 206 | hardware_event( WM_LBUTTONUP, |
| 207 | keyState, 0L, posX, posY, time, extra ); |
| 208 | } |
| 209 | if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) ) |
| 210 | { |
| 211 | MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE; |
| 212 | hardware_event( WM_RBUTTONDOWN, |
| 213 | keyState, 0L, posX, posY, time, extra ); |
| 214 | } |
| 215 | if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) ) |
| 216 | { |
| 217 | MouseButtonsStates[2] = FALSE; |
| 218 | hardware_event( WM_RBUTTONUP, |
| 219 | keyState, 0L, posX, posY, time, extra ); |
| 220 | } |
| 221 | if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) |
| 222 | { |
| 223 | MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE; |
| 224 | hardware_event( WM_MBUTTONDOWN, |
| 225 | keyState, 0L, posX, posY, time, extra ); |
| 226 | } |
| 227 | if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) |
| 228 | { |
| 229 | MouseButtonsStates[1] = FALSE; |
| 230 | hardware_event( WM_MBUTTONUP, |
| 231 | keyState, 0L, posX, posY, time, extra ); |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | /********************************************************************** |
| 236 | * EnableHardwareInput (USER.331) |
| 237 | */ |
| 238 | BOOL16 WINAPI EnableHardwareInput(BOOL16 bEnable) |
| 239 | { |
| 240 | BOOL16 bOldState = InputEnabled; |
| 241 | FIXME(event,"(%d) - stub\n", bEnable); |
| 242 | InputEnabled = bEnable; |
| 243 | return bOldState; |
| 244 | } |
| 245 | |
| 246 | |
| 247 | /*********************************************************************** |
| 248 | * SwapMouseButton16 (USER.186) |
| 249 | */ |
| 250 | BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap ) |
| 251 | { |
| 252 | BOOL16 ret = SwappedButtons; |
| 253 | SwappedButtons = fSwap; |
| 254 | return ret; |
| 255 | } |
| 256 | |
| 257 | |
| 258 | /*********************************************************************** |
| 259 | * SwapMouseButton32 (USER32.537) |
| 260 | */ |
| 261 | BOOL32 WINAPI SwapMouseButton32( BOOL32 fSwap ) |
| 262 | { |
| 263 | BOOL32 ret = SwappedButtons; |
| 264 | SwappedButtons = fSwap; |
| 265 | return ret; |
| 266 | } |
| 267 | |
| 268 | /********************************************************************** |
| 269 | * EVENT_Capture |
| 270 | * |
| 271 | * We need this to be able to generate double click messages |
| 272 | * when menu code captures mouse in the window without CS_DBLCLK style. |
| 273 | */ |
| 274 | HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht) |
| 275 | { |
| 276 | HWND32 capturePrev = captureWnd; |
| 277 | |
| 278 | if (!hwnd) |
| 279 | { |
| 280 | captureWnd = 0L; |
| 281 | captureHT = 0; |
| 282 | } |
| 283 | else |
| 284 | { |
| 285 | WND* wndPtr = WIN_FindWndPtr( hwnd ); |
| 286 | if (wndPtr) |
| 287 | { |
| 288 | TRACE(win, "(0x%04x)\n", hwnd ); |
| 289 | captureWnd = hwnd; |
| 290 | captureHT = ht; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | if( capturePrev && capturePrev != captureWnd ) |
| 295 | { |
| 296 | WND* wndPtr = WIN_FindWndPtr( capturePrev ); |
| 297 | if( wndPtr && (wndPtr->flags & WIN_ISWIN32) ) |
| 298 | SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd); |
| 299 | } |
| 300 | return capturePrev; |
| 301 | } |
| 302 | |
| 303 | /********************************************************************** |
| 304 | * EVENT_GetCaptureInfo |
| 305 | */ |
| 306 | INT16 EVENT_GetCaptureInfo() |
| 307 | { |
| 308 | return captureHT; |
| 309 | } |
| 310 | |
| 311 | /********************************************************************** |
| 312 | * SetCapture16 (USER.18) |
| 313 | */ |
| 314 | HWND16 WINAPI SetCapture16( HWND16 hwnd ) |
| 315 | { |
| 316 | return (HWND16)EVENT_Capture( hwnd, HTCLIENT ); |
| 317 | } |
| 318 | |
| 319 | |
| 320 | /********************************************************************** |
| 321 | * SetCapture32 (USER32.464) |
| 322 | */ |
| 323 | HWND32 WINAPI SetCapture32( HWND32 hwnd ) |
| 324 | { |
| 325 | return EVENT_Capture( hwnd, HTCLIENT ); |
| 326 | } |
| 327 | |
| 328 | |
| 329 | /********************************************************************** |
| 330 | * ReleaseCapture (USER.19) (USER32.439) |
| 331 | */ |
| 332 | void WINAPI ReleaseCapture(void) |
| 333 | { |
| 334 | TRACE(win, "captureWnd=%04x\n", captureWnd ); |
| 335 | if( captureWnd ) EVENT_Capture( 0, 0 ); |
| 336 | } |
| 337 | |
| 338 | |
| 339 | /********************************************************************** |
| 340 | * GetCapture16 (USER.236) |
| 341 | */ |
| 342 | HWND16 WINAPI GetCapture16(void) |
| 343 | { |
| 344 | return captureWnd; |
| 345 | } |
| 346 | |
| 347 | /********************************************************************** |
| 348 | * GetCapture32 (USER32.208) |
| 349 | */ |
| 350 | HWND32 WINAPI GetCapture32(void) |
| 351 | { |
| 352 | return captureWnd; |
| 353 | } |
| 354 | |
| 355 | /********************************************************************** |
| 356 | * GetKeyState (USER.106) |
| 357 | */ |
Uwe Bonnes | 9fdceb8 | 1998-11-08 13:12:49 +0000 | [diff] [blame] | 358 | INT16 WINAPI GetKeyState16(INT16 vkey) |
Ulrich Weigand | 2b06758 | 1998-11-08 12:26:36 +0000 | [diff] [blame] | 359 | { |
| 360 | return GetKeyState32(vkey); |
| 361 | } |
| 362 | |
| 363 | /********************************************************************** |
| 364 | * GetKeyState (USER32.249) |
| 365 | * |
| 366 | * An application calls the GetKeyState function in response to a |
| 367 | * keyboard-input message. This function retrieves the state of the key |
| 368 | * at the time the input message was generated. (SDK 3.1 Vol 2. p 390) |
| 369 | */ |
Uwe Bonnes | 9fdceb8 | 1998-11-08 13:12:49 +0000 | [diff] [blame] | 370 | INT16 WINAPI GetKeyState32(INT32 vkey) |
Ulrich Weigand | 2b06758 | 1998-11-08 12:26:36 +0000 | [diff] [blame] | 371 | { |
| 372 | INT32 retval; |
| 373 | |
| 374 | switch (vkey) |
| 375 | { |
| 376 | case VK_LBUTTON : /* VK_LBUTTON is 1 */ |
| 377 | retval = MouseButtonsStates[0] ? 0x8000 : 0; |
| 378 | break; |
| 379 | case VK_MBUTTON : /* VK_MBUTTON is 4 */ |
| 380 | retval = MouseButtonsStates[1] ? 0x8000 : 0; |
| 381 | break; |
| 382 | case VK_RBUTTON : /* VK_RBUTTON is 2 */ |
| 383 | retval = MouseButtonsStates[2] ? 0x8000 : 0; |
| 384 | break; |
| 385 | default : |
| 386 | if (vkey >= 'a' && vkey <= 'z') |
| 387 | vkey += 'A' - 'a'; |
| 388 | retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) | |
| 389 | (WORD)(QueueKeyStateTable[vkey] & 0x01); |
| 390 | } |
| 391 | /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */ |
| 392 | return retval; |
| 393 | } |
| 394 | |
| 395 | /********************************************************************** |
| 396 | * GetKeyboardState (USER.222)(USER32.254) |
| 397 | * |
| 398 | * An application calls the GetKeyboardState function in response to a |
| 399 | * keyboard-input message. This function retrieves the state of the keyboard |
| 400 | * at the time the input message was generated. (SDK 3.1 Vol 2. p 387) |
| 401 | */ |
| 402 | VOID WINAPI GetKeyboardState(LPBYTE lpKeyState) |
| 403 | { |
| 404 | TRACE(key, "(%p)\n", lpKeyState); |
| 405 | if (lpKeyState != NULL) { |
| 406 | QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0; |
| 407 | QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0; |
| 408 | QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0; |
| 409 | memcpy(lpKeyState, QueueKeyStateTable, 256); |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | /********************************************************************** |
| 414 | * SetKeyboardState (USER.223)(USER32.484) |
| 415 | */ |
| 416 | VOID WINAPI SetKeyboardState(LPBYTE lpKeyState) |
| 417 | { |
| 418 | TRACE(key, "(%p)\n", lpKeyState); |
| 419 | if (lpKeyState != NULL) { |
| 420 | memcpy(QueueKeyStateTable, lpKeyState, 256); |
| 421 | MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0); |
| 422 | MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0); |
| 423 | MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0); |
| 424 | } |
| 425 | } |
| 426 | |
| 427 | /********************************************************************** |
| 428 | * GetAsyncKeyState32 (USER32.207) |
| 429 | * |
| 430 | * Determine if a key is or was pressed. retval has high-order |
| 431 | * bit set to 1 if currently pressed, low-order bit set to 1 if key has |
| 432 | * been pressed. |
| 433 | * |
| 434 | * This uses the variable AsyncMouseButtonsStates and |
| 435 | * AsyncKeyStateTable (set in event.c) which have the mouse button |
| 436 | * number or key number (whichever is applicable) set to true if the |
| 437 | * mouse or key had been depressed since the last call to |
| 438 | * GetAsyncKeyState. |
| 439 | */ |
| 440 | WORD WINAPI GetAsyncKeyState32(INT32 nKey) |
| 441 | { |
| 442 | short retval; |
| 443 | |
| 444 | switch (nKey) { |
| 445 | case VK_LBUTTON: |
| 446 | retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) | |
| 447 | (MouseButtonsStates[0] ? 0x8000 : 0); |
| 448 | break; |
| 449 | case VK_MBUTTON: |
| 450 | retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) | |
| 451 | (MouseButtonsStates[1] ? 0x8000 : 0); |
| 452 | break; |
| 453 | case VK_RBUTTON: |
| 454 | retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) | |
| 455 | (MouseButtonsStates[2] ? 0x8000 : 0); |
| 456 | break; |
| 457 | default: |
| 458 | retval = AsyncKeyStateTable[nKey] | |
| 459 | ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0); |
| 460 | break; |
| 461 | } |
| 462 | |
| 463 | /* all states to false */ |
| 464 | memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) ); |
| 465 | memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) ); |
| 466 | |
| 467 | TRACE(key, "(%x) -> %x\n", nKey, retval); |
| 468 | return retval; |
| 469 | } |
| 470 | |
| 471 | /********************************************************************** |
| 472 | * GetAsyncKeyState16 (USER.249) |
| 473 | */ |
| 474 | WORD WINAPI GetAsyncKeyState16(INT16 nKey) |
| 475 | { |
| 476 | return GetAsyncKeyState32(nKey); |
| 477 | } |
| 478 | |
| 479 | /********************************************************************** |
| 480 | * KBD_translate_accelerator |
| 481 | * |
| 482 | * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages |
| 483 | */ |
| 484 | static BOOL32 KBD_translate_accelerator(HWND32 hWnd,LPMSG32 msg, |
| 485 | BYTE fVirt,WORD key,WORD cmd) |
| 486 | { |
| 487 | BOOL32 sendmsg = FALSE; |
| 488 | |
| 489 | if(msg->wParam == key) |
| 490 | { |
| 491 | if (msg->message == WM_CHAR) { |
| 492 | if ( !(fVirt & FALT) && !(fVirt & FVIRTKEY) ) |
| 493 | { |
| 494 | TRACE(accel,"found accel for WM_CHAR: ('%c')\n", |
| 495 | msg->wParam&0xff); |
| 496 | sendmsg=TRUE; |
| 497 | } |
| 498 | } else { |
| 499 | if(fVirt & FVIRTKEY) { |
| 500 | INT32 mask = 0; |
| 501 | TRACE(accel,"found accel for virt_key %04x (scan %04x)\n", |
| 502 | msg->wParam,0xff & HIWORD(msg->lParam)); |
| 503 | if(GetKeyState32(VK_SHIFT) & 0x8000) mask |= FSHIFT; |
| 504 | if(GetKeyState32(VK_CONTROL) & 0x8000) mask |= FCONTROL; |
| 505 | if(GetKeyState32(VK_MENU) & 0x8000) mask |= FALT; |
| 506 | if(mask == (fVirt & (FSHIFT | FCONTROL | FALT))) |
| 507 | sendmsg=TRUE; |
| 508 | else |
| 509 | TRACE(accel,", but incorrect SHIFT/CTRL/ALT-state\n"); |
| 510 | } |
| 511 | else |
| 512 | { |
| 513 | if (!(msg->lParam & 0x01000000)) /* no special_key */ |
| 514 | { |
| 515 | if ((fVirt & FALT) && (msg->lParam & 0x20000000)) |
| 516 | { /* ^^ ALT pressed */ |
| 517 | TRACE(accel,"found accel for Alt-%c\n", msg->wParam&0xff); |
| 518 | sendmsg=TRUE; |
| 519 | } |
| 520 | } |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | if (sendmsg) /* found an accelerator, but send a message... ? */ |
| 525 | { |
| 526 | INT16 iSysStat,iStat,mesg=0; |
| 527 | HMENU16 hMenu; |
| 528 | |
| 529 | if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) |
| 530 | mesg=1; |
| 531 | else |
| 532 | if (GetCapture32()) |
| 533 | mesg=2; |
| 534 | else |
| 535 | if (!IsWindowEnabled32(hWnd)) |
| 536 | mesg=3; |
| 537 | else |
| 538 | { |
| 539 | WND* wndPtr = WIN_FindWndPtr(hWnd); |
| 540 | |
| 541 | hMenu = (wndPtr->dwStyle & WS_CHILD) ? 0 : (HMENU32)wndPtr->wIDmenu; |
| 542 | iSysStat = (wndPtr->hSysMenu) ? GetMenuState32(GetSubMenu16(wndPtr->hSysMenu, 0), |
| 543 | cmd, MF_BYCOMMAND) : -1 ; |
| 544 | iStat = (hMenu) ? GetMenuState32(hMenu, |
| 545 | cmd, MF_BYCOMMAND) : -1 ; |
| 546 | |
| 547 | if (iSysStat!=-1) |
| 548 | { |
| 549 | if (iSysStat & (MF_DISABLED|MF_GRAYED)) |
| 550 | mesg=4; |
| 551 | else |
| 552 | mesg=WM_SYSCOMMAND; |
| 553 | } |
| 554 | else |
| 555 | { |
| 556 | if (iStat!=-1) |
| 557 | { |
| 558 | if (IsIconic32(hWnd)) |
| 559 | mesg=5; |
| 560 | else |
| 561 | { |
| 562 | if (iStat & (MF_DISABLED|MF_GRAYED)) |
| 563 | mesg=6; |
| 564 | else |
| 565 | mesg=WM_COMMAND; |
| 566 | } |
| 567 | } |
| 568 | else |
| 569 | mesg=WM_COMMAND; |
| 570 | } |
| 571 | } |
| 572 | if ( mesg==WM_COMMAND || mesg==WM_SYSCOMMAND ) |
| 573 | { |
| 574 | TRACE(accel,", sending %s, wParam=%0x\n", |
| 575 | mesg==WM_COMMAND ? "WM_COMMAND" : "WM_SYSCOMMAND", |
| 576 | cmd); |
| 577 | SendMessage32A(hWnd, mesg, cmd, 0x00010000L); |
| 578 | } |
| 579 | else |
| 580 | { |
| 581 | /* some reasons for NOT sending the WM_{SYS}COMMAND message: |
| 582 | * #0: unknown (please report!) |
| 583 | * #1: for WM_KEYUP,WM_SYSKEYUP |
| 584 | * #2: mouse is captured |
| 585 | * #3: window is disabled |
| 586 | * #4: it's a disabled system menu option |
| 587 | * #5: it's a menu option, but window is iconic |
| 588 | * #6: it's a menu option, but disabled |
| 589 | */ |
| 590 | TRACE(accel,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg); |
| 591 | if(mesg==0) |
| 592 | ERR(accel, " unknown reason - please report!"); |
| 593 | } |
| 594 | return TRUE; |
| 595 | } |
| 596 | } |
| 597 | return FALSE; |
| 598 | } |
| 599 | |
| 600 | /********************************************************************** |
| 601 | * TranslateAccelerator32 (USER32.551)(USER32.552)(USER32.553) |
| 602 | */ |
| 603 | INT32 WINAPI TranslateAccelerator32(HWND32 hWnd, HACCEL32 hAccel, LPMSG32 msg) |
| 604 | { |
| 605 | LPACCEL32 lpAccelTbl = (LPACCEL32)LockResource32(hAccel); |
| 606 | int i; |
| 607 | |
| 608 | TRACE(accel,"hwnd=0x%x hacc=0x%x msg=0x%x wp=0x%x lp=0x%lx\n", hWnd, hAccel, msg->message, msg->wParam, msg->lParam); |
| 609 | |
| 610 | if (hAccel == 0 || msg == NULL || |
| 611 | (msg->message != WM_KEYDOWN && |
| 612 | msg->message != WM_KEYUP && |
| 613 | msg->message != WM_SYSKEYDOWN && |
| 614 | msg->message != WM_SYSKEYUP && |
| 615 | msg->message != WM_CHAR)) { |
| 616 | WARN(accel, "erraneous input parameters\n"); |
| 617 | SetLastError(ERROR_INVALID_PARAMETER); |
| 618 | return 0; |
| 619 | } |
| 620 | |
| 621 | TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x," |
| 622 | "msg->hwnd=%04x, msg->message=%04x\n", |
| 623 | hAccel,hWnd,msg->hwnd,msg->message); |
| 624 | |
| 625 | i = 0; |
| 626 | do |
| 627 | { |
| 628 | if (KBD_translate_accelerator(hWnd,msg,lpAccelTbl[i].fVirt, |
| 629 | lpAccelTbl[i].key,lpAccelTbl[i].cmd)) |
| 630 | return 1; |
| 631 | } while ((lpAccelTbl[i++].fVirt & 0x80) == 0); |
| 632 | WARN(accel, "couldn't translate accelerator key\n"); |
| 633 | return 0; |
| 634 | } |
| 635 | |
| 636 | /********************************************************************** |
| 637 | * TranslateAccelerator16 (USER.178) |
| 638 | */ |
| 639 | INT16 WINAPI TranslateAccelerator16(HWND16 hWnd, HACCEL16 hAccel, LPMSG16 msg) |
| 640 | { |
| 641 | LPACCEL16 lpAccelTbl = (LPACCEL16)LockResource16(hAccel); |
| 642 | int i; |
| 643 | MSG32 msg32; |
| 644 | |
| 645 | if (hAccel == 0 || msg == NULL || |
| 646 | (msg->message != WM_KEYDOWN && |
| 647 | msg->message != WM_KEYUP && |
| 648 | msg->message != WM_SYSKEYDOWN && |
| 649 | msg->message != WM_SYSKEYUP && |
| 650 | msg->message != WM_CHAR)) { |
| 651 | WARN(accel, "erraneous input parameters\n"); |
| 652 | SetLastError(ERROR_INVALID_PARAMETER); |
| 653 | return 0; |
| 654 | } |
| 655 | |
| 656 | TRACE(accel, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\ |
| 657 | msg->hwnd=%04x, msg->message=%04x\n", hAccel,hWnd,msg->hwnd,msg->message); |
| 658 | STRUCT32_MSG16to32(msg,&msg32); |
| 659 | |
| 660 | |
| 661 | i = 0; |
| 662 | do |
| 663 | { |
| 664 | if (KBD_translate_accelerator(hWnd,&msg32,lpAccelTbl[i].fVirt, |
| 665 | lpAccelTbl[i].key,lpAccelTbl[i].cmd)) |
| 666 | return 1; |
| 667 | } while ((lpAccelTbl[i++].fVirt & 0x80) == 0); |
| 668 | WARN(accel, "couldn't translate accelerator key\n"); |
| 669 | return 0; |
| 670 | } |
| 671 | |
| 672 | |
| 673 | /********************************************************************** |
| 674 | * VkKeyScanA (USER32.573) |
| 675 | */ |
| 676 | WORD WINAPI VkKeyScan32A(CHAR cChar) |
| 677 | { |
| 678 | return VkKeyScan16(cChar); |
| 679 | } |
| 680 | |
| 681 | /****************************************************************************** |
| 682 | * VkKeyScanW (USER32.576) |
| 683 | */ |
| 684 | WORD WINAPI VkKeyScan32W(WCHAR cChar) |
| 685 | { |
| 686 | return VkKeyScan32A((CHAR)cChar); /* FIXME: check unicode */ |
| 687 | } |
| 688 | |
| 689 | /****************************************************************************** |
| 690 | * GetKeyboardType32 (USER32.255) |
| 691 | */ |
| 692 | INT32 WINAPI GetKeyboardType32(INT32 nTypeFlag) |
| 693 | { |
| 694 | return GetKeyboardType16(nTypeFlag); |
| 695 | } |
| 696 | |
| 697 | /****************************************************************************** |
| 698 | * MapVirtualKey32A (USER32.383) |
| 699 | */ |
| 700 | UINT32 WINAPI MapVirtualKey32A(UINT32 code, UINT32 maptype) |
| 701 | { |
| 702 | return MapVirtualKey16(code,maptype); |
| 703 | } |
| 704 | |
| 705 | /****************************************************************************** |
| 706 | * MapVirtualKey32W (USER32.385) |
| 707 | */ |
| 708 | UINT32 WINAPI MapVirtualKey32W(UINT32 code, UINT32 maptype) |
| 709 | { |
| 710 | return MapVirtualKey16(code,maptype); |
| 711 | } |
| 712 | |
| 713 | /**************************************************************************** |
| 714 | * GetKBCodePage32 (USER32.246) |
| 715 | */ |
| 716 | UINT32 WINAPI GetKBCodePage32(void) |
| 717 | { |
| 718 | return GetKBCodePage16(); |
| 719 | } |
| 720 | |
| 721 | /**************************************************************************** |
Ulrich Weigand | 8bf078b | 1998-11-14 18:26:59 +0000 | [diff] [blame^] | 722 | * GetKeyboardLayoutName16 (USER.477) |
| 723 | */ |
| 724 | INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID) |
| 725 | { |
| 726 | return GetKeyboardLayoutName32A(pwszKLID); |
| 727 | } |
| 728 | |
| 729 | /**************************************************************************** |
Ulrich Weigand | 2b06758 | 1998-11-08 12:26:36 +0000 | [diff] [blame] | 730 | * GetKeyboardLayoutName32A (USER32.252) |
| 731 | */ |
| 732 | INT32 WINAPI GetKeyboardLayoutName32A(LPSTR pwszKLID) |
| 733 | { |
Ulrich Weigand | 8bf078b | 1998-11-14 18:26:59 +0000 | [diff] [blame^] | 734 | FIXME(keyboard,"always returns primary U.S. English layout\n"); |
| 735 | strcpy(pwszKLID,"00000409"); |
| 736 | return 1; |
Ulrich Weigand | 2b06758 | 1998-11-08 12:26:36 +0000 | [diff] [blame] | 737 | } |
| 738 | |
| 739 | /**************************************************************************** |
| 740 | * GetKeyboardLayoutName32W (USER32.253) |
| 741 | */ |
| 742 | INT32 WINAPI GetKeyboardLayoutName32W(LPWSTR pwszKLID) |
| 743 | { |
| 744 | LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, strlen("00000409")+1); |
| 745 | int res = GetKeyboardLayoutName32A(buf); |
| 746 | lstrcpyAtoW(pwszKLID,buf); |
| 747 | HeapFree( GetProcessHeap(), 0, buf ); |
| 748 | return res; |
| 749 | } |
| 750 | |
| 751 | /**************************************************************************** |
| 752 | * GetKeyNameText32A (USER32.247) |
| 753 | */ |
| 754 | INT32 WINAPI GetKeyNameText32A(LONG lParam, LPSTR lpBuffer, INT32 nSize) |
| 755 | { |
| 756 | return GetKeyNameText16(lParam,lpBuffer,nSize); |
| 757 | } |
| 758 | |
| 759 | /**************************************************************************** |
| 760 | * GetKeyNameText32W (USER32.248) |
| 761 | */ |
| 762 | INT32 WINAPI GetKeyNameText32W(LONG lParam, LPWSTR lpBuffer, INT32 nSize) |
| 763 | { |
| 764 | LPSTR buf = HEAP_xalloc( GetProcessHeap(), 0, nSize ); |
| 765 | int res = GetKeyNameText32A(lParam,buf,nSize); |
| 766 | |
| 767 | lstrcpynAtoW(lpBuffer,buf,nSize); |
| 768 | HeapFree( GetProcessHeap(), 0, buf ); |
| 769 | return res; |
| 770 | } |
| 771 | |
| 772 | /**************************************************************************** |
| 773 | * ToAscii32 (USER32.546) |
| 774 | */ |
| 775 | INT32 WINAPI ToAscii32( UINT32 virtKey,UINT32 scanCode,LPBYTE lpKeyState, |
| 776 | LPWORD lpChar,UINT32 flags ) |
| 777 | { |
| 778 | return ToAscii16(virtKey,scanCode,lpKeyState,lpChar,flags); |
| 779 | } |
| 780 | |
| 781 | /*********************************************************************** |
| 782 | * GetKeyboardLayout (USER32.250) |
| 783 | */ |
| 784 | HKL32 WINAPI GetKeyboardLayout(DWORD dwLayout) |
| 785 | { |
| 786 | HKL32 layout; |
| 787 | FIXME(keyboard,"(%ld): stub\n",dwLayout); |
| 788 | layout = (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */ |
| 789 | TRACE(keyboard,"returning %x\n",layout); |
| 790 | return layout; |
| 791 | } |
| 792 | |
| 793 | /*********************************************************************** |
| 794 | * GetKeyboardLayoutList (USER32.251) |
| 795 | * FIXME |
| 796 | */ |
| 797 | INT32 WINAPI GetKeyboardLayoutList(INT32 nBuff,HKL32 *layouts) |
| 798 | { |
| 799 | FIXME(keyboard,"(%d,%p): stub\n",nBuff,layouts); |
| 800 | if (layouts) |
| 801 | layouts[0] = GetKeyboardLayout(0); |
| 802 | return 1; |
| 803 | } |
| 804 | |
| 805 | |
| 806 | /*********************************************************************** |
| 807 | * RegisterHotKey (USER32.433) |
| 808 | */ |
| 809 | BOOL32 WINAPI RegisterHotKey(HWND32 hwnd,INT32 id,UINT32 modifiers,UINT32 vk) { |
| 810 | FIXME(keyboard,"(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk); |
| 811 | return TRUE; |
| 812 | } |
| 813 | |
| 814 | /*********************************************************************** |
| 815 | * UnregisterHotKey (USER32.565) |
| 816 | */ |
| 817 | BOOL32 WINAPI UnregisterHotKey(HWND32 hwnd,INT32 id) { |
| 818 | FIXME(keyboard,"(0x%08x,%d): stub\n",hwnd,id); |
| 819 | return TRUE; |
| 820 | } |
| 821 | |