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

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

Merged Rewind menu control

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