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

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

double click fix + double click on system menu now works

File size: 34.5 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.66 2001-10-24 15:41: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
38#define DBG_LOCALLOG DBG_oslibmsgtranslate
39#include "dbglocal.h"
40
41// Formerly used method of translation based on OS/2 VKEY value didn't work
42// right. We need to take a look at the scan code we get from PM and derive
43// the Win32 VKEY and scancode from that because sometimes even the scancode
44// used in Win32 is different from the PM scancode!
45// The format is:
46// Win VKEY, Win scancode, (PM scancode) (key description)
47USHORT pmscan2winkey [][2] = {
48 0, 0, // 0x00
49 0x1B, 0x01, // 0x01 Esc
50 0x31, 0x02, // 0x02 1
51 0x32, 0x03, // 0x03 2
52 0x33, 0x04, // 0x04 3
53 0x34, 0x05, // 0x05 4
54 0x35, 0x06, // 0x06 5
55 0x36, 0x07, // 0x07 6
56 0x37, 0x08, // 0x08 7
57 0x38, 0x09, // 0x09 8
58 0x39, 0x0A, // 0x0A 9
59 0x30, 0x0B, // 0x0B 0
60 0xBD, 0x0C, // 0x0C -
61 0xBB, 0x0D, // 0x0D =
62 0x08, 0x0E, // 0x0E Bksp
63 0x09, 0x0F, // 0x0F Tab
64 0x51, 0x10, // 0x10 q
65 0x57, 0x11, // 0x11 w
66 0x45, 0x12, // 0x12 e
67 0x52, 0x13, // 0x13 r
68 0x54, 0x14, // 0x14 t
69 0x59, 0x15, // 0x15 y
70 0x55, 0x16, // 0x16 u
71 0x49, 0x17, // 0x17 i
72 0x4F, 0x18, // 0x18 o
73 0x50, 0x19, // 0x19 p
74 0xDB, 0x1A, // 0x1A [
75 0xDD, 0x1B, // 0x1B ]
76 0x0D, 0x1C, // 0x1C Enter
77 0x11, 0x1D, // 0x1D LCtrl
78 0x41, 0x1E, // 0x1E a
79 0x53, 0x1F, // 0x1F s
80 0x44, 0x20, // 0x20 d
81 0x46, 0x21, // 0x21 f
82 0x47, 0x22, // 0x22 g
83 0x48, 0x23, // 0x23 h
84 0x4A, 0x24, // 0x24 j
85 0x4B, 0x25, // 0x25 k
86 0x4C, 0x26, // 0x26 l
87 0xBA, 0x27, // 0x27 ;
88 0xDE, 0x28, // 0x28 '
89 0xC0, 0x29, // 0x29 `
90 0x10, 0x2A, // 0x2A LShift
91 0xDC, 0x2B, // 0x2B Bkslsh
92 0x5A, 0x2C, // 0x2C z
93 0x58, 0x2D, // 0x2D x
94 0x43, 0x2E, // 0x2E c
95 0x56, 0x2F, // 0x2F v
96 0x42, 0x30, // 0x30 b
97 0x4E, 0x31, // 0x31 n
98 0x4D, 0x32, // 0x32 m
99 0xBC, 0x33, // 0x33 ,
100 0xBE, 0x34, // 0x34 .
101 0xBF, 0x35, // 0x35 /
102 0x10, 0x36, // 0x36 RShift
103 0x6A, 0x37, // 0x37 * Pad
104// 0x12, 0x38, // 0x38 LAlt
105 VK_LMENU_W, 0x38, // 0x38 LAlt
106 0x20, 0x39, // 0x39 Space
107 0x14, 0x3A, // 0x3A CapsLk
108 0x70, 0x3B, // 0x3B F1
109 0x71, 0x3C, // 0x3C F2
110 0x72, 0x3D, // 0x3D F3
111 0x73, 0x3E, // 0x3E F4
112 0x74, 0x3F, // 0x3F F5
113 0x75, 0x40, // 0x40 F6
114 0x76, 0x41, // 0x41 F7
115 0x77, 0x42, // 0x42 F8
116 0x78, 0x43, // 0x43 F9
117 0x79, 0x44, // 0x44 F10 (?)
118 0x90, 0x145, // 0x45 NumLk
119 0x91, 0x46, // 0x46 ScrLk
120 0x24, 0x47, // 0x47 7 Pad
121 0x26, 0x48, // 0x48 8 Pad
122 0x21, 0x49, // 0x49 9 Pad
123 0x6D, 0x4A, // 0x4A - Pad
124 VK_LEFT_W, 0x4B, // 0x4B Left Arrow (depends on NumLock State)
125 0x0C, 0x4C, // 0x4C 5 Pad
126 0x27, 0x4D, // 0x4D 6 Pad
127 0x6B, 0x4E, // 0x4E + Pad
128 0x23, 0x4F, // 0x4F 1 Pad
129 0x28, 0x50, // 0x50 2 Pad
130 0x22, 0x51, // 0x51 3 Pad
131 0x2D, 0x52, // 0x52 0 Pad
132 0x2E, 0x53, // 0x53 . Pad
133 0, 0, // 0x54
134 0, 0, // 0x55
135 0xe2, 0x56, // 0x56 "<>|"
136 0x7A, 0x57, // 0x57 F11
137 0x7B, 0x58, // 0x58 F12
138 0, 0, // 0x59
139 0x0D, 0x11C, // 0x5A Enter Pad
140 0x11, 0x11D, // 0x5B RCtrl
141 0x6F, 0x135, // 0x5C / Pad
142 0x2D, 0x152, // 0x5D PrtSc
143 0x12, 0x5E, // 0x5E RAlt
144 0x13, 0x45, // 0x5F Pause
145 VK_HOME_W, 0x60, // 0x60
146 VK_UP_W, 0x61, // 0x61
147 VK_PRIOR_W, 0x62, // 0x62
148 VK_LEFT_W, 0x63, // 0x63
149 VK_RIGHT_W, 0x64, // 0x64
150 VK_END_W, 0x65, // 0x65
151 VK_DOWN_W, 0x66, // 0x66
152 VK_NEXT_W, 0x67, // 0x67
153 VK_INSERT_W, 0x68, // 0x68
154 VK_DELETE_W, 0x69, // 0x69
155 VK_F23_W, 0x6A, // 0x6A
156 VK_F24_W, 0x6B, // 0x6B
157 0x5D, 0x15D, // 0x6C RWin (PM scan 0x7C)
158 0, 0, // 0x6D
159 0x5B, 0x15B, // 0x6E LWin (PM scan 0x7E)
160 0x5C, 0x15C // 0x6F RMenu? (PM scan 0x7F)
161};
162
163static BOOL fGenerateDoubleClick = FALSE;
164static MSG doubleClickMsg = {0};
165
166//******************************************************************************
167//******************************************************************************
168ULONG GetMouseKeyState()
169{
170 ULONG keystate = 0;
171
172 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000)
173 keystate |= MK_LBUTTON_W;
174 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000)
175 keystate |= MK_RBUTTON_W;
176 if(WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000)
177 keystate |= MK_MBUTTON_W;
178 if(WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000)
179 keystate |= MK_SHIFT_W;
180 if(WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000)
181 keystate |= MK_CONTROL_W;
182
183 return keystate;
184}
185//******************************************************************************
186//******************************************************************************
187LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
188{
189 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
190}
191//******************************************************************************
192//******************************************************************************
193void SetMenuDoubleClick(BOOL fSet)
194{
195 fGenerateDoubleClick = fSet;
196}
197//******************************************************************************
198//******************************************************************************
199BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
200{
201 Win32BaseWindow *win32wnd = 0;
202 OSLIBPOINT point, ClientPoint;
203 POSTMSG_PACKET *packet;
204 TEB *teb = (TEB *)pTeb;
205 BOOL fWasDisabled = FALSE;
206 BOOL fIsFrame = FALSE;
207 int i;
208
209 memset(winMsg, 0, sizeof(MSG));
210 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
211 if(!win32wnd) {
212 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
213 if(win32wnd) {
214 fIsFrame = TRUE;
215 }
216 }
217
218 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
219 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
220 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
221 {
222 goto dummymessage; //not a win32 client window
223 }
224 winMsg->time = os2Msg->time;
225 //CB: PM bug or undocumented feature? ptl.x highword is set!
226 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
227 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
228
229 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
230 winMsg->hwnd = win32wnd->getWindowHandle();
231
232 if(os2Msg->msg >= WIN32APP_POSTMSG) {
233 packet = (POSTMSG_PACKET *)os2Msg->mp2;
234 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
235 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
236 winMsg->wParam = packet->wParam;
237 winMsg->lParam = packet->lParam;
238 if(fMsgRemoved == MSG_REMOVE) free(packet); //free the shared memory here
239 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
240 return TRUE;
241 }
242 else {//broadcasted message (no packet present)
243 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
244 winMsg->wParam = (UINT)os2Msg->mp1;
245 winMsg->lParam = (DWORD)os2Msg->mp2;
246 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
247 return TRUE;
248 }
249 goto dummymessage;
250 }
251
252 switch(os2Msg->msg)
253 {
254 //OS/2 msgs
255 case WM_CREATE:
256 {
257 if(teb->o.odin.newWindow == 0) {
258 DebugInt3();
259 goto dummymessage;
260 }
261
262 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
263 win32wnd->addRef();
264
265 winMsg->message = WINWM_CREATE;
266 winMsg->hwnd = win32wnd->getWindowHandle();
267 winMsg->wParam = 0;
268 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
269 break;
270 }
271
272 case WM_QUIT:
273 winMsg->message = WINWM_QUIT;
274 break;
275
276 case WM_CLOSE:
277 winMsg->message = WINWM_CLOSE;
278 break;
279
280 case WM_DESTROY:
281 winMsg->message = WINWM_DESTROY;
282 break;
283
284 case WM_ENABLE:
285 winMsg->message = WINWM_ENABLE;
286 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
287 break;
288
289 case WM_SHOW:
290 winMsg->message = WINWM_SHOWWINDOW;
291 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
292 break;
293
294 case WM_WINDOWPOSCHANGED:
295 {
296 PSWP pswp = (PSWP)os2Msg->mp1;
297 SWP swpOld = *(pswp + 1);
298 HWND hParent = NULLHANDLE;
299 LONG yDelta = pswp->cy - swpOld.cy;
300 LONG xDelta = pswp->cx - swpOld.cx;
301
302 if(!fIsFrame) goto dummymessage;
303
304 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
305
306 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
307 if (win32wnd->isChild()) {
308 if(win32wnd->getParent()) {
309 hParent = win32wnd->getParent()->getOS2WindowHandle();
310 }
311 else goto dummymessage; //parent has just been destroyed
312 }
313 }
314 if(win32wnd->getParent()) {
315 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
316 win32wnd->getOS2WindowHandle());
317 }
318 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
319
320 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
321
322 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
323 {
324 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
325 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
326 {
327 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
328 if(wndAfter) {
329 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
330 RELEASE_WNDOBJ(wndAfter);
331 }
332 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
333 }
334 }
335 winMsg->message = WINWM_WINDOWPOSCHANGED;
336 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
337 break;
338 }
339
340 case WM_ACTIVATE:
341 {
342 HWND hwndActivate = (HWND)os2Msg->mp2;
343 BOOL fMinimized = FALSE;
344
345 hwndActivate = OS2ToWin32Handle(hwndActivate);
346 if(hwndActivate == 0) {
347 //another (non-win32) application's window
348 //set to desktop window handle
349 hwndActivate = windowDesktop->getWindowHandle();
350 }
351
352 if(win32wnd->getStyle() & WS_MINIMIZE_W)
353 {
354 fMinimized = TRUE;
355 }
356
357 winMsg->message = WINWM_ACTIVATE;
358 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
359 winMsg->lParam = (LPARAM)hwndActivate;
360 break;
361 }
362
363 case WM_SETFOCUS:
364 {
365 HWND hwndFocus = (HWND)os2Msg->mp1;
366
367 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
368 //another (non-win32) application's window
369 //set to NULL (allowed according to win32 SDK) to avoid problems
370 hwndFocus = NULL;
371 }
372 else hwndFocus = OS2ToWin32Handle(hwndFocus);
373
374 if((ULONG)os2Msg->mp2 == TRUE) {
375 winMsg->message = WINWM_SETFOCUS;
376 winMsg->wParam = (WPARAM)hwndFocus;
377 }
378 else {
379 winMsg->message = WINWM_KILLFOCUS;
380 winMsg->wParam = (WPARAM)hwndFocus;
381 }
382 break;
383 }
384
385 //**************************************************************************
386 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
387 //**************************************************************************
388 case WM_BUTTON1DOWN:
389 case WM_BUTTON1UP:
390 case WM_BUTTON1DBLCLK:
391 case WM_BUTTON2DOWN:
392 case WM_BUTTON2UP:
393 case WM_BUTTON2DBLCLK:
394 case WM_BUTTON3DOWN:
395 case WM_BUTTON3UP:
396 case WM_BUTTON3DBLCLK:
397 {
398 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
399
400 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));
401
402 HWND hwnd;
403
404 DisableLogging();
405 if(GetCapture() != winMsg->hwnd)
406 {
407 hwnd = WindowFromPoint(winMsg->pt);
408 if(win32wnd->getWindowHandle() != hwnd) {
409 RELEASE_WNDOBJ(win32wnd);
410 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
411 if(win32wnd == NULL) {
412 DebugInt3();
413 EnableLogging();
414 goto dummymessage;
415 }
416 winMsg->hwnd = hwnd;
417 }
418 }
419
420 //if a window is disabled, it's parent receives the mouse messages
421 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
422 if(win32wnd->getParent()) {
423 Win32BaseWindow *parent = win32wnd->getParent();;
424 if(parent) parent->addRef();
425 RELEASE_WNDOBJ(win32wnd);
426 win32wnd = parent;
427 }
428 fWasDisabled = TRUE;
429 }
430
431 if(IsNCMouseMsg(win32wnd)) {
432 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
433 winMsg->wParam = win32wnd->getLastHitTestVal();
434 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
435 }
436 else {
437 ClientPoint.x = winMsg->pt.x;
438 ClientPoint.y = winMsg->pt.y;
439 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
440 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
441 winMsg->wParam = GetMouseKeyState();
442 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
443 }
444 EnableLogging();
445 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
446 {
447 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
448 goto dummymessage; //dinput swallowed message
449 }
450 }
451
452 if(fWasDisabled) {
453 if(win32wnd) {
454 winMsg->hwnd = win32wnd->getWindowHandle();
455 }
456 else goto dummymessage; //don't send mouse messages to disabled windows
457 }
458
459 DisableLogging();
460 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
461 (winMsg->message == WINWM_RBUTTONDOWN) ||
462 (winMsg->message == WINWM_MBUTTONDOWN) ||
463 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
464 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
465 (winMsg->message == WINWM_NCMBUTTONDOWN))
466 {
467 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
468 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
469 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
470 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
471 {
472 dprintf(("single -> double click"));
473 if(winMsg->message >= WINWM_LBUTTONDOWN) {
474 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
475 }
476 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
477 doubleClickMsg.message = 0;
478 }
479 else {
480 dprintf(("save for double click"));
481 doubleClickMsg = *winMsg;
482 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
483 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
484 }
485 }
486 }
487 EnableLogging();
488
489 break;
490 }
491
492 case WM_BUTTON2CLICK:
493 case WM_BUTTON1CLICK:
494 case WM_BUTTON3CLICK:
495 goto dummymessage;
496
497 case WM_BUTTON2MOTIONSTART:
498 case WM_BUTTON2MOTIONEND:
499 case WM_BUTTON1MOTIONSTART:
500 case WM_BUTTON1MOTIONEND:
501 case WM_BUTTON3MOTIONSTART:
502 case WM_BUTTON3MOTIONEND:
503 //no break; translate to WM_MOUSEMOVE
504 //Some applications (e.g. Unreal) retrieve all mouse messages
505 //when a mouse button is pressed and don't expect WM_NULL
506
507 case WM_MOUSEMOVE:
508 {
509 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
510
511 HWND hwnd;
512
513 dprintf2(("WM_NCMOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
514 DisableLogging();
515 if(GetCapture() != winMsg->hwnd)
516 {
517 hwnd = WindowFromPoint(winMsg->pt);
518 if(win32wnd->getWindowHandle() != hwnd) {
519 RELEASE_WNDOBJ(win32wnd);
520 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
521 if(win32wnd == NULL) {
522 DebugInt3();
523 EnableLogging();
524 goto dummymessage;
525 }
526 winMsg->hwnd = hwnd;
527 }
528 }
529
530 //if a window is disabled, it's parent receives the mouse messages
531 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
532 if(win32wnd->getParent()) {
533 Win32BaseWindow *parent = win32wnd->getParent();;
534 if(parent) parent->addRef();
535 RELEASE_WNDOBJ(win32wnd);
536 win32wnd = parent;
537 }
538 fWasDisabled = TRUE;
539 }
540 if(IsNCMouseMsg(win32wnd))
541 {
542 winMsg->message = WINWM_NCMOUSEMOVE;
543 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
544 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
545 }
546 else
547 {
548 ClientPoint.x = winMsg->pt.x;
549 ClientPoint.y = winMsg->pt.y;
550 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
551
552 winMsg->message = WINWM_MOUSEMOVE;
553 winMsg->wParam = GetMouseKeyState();
554 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
555 }
556 EnableLogging();
557 if((fMsgRemoved == MSG_REMOVE) && ISMOUSE_CAPTURED())
558 {
559 if(DInputMouseHandler(win32wnd->getWindowHandle(), winMsg->message, winMsg->pt.x, winMsg->pt.y)) {
560 goto dummymessage; //dinput swallowed message
561 }
562 }
563 if(fWasDisabled) {
564 if(win32wnd) {
565 winMsg->hwnd = win32wnd->getWindowHandle();
566 }
567 else {
568 goto dummymessage; //don't send mouse messages to disabled windows
569 }
570 }
571 //OS/2 Window coordinates -> Win32 Window coordinates
572 break;
573 }
574
575 case WM_CONTROL:
576 goto dummymessage;
577
578 case WM_COMMAND:
579 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
580 winMsg->message = WINWM_COMMAND;
581 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
582 break;
583 }
584 //todo controls
585 goto dummymessage;
586
587 case WM_SYSCOMMAND:
588 {
589 ULONG x = 0, y = 0;
590 ULONG win32sc;
591
592 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
593 POINTL pointl;
594 WinQueryPointerPos(HWND_DESKTOP, &pointl);
595 x = pointl.x;
596 y = mapScreenY(y);
597 }
598 switch(SHORT1FROMMP(os2Msg->mp1)) {
599 case SC_MOVE:
600 win32sc = SC_MOVE_W;
601 break;
602 case SC_CLOSE:
603 {
604 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
605 //TRUE -> user clicked on close button -> close window
606 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
607 {
608 HWND hwnd = win32wnd->GetTopParent();
609 if(win32wnd->getWindowHandle() != hwnd) {
610 RELEASE_WNDOBJ(win32wnd);
611 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
612 if(win32wnd == NULL) {
613 DebugInt3();
614 goto dummymessage;
615 }
616 winMsg->hwnd = hwnd;
617 }
618 }
619 win32sc = SC_CLOSE_W;
620 break;
621 }
622 case SC_MAXIMIZE:
623 win32sc = SC_MAXIMIZE_W;
624 break;
625 case SC_MINIMIZE:
626 win32sc = SC_MINIMIZE_W;
627 break;
628 case SC_NEXTFRAME:
629 case SC_NEXTWINDOW:
630 win32sc = SC_NEXTWINDOW_W;
631 break;
632 case SC_RESTORE:
633 win32sc = SC_RESTORE_W;
634 break;
635 case SC_TASKMANAGER:
636 win32sc = SC_TASKLIST_W;
637 break;
638 default:
639 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
640 goto dummymessage;
641 }
642 winMsg->message= WINWM_SYSCOMMAND;
643 winMsg->wParam = (WPARAM)win32sc;
644 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
645 break;
646 }
647
648 case WM_CHAR_SPECIAL:
649 {
650 // @@@PH
651 // special char message from the keyboard hook
652 dprintf(("PM: WM_CHAR_SPECIAL\n"));
653
654 // AltGr is a very, very strange key!
655 UCHAR ucPMScanCode = CHAR4FROMMP(os2Msg->mp1);
656 switch (ucPMScanCode)
657 {
658 case PMSCAN_ESC:
659 // Note: ESC generates a WM_CHAR under Windows, not under PM
660 // so we've got to post it to ourself here!
661 // WM_CHAR(0x0000001bh, 000010001h)
662 // @@@PH
663 break;
664
665 case PMSCAN_ALTRIGHT:
666 {
667 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
668
669 // we need very special treatment here for the
670 // poor, crippled AltGr key
671
672 if (flags & KC_KEYUP)
673 {
674 // key up
675 // 1 - generate a virtual LCONTROL-keypress
676 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-Alt!)
677 }
678 else
679 {
680 // key down:
681 // 1 - generate a virtual LCONTROL-keypress
682 // 2 - send LMENU-keypress (NT emulates ALtGr w/ Ctrl-AltGr!)
683 }
684 }
685 } /* switch */
686 } /* case */
687 // NO BREAK! FALLTHRU CASE!
688
689 case WM_CHAR:
690 {
691 ULONG repeatCount=0, virtualKey=0, keyFlags=0, scanCode=0;
692 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
693 BOOL keyWasPressed, isExtended = FALSE;
694 char c;
695
696 teb->o.odin.fTranslated = FALSE;
697 repeatCount = CHAR3FROMMP(os2Msg->mp1);
698 scanCode = CHAR4FROMMP(os2Msg->mp1);
699 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
700
701 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode));
702 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2));
703
704 // vitali add begin
705 if ( ( SHORT1FROMMP(os2Msg->mp2) & 0x0FF ) == 0x0E0 )
706 {
707 // an extended key ( arrows, ins, del and so on )
708 // get "virtual" scancode from character code because
709 // for "regular" keys they are equal
710 if(!(flags & (KC_SHIFT|KC_ALT|KC_CTRL))) {
711 scanCode = ( SHORT1FROMMP(os2Msg->mp2) >> 8) & 0x0FF;
712 }
713 isExtended = TRUE;
714 }
715 // vitali add end
716
717 // both WM_KEYUP & WM_KEYDOWN want a virtual key, find the right Win32 virtual key
718 // given the OS/2 virtual key and OS/2 character
719
720 //if (((SHORT1FROMMP (mp1) & KC_CHAR) == KC_CHAR) ||
721 // ((SHORT1FROMMP (mp1) & KC_LONEKEY) == KC_LONEKEY))
722 c = 0;
723 if ((SHORT1FROMMP (os2Msg->mp1) & 0xFF) != 0)
724 {
725 c = SHORT1FROMMP (os2Msg->mp2);
726 if ((c >= 'A') && (c <= 'Z')) {
727 virtualKey = c;
728 goto VirtualKeyFound;
729 }
730 if ((c >='a') && (c <= 'z')) {
731 virtualKey = c - 32; // make it uppercase
732 goto VirtualKeyFound;
733 }
734 if ((c >= '0') && (c <= '9')) {
735 virtualKey = c;
736 goto VirtualKeyFound;
737 }
738 }
739
740VirtualKeyFound:
741// dprintf (("VIRTUALKEYFOUND:(%x)", virtualKey));
742
743 // Adjust PM scancodes for Win* keys
744 if (scanCode >= 0x70)
745 scanCode -= 0x10;
746 winMsg->wParam = pmscan2winkey[scanCode][0];
747 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
748 winMsg->lParam |= (pmscan2winkey[scanCode][1] & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
749
750 // Adjust VKEY value for pad digits if NumLock is on
751 if ((scanCode >= 0x47) && (scanCode <= 0x53) &&
752 (virtualKey >= 0x30) && (virtualKey >= 39))
753 winMsg->wParam = virtualKey + 0x30;
754
755 // Set the extended bit when appropriate
756 if (isExtended)
757 winMsg->lParam = winMsg->lParam | (1<<24);
758
759 if (!(flags & KC_ALT))
760 {
761 //
762 // the Alt key is not pressed
763 // or no more pressed
764 //
765 if (flags & KC_KEYUP)
766 {
767 // check for a lonesome ALT key ...
768 if ( (flags & KC_LONEKEY) &&
769 (winMsg->wParam == VK_LMENU_W) )
770 {
771 winMsg->message = WINWM_SYSKEYUP;
772
773 // held ALT-key when current key is released
774 // generates additional flag 0x2000000
775 // Note: PM seems to do this differently,
776 // KC_ALT is already reset
777 }
778 else
779 {
780 // send WM_KEYUP message
781 winMsg->message = WINWM_KEYUP;
782 }
783
784 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
785 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
786 }
787 else
788 {
789 // send WM_KEYDOWN message
790 winMsg->message = WINWM_KEYDOWN;
791 if (keyWasPressed)
792 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
793 }
794 }
795 else
796 {
797 //
798 // the Alt key is pressed
799 //
800 if (flags & KC_KEYUP)
801 {
802 // send WM_SYSKEYUP message
803 winMsg->message = WINWM_SYSKEYUP;
804 winMsg->lParam |= 1 << 30; // bit 30, previous state, always 1 for a WM_KEYUP message
805 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
806 }
807 else
808 {
809 // send WM_SYSKEYDOWN message
810 winMsg->message = WINWM_SYSKEYDOWN;
811 if (keyWasPressed)
812 winMsg->lParam |= 1 << 30; // bit 30, previous state, 1 means key was pressed
813
814 // pressed ALT-key generates additional flag 0x2000000
815 // if the current window has keyboard focus
816 winMsg->lParam |= 1 << 29;
817 }
818 }
819
820
821 if (ISKDB_CAPTURED())
822 {
823 if (DInputKeyBoardHandler(winMsg)) {
824 goto dummymessage; //dinput swallowed message
825 }
826 }
827 break;
828 }
829
830 case WM_TIMER:
831//Why was this check here????
832// if (os2Msg->mp2)
833// {
834 BOOL sys;
835 ULONG id;
836
837 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id))
838 {
839 winMsg->wParam = (WPARAM)id;
840 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
841 break;
842 }
843// }
844 goto dummymessage; //for caret blinking
845
846 case WM_SETWINDOWPARAMS:
847 {
848 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
849
850 if(wndParams->fsStatus & WPM_TEXT) {
851 winMsg->message = WINWM_SETTEXT;
852 winMsg->lParam = (LPARAM)wndParams->pszText;
853 break;
854 }
855 goto dummymessage;
856 }
857
858#if 0
859 case WM_QUERYWINDOWPARAMS:
860 {
861 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
862 ULONG textlen;
863 PSZ wintext;
864
865 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
866 {
867 if(wndpars->fsStatus & WPM_CCHTEXT)
868 wndpars->cchText = win32wnd->MsgGetTextLength();
869 if(wndpars->fsStatus & WPM_TEXT)
870 wndpars->pszText = win32wnd->MsgGetText();
871
872 wndpars->fsStatus = 0;
873 wndpars->cbCtlData = 0;
874 wndpars->cbPresParams = 0;
875 goto dummymessage;
876 }
877 }
878#endif
879
880 case WM_PAINT:
881 {
882 if(win32wnd->IsWindowIconic()) {
883 winMsg->message = WINWM_PAINTICON;
884 }
885 else winMsg->message = WINWM_PAINT;
886 break;
887 }
888
889 case WM_CONTEXTMENU:
890 winMsg->message = WINWM_CONTEXTMENU;
891 winMsg->wParam = win32wnd->getWindowHandle();
892 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
893 break;
894
895 case WM_RENDERFMT:
896 winMsg->message = WINWM_RENDERFORMAT;
897 winMsg->wParam = (UINT) os2Msg->mp1;
898 break;
899
900 case WM_RENDERALLFMTS:
901 winMsg->message = WINWM_RENDERALLFORMATS;
902 break;
903
904 case WM_DESTROYCLIPBOARD:
905 winMsg->message = WINWM_DESTROYCLIPBOARD;
906 break;
907
908 case WM_HSCROLL:
909 case WM_VSCROLL:
910 winMsg->message = (os2Msg->msg == WM_HSCROLL) ? WINWM_HSCROLL : WINWM_VSCROLL;
911 winMsg->lParam = 0;
912 winMsg->wParam = 0;
913 switch(SHORT2FROMMP(os2Msg->mp2)) {
914 case SB_LINERIGHT:
915 winMsg->wParam = SB_LINERIGHT_W;
916 break;
917 case SB_LINELEFT:
918 winMsg->wParam = SB_LINELEFT_W;
919 break;
920 case SB_PAGELEFT:
921 winMsg->wParam = SB_PAGELEFT_W;
922 break;
923 case SB_PAGERIGHT:
924 winMsg->wParam = SB_PAGERIGHT_W;
925 break;
926 default:
927 dprintf(("Unsupported WM_H/VSCROLL message %x!!", SHORT2FROMMP(os2Msg->mp2)));
928 goto dummymessage;
929 }
930 break;
931
932 case WM_INITMENU:
933 case WM_MENUSELECT:
934 case WM_MENUEND:
935 case WM_NEXTMENU:
936 case WM_SYSCOLORCHANGE:
937 case WM_SYSVALUECHANGED:
938 case WM_SETSELECTION:
939 case WM_PPAINT:
940 case WM_PSETFOCUS:
941 case WM_PSYSCOLORCHANGE:
942 case WM_PSIZE:
943 case WM_PACTIVATE:
944 case WM_PCONTROL:
945 case WM_HELP:
946 case WM_APPTERMINATENOTIFY:
947 case WM_PRESPARAMCHANGED:
948 case WM_DRAWITEM:
949 case WM_MEASUREITEM:
950 case WM_CONTROLPOINTER:
951 case WM_QUERYDLGCODE:
952 case WM_SUBSTITUTESTRING:
953 case WM_MATCHMNEMONIC:
954 case WM_SAVEAPPLICATION:
955 case WM_SEMANTICEVENT:
956 default:
957dummymessage:
958 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
959 winMsg->message = 0;
960 winMsg->wParam = 0;
961 winMsg->lParam = 0;
962 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
963 return FALSE;
964 }
965 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
966 return TRUE;
967}
968//******************************************************************************
969//******************************************************************************
970BOOL OSLibWinTranslateMessage(MSG *msg)
971{
972 TEB *teb;
973
974 teb = GetThreadTEB();
975 if(!teb) {
976 return FALSE;
977 }
978 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
979 // the newly generated WM_CHAR message.
980 if(!teb->o.odin.fTranslated && teb->o.odin.os2msg.msg == WM_CHAR && !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
981 {//TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
982 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
983 MSG extramsg;
984
985 memcpy(&extramsg, msg, sizeof(MSG));
986 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
987 extramsg.lParam = 0;
988
989 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN) {
990 return FALSE;
991 }
992
993 if(fl & KC_VIRTUALKEY) {
994 if(msg->wParam) {
995 if ((msg->wParam >= VK_NUMPAD0_W) && (msg->wParam <= VK_NUMPAD9_W))
996 extramsg.wParam = msg->wParam - 0x30;
997 else
998 extramsg.wParam = msg->wParam;
999 }
1000 else extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1001 }
1002
1003
1004 if(msg->message >= WINWM_SYSKEYDOWN) {
1005 extramsg.message = WINWM_SYSCHAR;
1006 }
1007 else extramsg.message = WINWM_CHAR;
1008
1009 if(fl & KC_DEADKEY) {
1010 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1011 }
1012
1013 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1014 if(fl & KC_ALT)
1015 extramsg.lParam |= (1<<29);
1016 if(fl & KC_PREVDOWN)
1017 extramsg.lParam |= (1<<30);
1018 if(fl & KC_KEYUP)
1019 extramsg.lParam |= (1<<31);
1020
1021 teb->o.odin.fTranslated = TRUE;
1022 memcpy(&teb->o.odin.msgWCHAR, &extramsg, sizeof(MSG));
1023 return TRUE;
1024 }
1025 return FALSE;
1026}
1027//******************************************************************************
1028//******************************************************************************
1029
Note: See TracBrowser for help on using the repository browser.