source: trunk/src/user32/oslibmsgtranslate.cpp@ 7213

Last change on this file since 7213 was 7213, checked in by phaller, 24 years ago

fixed right shift

File size: 36.3 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.71 2001-10-26 10:11:50 phaller Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Daniela Engert (dani@ngrt.de)
8 * Copyright 1999 Rene Pronk (R.Pronk@twi.tudelft.nl)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 * TODO: Extra msgs: which messages must be put into the queue and which can be sent directly?
13 * (According to the docs TranslateMessage really inserts a msg in the queue)
14 * TODO: Filter translation isn't correct for posted messages
15 *
16 */
17#define INCL_WIN
18#define INCL_PM
19#define INCL_DOSPROCESS
20#include <os2wrap.h>
21#include <string.h>
22#include <misc.h>
23#include <winconst.h>
24#include <win32api.h>
25#include "oslibmsg.h"
26#include <winuser32.h>
27#include "win32wdesktop.h"
28#include "oslibutil.h"
29#include "timer.h"
30#include <thread.h>
31#include <wprocess.h>
32#include "pmwindow.h"
33#include "oslibwin.h"
34#include "winmouse.h"
35#include <pmkbdhk.h>
36#include <pmscan.h>
37#include <winscan.h>
38#include <winkeyboard.h>
39
40#define DBG_LOCALLOG DBG_oslibmsgtranslate
41#include "dbglocal.h"
42
43
44static BOOL fGenerateDoubleClick = FALSE;
45static MSG doubleClickMsg = {0};
46
47
48// Note:
49// For a "lonekey"-press of AltGr, we only receive WM_KEYUP
50// messages. If the key is pressed longer and starts to repeat,
51// WM_KEYDOWN messages come in properly.
52static BOOL fKeyAltGrDown = FALSE;
53
54//******************************************************************************
55//******************************************************************************
56BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
57{
58 // check if the single slot is occupied already
59 if (teb->o.odin.fTranslated == TRUE)
60 // there's still an already translated message to be processed
61 return FALSE;
62
63 teb->o.odin.fTranslated = TRUE;
64 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
65 return TRUE;
66}
67
68//******************************************************************************
69//******************************************************************************
70ULONG GetMouseKeyState()
71{
72 ULONG keystate = 0;
73
74 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
75 keystate |= MK_LBUTTON_W;
76 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
77 keystate |= MK_RBUTTON_W;
78 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
79 keystate |= MK_MBUTTON_W;
80 if(WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000)
81 keystate |= MK_SHIFT_W;
82 if(WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
83 keystate |= MK_CONTROL_W;
84
85 return keystate;
86}
87//******************************************************************************
88//******************************************************************************
89LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
90{
91 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
92}
93//******************************************************************************
94//******************************************************************************
95void SetMenuDoubleClick(BOOL fSet)
96{
97 fGenerateDoubleClick = fSet;
98}
99//******************************************************************************
100//******************************************************************************
101BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
102{
103 Win32BaseWindow *win32wnd = 0;
104 OSLIBPOINT point, ClientPoint;
105 POSTMSG_PACKET *packet;
106 TEB *teb = (TEB *)pTeb;
107 BOOL fWasDisabled = FALSE;
108 BOOL fIsFrame = FALSE;
109 int i;
110
111 memset(winMsg, 0, sizeof(MSG));
112 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
113 if(!win32wnd) {
114 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
115 if(win32wnd) {
116 fIsFrame = TRUE;
117 }
118 }
119
120 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
121 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
122 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
123 {
124 goto dummymessage; //not a win32 client window
125 }
126 winMsg->time = os2Msg->time;
127 //CB: PM bug or undocumented feature? ptl.x highword is set!
128 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
129 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
130
131 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
132 winMsg->hwnd = win32wnd->getWindowHandle();
133
134 if(os2Msg->msg >= WIN32APP_POSTMSG) {
135 packet = (POSTMSG_PACKET *)os2Msg->mp2;
136 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
137 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
138 winMsg->wParam = packet->wParam;
139 winMsg->lParam = packet->lParam;
140 if(fMsgRemoved == MSG_REMOVE) free(packet); //free the shared memory here
141 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
142 return TRUE;
143 }
144 else {//broadcasted message (no packet present)
145 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
146 winMsg->wParam = (UINT)os2Msg->mp1;
147 winMsg->lParam = (DWORD)os2Msg->mp2;
148 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
149 return TRUE;
150 }
151 goto dummymessage;
152 }
153
154 switch(os2Msg->msg)
155 {
156 //OS/2 msgs
157 case WM_CREATE:
158 {
159 if(teb->o.odin.newWindow == 0) {
160 DebugInt3();
161 goto dummymessage;
162 }
163
164 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
165 win32wnd->addRef();
166
167 winMsg->message = WINWM_CREATE;
168 winMsg->hwnd = win32wnd->getWindowHandle();
169 winMsg->wParam = 0;
170 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
171 break;
172 }
173
174 case WM_QUIT:
175 winMsg->message = WINWM_QUIT;
176 break;
177
178 case WM_CLOSE:
179 winMsg->message = WINWM_CLOSE;
180 break;
181
182 case WM_DESTROY:
183 winMsg->message = WINWM_DESTROY;
184 break;
185
186 case WM_ENABLE:
187 winMsg->message = WINWM_ENABLE;
188 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
189 break;
190
191 case WM_SHOW:
192 winMsg->message = WINWM_SHOWWINDOW;
193 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
194 break;
195
196 case WM_WINDOWPOSCHANGED:
197 {
198 PSWP pswp = (PSWP)os2Msg->mp1;
199 SWP swpOld = *(pswp + 1);
200 HWND hParent = NULLHANDLE;
201 LONG yDelta = pswp->cy - swpOld.cy;
202 LONG xDelta = pswp->cx - swpOld.cx;
203
204 if(!fIsFrame) goto dummymessage;
205
206 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
207
208 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
209 if (win32wnd->isChild()) {
210 if(win32wnd->getParent()) {
211 hParent = win32wnd->getParent()->getOS2WindowHandle();
212 }
213 else goto dummymessage; //parent has just been destroyed
214 }
215 }
216 if(win32wnd->getParent()) {
217 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
218 win32wnd->getOS2WindowHandle());
219 }
220 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
221
222 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
223
224 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
225 {
226 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
227 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
228 {
229 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
230 if(wndAfter) {
231 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
232 RELEASE_WNDOBJ(wndAfter);
233 }
234 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
235 }
236 }
237 winMsg->message = WINWM_WINDOWPOSCHANGED;
238 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
239 break;
240 }
241
242 case WM_ACTIVATE:
243 {
244 HWND hwndActivate = (HWND)os2Msg->mp2;
245 BOOL fMinimized = FALSE;
246
247 hwndActivate = OS2ToWin32Handle(hwndActivate);
248 if(hwndActivate == 0) {
249 //another (non-win32) application's window
250 //set to desktop window handle
251 hwndActivate = windowDesktop->getWindowHandle();
252 }
253
254 if(win32wnd->getStyle() & WS_MINIMIZE_W)
255 {
256 fMinimized = TRUE;
257 }
258
259 winMsg->message = WINWM_ACTIVATE;
260 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
261 winMsg->lParam = (LPARAM)hwndActivate;
262 break;
263 }
264
265 case WM_SETFOCUS:
266 {
267 HWND hwndFocus = (HWND)os2Msg->mp1;
268
269 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
270 //another (non-win32) application's window
271 //set to NULL (allowed according to win32 SDK) to avoid problems
272 hwndFocus = NULL;
273 }
274 else hwndFocus = OS2ToWin32Handle(hwndFocus);
275
276 if((ULONG)os2Msg->mp2 == TRUE) {
277 winMsg->message = WINWM_SETFOCUS;
278 winMsg->wParam = (WPARAM)hwndFocus;
279 }
280 else {
281 winMsg->message = WINWM_KILLFOCUS;
282 winMsg->wParam = (WPARAM)hwndFocus;
283 }
284 break;
285 }
286
287 //**************************************************************************
288 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
289 //**************************************************************************
290 case WM_BUTTON1DOWN:
291 case WM_BUTTON1UP:
292 case WM_BUTTON1DBLCLK:
293 case WM_BUTTON2DOWN:
294 case WM_BUTTON2UP:
295 case WM_BUTTON2DBLCLK:
296 case WM_BUTTON3DOWN:
297 case WM_BUTTON3UP:
298 case WM_BUTTON3DBLCLK:
299 {
300 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
301
302 dprintf(("MsgButton %x (%x) %d at (%d,%d) time %x", winMsg->hwnd, os2Msg->hwnd, WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN), winMsg->pt.x, winMsg->pt.y, winMsg->time));
303
304 HWND hwnd;
305
306 DisableLogging();
307 if(GetCapture() != winMsg->hwnd)
308 {
309 hwnd = WindowFromPoint(winMsg->pt);
310 if(win32wnd->getWindowHandle() != hwnd) {
311 RELEASE_WNDOBJ(win32wnd);
312 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
313 if(win32wnd == NULL) {
314 DebugInt3();
315 EnableLogging();
316 goto dummymessage;
317 }
318 winMsg->hwnd = hwnd;
319 }
320 }
321
322 //if a window is disabled, it's parent receives the mouse messages
323 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
324 if(win32wnd->getParent()) {
325 Win32BaseWindow *parent = win32wnd->getParent();;
326 if(parent) parent->addRef();
327 RELEASE_WNDOBJ(win32wnd);
328 win32wnd = parent;
329 }
330 fWasDisabled = TRUE;
331 }
332
333 if(IsNCMouseMsg(win32wnd)) {
334 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
335 winMsg->wParam = win32wnd->getLastHitTestVal();
336 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
337 }
338 else {
339 ClientPoint.x = winMsg->pt.x;
340 ClientPoint.y = winMsg->pt.y;
341 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
342 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
343 winMsg->wParam = GetMouseKeyState();
344 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
345 }
346 EnableLogging();
347 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
348 {
349 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
350 goto dummymessage; //dinput swallowed message
351 }
352 }
353
354 if(fWasDisabled) {
355 if(win32wnd) {
356 winMsg->hwnd = win32wnd->getWindowHandle();
357 }
358 else goto dummymessage; //don't send mouse messages to disabled windows
359 }
360
361 DisableLogging();
362 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
363 (winMsg->message == WINWM_RBUTTONDOWN) ||
364 (winMsg->message == WINWM_MBUTTONDOWN) ||
365 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
366 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
367 (winMsg->message == WINWM_NCMBUTTONDOWN))
368 {
369 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
370 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
371 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
372 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
373 {
374 dprintf(("single -> double click"));
375 if(winMsg->message >= WINWM_LBUTTONDOWN) {
376 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
377 }
378 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
379 doubleClickMsg.message = 0;
380 }
381 else {
382 dprintf(("save for double click"));
383 doubleClickMsg = *winMsg;
384 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
385 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
386 }
387 }
388 }
389 EnableLogging();
390
391 break;
392 }
393
394 case WM_BUTTON2CLICK:
395 case WM_BUTTON1CLICK:
396 case WM_BUTTON3CLICK:
397 goto dummymessage;
398
399 case WM_BUTTON2MOTIONSTART:
400 case WM_BUTTON2MOTIONEND:
401 case WM_BUTTON1MOTIONSTART:
402 case WM_BUTTON1MOTIONEND:
403 case WM_BUTTON3MOTIONSTART:
404 case WM_BUTTON3MOTIONEND:
405 //no break; translate to WM_MOUSEMOVE
406 //Some applications (e.g. Unreal) retrieve all mouse messages
407 //when a mouse button is pressed and don't expect WM_NULL
408
409 case WM_MOUSEMOVE:
410 {
411 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
412
413 HWND hwnd;
414
415 dprintf2(("WM_NCMOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
416 DisableLogging();
417 if(GetCapture() != winMsg->hwnd)
418 {
419 hwnd = WindowFromPoint(winMsg->pt);
420 if(win32wnd->getWindowHandle() != hwnd) {
421 RELEASE_WNDOBJ(win32wnd);
422 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
423 if(win32wnd == NULL) {
424 DebugInt3();
425 EnableLogging();
426 goto dummymessage;
427 }
428 winMsg->hwnd = hwnd;
429 }
430 }
431
432 //if a window is disabled, it's parent receives the mouse messages
433 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
434 if(win32wnd->getParent()) {
435 Win32BaseWindow *parent = win32wnd->getParent();;
436 if(parent) parent->addRef();
437 RELEASE_WNDOBJ(win32wnd);
438 win32wnd = parent;
439 }
440 fWasDisabled = TRUE;
441 }
442 if(IsNCMouseMsg(win32wnd))
443 {
444 winMsg->message = WINWM_NCMOUSEMOVE;
445 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
446 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
447 }
448 else
449 {
450 ClientPoint.x = winMsg->pt.x;
451 ClientPoint.y = winMsg->pt.y;
452 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
453
454 winMsg->message = WINWM_MOUSEMOVE;
455 winMsg->wParam = GetMouseKeyState();
456 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
457 }
458 EnableLogging();
459 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
460 {
461 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
462 goto dummymessage; //dinput swallowed message
463 }
464 }
465 if(fWasDisabled) {
466 if(win32wnd) {
467 winMsg->hwnd = win32wnd->getWindowHandle();
468 }
469 else {
470 goto dummymessage; //don't send mouse messages to disabled windows
471 }
472 }
473 //OS/2 Window coordinates -> Win32 Window coordinates
474 break;
475 }
476
477 case WM_CONTROL:
478 goto dummymessage;
479
480 case WM_COMMAND:
481 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
482 winMsg->message = WINWM_COMMAND;
483 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
484 break;
485 }
486 //todo controls
487 goto dummymessage;
488
489 case WM_SYSCOMMAND:
490 {
491 ULONG x = 0, y = 0;
492 ULONG win32sc;
493
494 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
495 POINTL pointl;
496 WinQueryPointerPos(HWND_DESKTOP, &pointl);
497 x = pointl.x;
498 y = mapScreenY(y);
499 }
500 switch(SHORT1FROMMP(os2Msg->mp1)) {
501 case SC_MOVE:
502 win32sc = SC_MOVE_W;
503 break;
504 case SC_CLOSE:
505 {
506 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
507 //TRUE -> user clicked on close button -> close window
508 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
509 {
510 HWND hwnd = win32wnd->GetTopParent();
511 if(win32wnd->getWindowHandle() != hwnd) {
512 RELEASE_WNDOBJ(win32wnd);
513 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
514 if(win32wnd == NULL) {
515 DebugInt3();
516 goto dummymessage;
517 }
518 winMsg->hwnd = hwnd;
519 }
520 }
521 win32sc = SC_CLOSE_W;
522 break;
523 }
524 case SC_MAXIMIZE:
525 win32sc = SC_MAXIMIZE_W;
526 break;
527 case SC_MINIMIZE:
528 win32sc = SC_MINIMIZE_W;
529 break;
530 case SC_NEXTFRAME:
531 case SC_NEXTWINDOW:
532 win32sc = SC_NEXTWINDOW_W;
533 break;
534 case SC_RESTORE:
535 win32sc = SC_RESTORE_W;
536 break;
537 case SC_TASKMANAGER:
538 win32sc = SC_TASKLIST_W;
539 break;
540 default:
541 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
542 goto dummymessage;
543 }
544 winMsg->message= WINWM_SYSCOMMAND;
545 winMsg->wParam = (WPARAM)win32sc;
546 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
547 break;
548 }
549
550 case WM_CHAR_SPECIAL:
551 {
552 // @@@PH
553 // special char message from the keyboard hook
554 dprintf(("PM: WM_CHAR_SPECIAL\n"));
555
556 // NO BREAK! FALLTHRU CASE!
557 }
558
559 case WM_CHAR:
560 {
561 ULONG repeatCount=0, virtualKey=0, keyFlags=0, scanCode=0;
562 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
563 BOOL keyWasPressed, isExtended = FALSE;
564 char c;
565
566 teb->o.odin.fTranslated = FALSE;
567 repeatCount = CHAR3FROMMP(os2Msg->mp1);
568 scanCode = CHAR4FROMMP(os2Msg->mp1);
569 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
570
571 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode));
572 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
573
574 // vitali add begin
575 if ( ( SHORT1FROMMP(os2Msg->mp2) & 0x0FF ) == 0x0E0 )
576 {
577 // an extended key ( arrows, ins, del and so on )
578 // get "virtual" scancode from character code because
579 // for "regular" keys they are equal
580 if(!(flags & (KC_SHIFT|KC_ALT|KC_CTRL))) {
581 scanCode = ( SHORT1FROMMP(os2Msg->mp2) >> 8) & 0x0FF;
582 }
583 isExtended = TRUE;
584 }
585 // vitali add end
586
587 // both WM_KEYUP & WM_KEYDOWN want a virtual key, find the right Win32 virtual key
588 // given the OS/2 virtual key and OS/2 character
589
590 //if (((SHORT1FROMMP (mp1) & KC_CHAR) == KC_CHAR) ||
591 // ((SHORT1FROMMP (mp1) & KC_LONEKEY) == KC_LONEKEY))
592 c = 0;
593 if ((SHORT1FROMMP (os2Msg->mp1) & 0xFF) != 0)
594 {
595 c = SHORT1FROMMP (os2Msg->mp2);
596 if ((c >= 'A') && (c <= 'Z')) {
597 virtualKey = c;
598 goto VirtualKeyFound;
599 }
600 if ((c >='a') && (c <= 'z')) {
601 virtualKey = c - 32; // make it uppercase
602 goto VirtualKeyFound;
603 }
604 if ((c >= '0') && (c <= '9')) {
605 virtualKey = c;
606 goto VirtualKeyFound;
607 }
608 }
609
610VirtualKeyFound:
611// dprintf (("VIRTUALKEYFOUND:(%x)", virtualKey));
612
613 // @@@PH: what's this supposed to be?
614 // Adjust PM scancodes for Win* keys
615 if (scanCode >= 0x70)
616 scanCode -= 0x10;
617
618 // winMsg->wParam = pmscan2winkey[scanCode][0];
619 // wWinScan = pmscan2winkey[scanCode][1];
620 {
621 BOOL fWinExtended;
622 BYTE bWinVKey;
623 WORD wWinScan;
624
625 // Note: Numlock-state currently ignored, see below
626 KeyTranslatePMScanToWinVKey(scanCode,
627 FALSE,
628 &bWinVKey,
629 &wWinScan,
630 &fWinExtended);
631 winMsg->wParam = bWinVKey;
632 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
633 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
634
635 // Set the extended bit when appropriate
636 if (fWinExtended)
637 winMsg->lParam = winMsg->lParam | (1<<24);
638 }
639
640 // Adjust VKEY value for pad digits if NumLock is on
641 if ((scanCode >= 0x47) && (scanCode <= 0x53) &&
642 (virtualKey >= 0x30) && (virtualKey >= 39))
643 winMsg->wParam = virtualKey + 0x30;
644
645
646 if (!(flags & KC_ALT))
647 {
648 //
649 // the Alt key is not pressed
650 // or no more pressed
651 //
652 if (flags & KC_KEYUP)
653 {
654 // check for a lonesome ALT key ...
655 if ( (flags & KC_LONEKEY) &&
656 (winMsg->wParam == VK_LMENU_W) )
657 {
658 winMsg->message = WINWM_SYSKEYUP;
659
660 // held ALT-key when current key is released
661 // generates additional flag 0x2000000
662 // Note: PM seems to do this differently,
663 // KC_ALT is already reset
664 }
665 else
666 {
667 // send WM_KEYUP message
668 winMsg->message = WINWM_KEYUP;
669 }
670
671 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
672 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
673 }
674 else
675 {
676 // send WM_KEYDOWN message
677 winMsg->message = WINWM_KEYDOWN;
678 if (keyWasPressed)
679 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
680 }
681 }
682 else
683 {
684 //
685 // the Alt key is pressed
686 //
687 if (flags & KC_KEYUP)
688 {
689 // send WM_SYSKEYUP message
690 winMsg->message = WINWM_SYSKEYUP;
691 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
692 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
693 }
694 else
695 {
696 // send WM_SYSKEYDOWN message
697 winMsg->message = WINWM_SYSKEYDOWN;
698 if (keyWasPressed)
699 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
700
701 // pressed ALT-key generates additional flag 0x2000000
702 // if the current window has keyboard focus
703 winMsg->lParam |= 1 << 29;
704 }
705 }
706
707 // ------------------------------------------------
708 // check if additional messages have to be recorded
709 // ------------------------------------------------
710#if 0
711 {
712 MSG extramsg;
713 extramsg.hwnd = winMsg->hwnd;
714 extramsg.time = winMsg->time;
715 extramsg.pt = winMsg->pt;
716
717 switch (scanCode)
718 {
719 case PMSCAN_PRINT:
720 // Note: PRINT generates a WM_KEYUP under Windows
721 // also only call the standard kbd hook for the WM_KEYUP msg,
722 // the low-level hook is called twice
723 // mb->putWinMsg(hwndWin32, WM_CHAR, VK_PRINT_W, ... )
724 // WM_CHAR(0x0000002ch, c1370001h)
725 extramsg.message = WINWM_KEYUP;
726 extramsg.wParam = VK_PRINT_W;
727 extramsg.lParam = winMsg->lParam;
728 setThreadQueueExtraCharMessage(teb, &extramsg);
729 break;
730
731 #define WIN_KEY_EXTENDED 0x01000000
732 #define WIN_KEY_DONTCARE 0x02000000
733 #define WIN_KEY_ALTHELD 0x20000000
734 #define WIN_KEY_PREVSTATE 0x40000000
735 case PMSCAN_ALTRIGHT:
736 {
737 // we need very special treatment here for the
738 // poor, crippled AltGr key
739 // Note: see fKeyAltGrDown above!
740
741 if ( (keyWasPressed) || (fKeyAltGrDown == FALSE) )
742 {
743 fKeyAltGrDown = TRUE;
744
745 // 1 - generate a virtual LCONTROL-keypress
746 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-AltGr!)
747 // 0xfe000000: mask out extended-key, scancode, repeatcount
748 // Note: Win sends a WINWM_SYSKEYDOWN to the hooks,
749 // the queue gets a WM_KEYDOWN only! (wrong impl. here)
750 extramsg.message = WINWM_KEYDOWN;
751 extramsg.wParam = VK_RMENU_W;
752 extramsg.lParam = (winMsg->lParam & 0xfe000000)
753 | WIN_KEY_EXTENDED
754 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
755 | WIN_KEY_ALTHELD
756 | repeatCount
757 | (WINSCAN_ALTRIGHT << 16);
758 winMsg->message = WINWM_KEYDOWN;
759 winMsg->wParam = VK_LCONTROL_W;
760 winMsg->lParam = (winMsg->lParam & 0xfe000000)
761 | WIN_KEY_DONTCARE
762 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
763 | WIN_KEY_ALTHELD
764 | repeatCount
765 | (WINSCAN_CTRLLEFT << 16);
766 }
767 else
768 {
769 // OK, now we can release it!
770 fKeyAltGrDown = FALSE;
771
772 // key up
773 // 1 - generate a virtual LCONTROL-keypress
774 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-Alt!)
775 extramsg.message = WINWM_KEYUP;
776 extramsg.wParam = VK_RMENU_W;
777 extramsg.lParam = (winMsg->lParam & 0xfe000000)
778 | WIN_KEY_EXTENDED
779 | repeatCount
780 | (WINSCAN_ALTRIGHT << 16);
781 winMsg->message = WINWM_SYSKEYUP;
782 winMsg->wParam = VK_LCONTROL_W;
783 winMsg->lParam = (winMsg->lParam & 0xfe000000)
784 | WIN_KEY_ALTHELD
785 | repeatCount
786 | (WINSCAN_CTRLLEFT << 16);
787 }
788
789 // @@@PH
790 // unknown: this leads to an infinite loop
791 // because the OS/2 WM_CHAR_SPECIAL message is never
792 // removed from the queue?!
793 setThreadQueueExtraCharMessage(teb, &extramsg);
794
795 if ( (keyWasPressed) || (fKeyAltGrDown == FALSE) )
796 {
797 fKeyAltGrDown = TRUE;
798
799 // 1 - generate a virtual LCONTROL-keypress
800 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-AltGr!)
801 // 0xfe000000: mask out extended-key, scancode, repeatcount
802 // Note: Win sends a WINWM_SYSKEYDOWN to the hooks,
803 // the queue gets a WM_KEYDOWN only! (wrong impl. here)
804 winMsg->message = WINWM_KEYDOWN;
805 winMsg->wParam = VK_RMENU_W;
806 winMsg->lParam = (winMsg->lParam & 0xfe000000)
807 | WIN_KEY_EXTENDED
808 | (keyWasPressed ? WIN_KEY_PREVSTATE : 0)
809 | WIN_KEY_ALTHELD
810 | repeatCount
811 | (WINSCAN_ALTRIGHT << 16);
812 }
813 else
814 {
815 // OK, now we can release it!
816 fKeyAltGrDown = FALSE;
817
818 // key up
819 // 1 - generate a virtual LCONTROL-keypress
820 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-Alt!)
821 winMsg->message = WINWM_KEYUP;
822 winMsg->wParam = VK_RMENU_W;
823 winMsg->lParam = (winMsg->lParam & 0xfe000000)
824 | WIN_KEY_EXTENDED
825 | repeatCount
826 | (WINSCAN_ALTRIGHT << 16);
827 }
828 }
829 break;
830 } /* switch */
831 }
832#endif
833
834 if (ISKDB_CAPTURED())
835 {
836 if (DInputKeyBoardHandler(winMsg)) {
837 goto dummymessage; //dinput swallowed message
838 }
839 }
840 break;
841 }
842
843 case WM_TIMER:
844//Why was this check here????
845// if (os2Msg->mp2)
846// {
847 BOOL sys;
848 ULONG id;
849
850 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id))
851 {
852 winMsg->wParam = (WPARAM)id;
853 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
854 break;
855 }
856// }
857 goto dummymessage; //for caret blinking
858
859 case WM_SETWINDOWPARAMS:
860 {
861 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
862
863 if(wndParams->fsStatus & WPM_TEXT) {
864 winMsg->message = WINWM_SETTEXT;
865 winMsg->lParam = (LPARAM)wndParams->pszText;
866 break;
867 }
868 goto dummymessage;
869 }
870
871#if 0
872 case WM_QUERYWINDOWPARAMS:
873 {
874 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
875 ULONG textlen;
876 PSZ wintext;
877
878 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
879 {
880 if(wndpars->fsStatus & WPM_CCHTEXT)
881 wndpars->cchText = win32wnd->MsgGetTextLength();
882 if(wndpars->fsStatus & WPM_TEXT)
883 wndpars->pszText = win32wnd->MsgGetText();
884
885 wndpars->fsStatus = 0;
886 wndpars->cbCtlData = 0;
887 wndpars->cbPresParams = 0;
888 goto dummymessage;
889 }
890 }
891#endif
892
893 case WM_PAINT:
894 {
895 if(win32wnd->IsWindowIconic()) {
896 winMsg->message = WINWM_PAINTICON;
897 }
898 else winMsg->message = WINWM_PAINT;
899 break;
900 }
901
902 case WM_CONTEXTMENU:
903 winMsg->message = WINWM_CONTEXTMENU;
904 winMsg->wParam = win32wnd->getWindowHandle();
905 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
906 break;
907
908 case WM_RENDERFMT:
909 winMsg->message = WINWM_RENDERFORMAT;
910 winMsg->wParam = (UINT) os2Msg->mp1;
911 break;
912
913 case WM_RENDERALLFMTS:
914 winMsg->message = WINWM_RENDERALLFORMATS;
915 break;
916
917 case WM_DESTROYCLIPBOARD:
918 winMsg->message = WINWM_DESTROYCLIPBOARD;
919 break;
920
921 case WM_HSCROLL:
922 case WM_VSCROLL:
923 winMsg->message = (os2Msg->msg == WM_HSCROLL) ? WINWM_HSCROLL : WINWM_VSCROLL;
924 winMsg->lParam = 0;
925 winMsg->wParam = 0;
926 switch(SHORT2FROMMP(os2Msg->mp2)) {
927 case SB_LINERIGHT:
928 winMsg->wParam = SB_LINERIGHT_W;
929 break;
930 case SB_LINELEFT:
931 winMsg->wParam = SB_LINELEFT_W;
932 break;
933 case SB_PAGELEFT:
934 winMsg->wParam = SB_PAGELEFT_W;
935 break;
936 case SB_PAGERIGHT:
937 winMsg->wParam = SB_PAGERIGHT_W;
938 break;
939 default:
940 dprintf(("Unsupported WM_H/VSCROLL message %x!!", SHORT2FROMMP(os2Msg->mp2)));
941 goto dummymessage;
942 }
943 break;
944
945 case WM_INITMENU:
946 case WM_MENUSELECT:
947 case WM_MENUEND:
948 case WM_NEXTMENU:
949 case WM_SYSCOLORCHANGE:
950 case WM_SYSVALUECHANGED:
951 case WM_SETSELECTION:
952 case WM_PPAINT:
953 case WM_PSETFOCUS:
954 case WM_PSYSCOLORCHANGE:
955 case WM_PSIZE:
956 case WM_PACTIVATE:
957 case WM_PCONTROL:
958 case WM_HELP:
959 case WM_APPTERMINATENOTIFY:
960 case WM_PRESPARAMCHANGED:
961 case WM_DRAWITEM:
962 case WM_MEASUREITEM:
963 case WM_CONTROLPOINTER:
964 case WM_QUERYDLGCODE:
965 case WM_SUBSTITUTESTRING:
966 case WM_MATCHMNEMONIC:
967 case WM_SAVEAPPLICATION:
968 case WM_SEMANTICEVENT:
969 default:
970dummymessage:
971 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
972 winMsg->message = 0;
973 winMsg->wParam = 0;
974 winMsg->lParam = 0;
975 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
976 return FALSE;
977 }
978 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
979 return TRUE;
980}
981//******************************************************************************
982//******************************************************************************
983BOOL OSLibWinTranslateMessage(MSG *msg)
984{
985 TEB *teb;
986
987 teb = GetThreadTEB();
988 if(!teb) {
989 return FALSE;
990 }
991 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
992 // the newly generated WM_CHAR message.
993 if(!teb->o.odin.fTranslated && teb->o.odin.os2msg.msg == WM_CHAR && !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
994 {
995 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
996 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
997 MSG extramsg;
998
999 memcpy(&extramsg, msg, sizeof(MSG));
1000 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1001 extramsg.lParam = 0;
1002
1003 // ESCAPE generates a WM_CHAR under windows, so take
1004 // special care for this here.
1005 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1006 switch (ucPMScanCode)
1007 {
1008 case PMSCAN_ESC:
1009 extramsg.wParam = VK_ESCAPE_W;
1010 fl |= KC_CHAR;
1011 break;
1012 }
1013
1014 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1015 {
1016 return FALSE;
1017 }
1018
1019 if(fl & KC_VIRTUALKEY)
1020 {
1021 if(msg->wParam)
1022 {
1023 if ((msg->wParam >= VK_NUMPAD0_W) &&
1024 (msg->wParam <= VK_NUMPAD9_W))
1025 extramsg.wParam = msg->wParam - 0x30;
1026 else
1027 extramsg.wParam = msg->wParam;
1028 }
1029 else
1030 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1031 }
1032
1033
1034 if(msg->message >= WINWM_SYSKEYDOWN)
1035 extramsg.message = WINWM_SYSCHAR;
1036 else
1037 extramsg.message = WINWM_CHAR;
1038
1039 if(fl & KC_DEADKEY)
1040 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1041
1042
1043 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1044 if(fl & KC_ALT)
1045 extramsg.lParam |= (1<<29);
1046 if(fl & KC_PREVDOWN)
1047 extramsg.lParam |= (1<<30);
1048 if(fl & KC_KEYUP)
1049 extramsg.lParam |= (1<<31);
1050
1051 // insert message into the queue
1052 setThreadQueueExtraCharMessage(teb, &extramsg);
1053 return TRUE;
1054 }
1055 return FALSE;
1056}
1057//******************************************************************************
1058//******************************************************************************
1059
Note: See TracBrowser for help on using the repository browser.