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

Last change on this file since 7837 was 7837, checked in by sandervl, 24 years ago

PF: fix for Shift-Enter + Alt-Enter

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