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

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

fixed ESC processing

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