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

Last change on this file since 9230 was 9230, checked in by sandervl, 23 years ago

Translate PM WM_VSCROLL to WM_MOUSEWHEEL messages

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