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

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 53.4 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.125 2004-05-24 09:01:59 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_NLS
18#define INCL_GPI
19#define INCL_WIN
20#define INCL_PM
21#define INCL_DOSPROCESS
22#include <os2wrap.h>
23#include <string.h>
24#include <misc.h>
25#include <winconst.h>
26#include <win32api.h>
27#include "oslibmsg.h"
28#include <winuser32.h>
29#include "win32wdesktop.h"
30#include "oslibutil.h"
31#include "timer.h"
32#include <thread.h>
33#include <wprocess.h>
34#include "pmwindow.h"
35#include "oslibwin.h"
36#include "winmouse.h"
37#include <pmkbdhk.h>
38#include <pmscan.h>
39#include <winscan.h>
40#include <winkeyboard.h>
41#include <winnls.h>
42#include <heapstring.h>
43#include "hook.h"
44#include "user32api.h"
45
46#include <os2im.h>
47#include <im32.h>
48
49#define DBG_LOCALLOG DBG_oslibmsgtranslate
50#include "dbglocal.h"
51
52static BOOL fGenerateDoubleClick = FALSE;
53static MSG doubleClickMsg = {0};
54
55extern "C" UINT WINAPI GetACP(void); // from winnls.h
56extern "C" UINT WIN32API clipboardPMToOdinFormat(ULONG ulPMFormat);
57
58//For wheel mouse translation
59#define WHEEL_DELTA 120
60#define OS2_WHEEL_CORRECTION 1
61//PF Correction is different for different mouse drivers. For now no correction
62//is ok because lots of Odin controls rely on minimum delta. However in future
63//we will possibly detect mouse driver and use correction if speed will be
64//too high or too low.
65
66//******************************************************************************
67//
68// setThreadQueueExtraCharMessage: queues WM_CHAR message so it is retrieved
69// by GetMessage & PeekMessage
70//
71// NOTE: WM_CHAR message always in ascii format
72//
73//******************************************************************************
74BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
75{
76 if ( teb->o.odin.tidAttachedInputThread
77 && OSLibForwardMessageToAttachedThread(teb, pExtraMsg, NULL))
78 return TRUE;
79
80 // check if the single slot is occupied already
81 if (teb->o.odin.fTranslated == TRUE) {
82 // there's still an already translated message to be processed
83 dprintf(("WARNING: translated message already pending!"));
84 return FALSE;
85 }
86
87 teb->o.odin.fTranslated = TRUE;
88 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
89 return TRUE;
90}
91
92//******************************************************************************
93//******************************************************************************
94ULONG ConvertNumPadKey(ULONG pmScan)
95{
96 ULONG ret;
97 UCHAR winKey;
98
99 switch (pmScan)
100 {
101 case PMSCAN_PAD7: ret = PMSCAN_HOME; break;
102 case PMSCAN_PAD8: ret = PMSCAN_UP; break;
103 case PMSCAN_PAD9: ret = PMSCAN_PAGEUP; break;
104 case PMSCAN_PAD4: ret = PMSCAN_LEFT; break;
105 case PMSCAN_PAD6: ret = PMSCAN_RIGHT; break;
106 case PMSCAN_PAD1: ret = PMSCAN_END; break;
107 case PMSCAN_PAD2: ret = PMSCAN_DOWN; break;
108 case PMSCAN_PAD3: ret = PMSCAN_PAGEDOWN; break;
109 case PMSCAN_PAD0: ret = PMSCAN_INSERT; break;
110 case PMSCAN_PADPERIOD: ret = PMSCAN_DELETE; break;
111 default:
112 ret = pmScan;
113 }
114
115 KeyTranslatePMScanToWinVKey(ret, FALSE, &winKey, NULL, NULL);
116 return winKey;
117
118}
119//******************************************************************************
120//******************************************************************************
121LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
122{
123 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
124}
125//******************************************************************************
126//******************************************************************************
127void OSLibSetMenuDoubleClick(BOOL fSet)
128{
129 fGenerateDoubleClick = fSet;
130}
131//******************************************************************************
132
133
134/**
135 * Inter process/thread packet cleanup.
136 * See OSLibPackMessage() for details on the packing.
137 *
138 * @param pTeb Pointer to the thread environment block for the current thread.
139 * @param pPacket Pointer to the packet in question.
140 * @param pWinMsg Pointer to the window message corresponding to the packet.
141 */
142inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
143{
144 switch (pWinMsg->message)
145 {
146 /*
147 * Place this in the TEB freeing any previous WM_COPYDATA packet.
148 * Note! Nested WM_COPYDATA isn't working.
149 */
150 case WINWM_COPYDATA:
151 {
152 dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
153 if (pTeb->o.odin.pWM_COPYDATA)
154 _sfree(pTeb->o.odin.pWM_COPYDATA);
155 pTeb->o.odin.pWM_COPYDATA = pPacket;
156 break;
157 }
158
159 /*
160 * Default packing - free the shared memory here.
161 */
162 default:
163 _sfree(pPacket);
164 break;
165 }
166}
167
168//******************************************************************************
169BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
170{
171 Win32BaseWindow *win32wnd = 0;
172 OSLIBPOINT point, ClientPoint;
173 POSTMSG_PACKET *packet;
174 TEB *teb = (TEB *)pTeb;
175 BOOL fWasDisabled = FALSE;
176 BOOL fIsFrame = FALSE;
177 int i;
178
179 /*
180 * Forwarded input (AttachThreadInput()).
181 */
182 if ( os2Msg->hwnd == NULLHANDLE
183 && os2Msg->msg == WIN32APP_FORWARDEDPOSTMSG
184 && os2Msg->mp2 == (MPARAM)WIN32APP_FORWARDEDPOSTMSG_MAGIC
185 && os2Msg->mp1 != NULL)
186 {
187 *winMsg = *(MSG*)os2Msg->mp1;
188 if (fMsgRemoved)
189 _sfree(os2Msg->mp1);
190 dprintf(("OS2ToWinMsgTranslate: Received forwarded messaged %x\n", os2Msg->msg));
191 return TRUE;
192 }
193
194 memset(winMsg, 0, sizeof(MSG));
195 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
196 if(!win32wnd) {
197 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
198 if(win32wnd) {
199 fIsFrame = TRUE;
200 }
201 }
202
203 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
204 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
205 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
206 {
207 goto dummymessage; //not a win32 client window
208 }
209 winMsg->time = os2Msg->time;
210 //CB: PM bug or undocumented feature? ptl.x highword is set!
211 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
212 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
213
214 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
215 winMsg->hwnd = win32wnd->getWindowHandle();
216
217 if(os2Msg->msg >= WIN32APP_POSTMSG) {
218 packet = (POSTMSG_PACKET *)os2Msg->mp2;
219 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
220 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
221 winMsg->wParam = packet->wParam;
222 winMsg->lParam = packet->lParam;
223 if (fMsgRemoved == MSG_REMOVE)
224 {
225 /* avoid double free */
226 if (os2Msg->mp2)
227 {
228 OSLibCleanupPacket(teb, packet, winMsg);
229 os2Msg->mp2 = NULL;
230 }
231#ifdef DEBUG
232 else
233 dprintf(("Trying to free NULL in WinMsgTranslate"));
234#endif
235 }
236 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
237 return TRUE;
238 }
239 else {//broadcasted message (no packet present)
240 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
241 winMsg->wParam = (UINT)os2Msg->mp1;
242 winMsg->lParam = (DWORD)os2Msg->mp2;
243 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
244 return TRUE;
245 }
246 goto dummymessage;
247 }
248
249 switch(os2Msg->msg)
250 {
251 //OS/2 msgs
252 case WM_CREATE:
253 {
254 if(teb->o.odin.newWindow == 0) {
255 DebugInt3();
256 goto dummymessage;
257 }
258
259 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
260 win32wnd->addRef();
261
262 winMsg->message = WINWM_CREATE;
263 winMsg->hwnd = win32wnd->getWindowHandle();
264 winMsg->wParam = 0;
265 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
266 break;
267 }
268
269 case WM_QUIT:
270 winMsg->message = WINWM_QUIT;
271 if (fMsgRemoved && win32wnd && (ULONG)os2Msg->mp2 != 0) {
272 // mp2 != 0 -> sent by window list; be nice and close
273 // the window first
274 win32wnd->MsgClose();
275 }
276 break;
277
278 case WM_CLOSE:
279 winMsg->message = WINWM_CLOSE;
280 break;
281
282 case WM_DESTROY:
283 winMsg->message = WINWM_DESTROY;
284 break;
285
286 case WM_ENABLE:
287 winMsg->message = WINWM_ENABLE;
288 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
289 break;
290
291 case WM_SHOW:
292 winMsg->message = WINWM_SHOWWINDOW;
293 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
294 break;
295
296 case WM_REALIZEPALETTE:
297 winMsg->message = WINWM_PALETTECHANGED;
298 break;
299
300 case WM_WINDOWPOSCHANGED:
301 {
302 PSWP pswp = (PSWP)os2Msg->mp1;
303 SWP swpOld = *(pswp + 1);
304 HWND hParent = NULLHANDLE;
305 LONG yDelta = pswp->cy - swpOld.cy;
306 LONG xDelta = pswp->cx - swpOld.cx;
307
308 if(!fIsFrame) goto dummymessage;
309
310 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
311
312 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
313 if (win32wnd->isChild()) {
314 if(win32wnd->getParent()) {
315 hParent = win32wnd->getParent()->getOS2WindowHandle();
316 }
317 else goto dummymessage; //parent has just been destroyed
318 }
319 }
320 if(win32wnd->getParent()) {
321 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
322 win32wnd->getOS2WindowHandle());
323 }
324 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
325
326 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
327
328 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
329 {
330 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
331 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
332 {
333 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
334 if(wndAfter) {
335 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
336 RELEASE_WNDOBJ(wndAfter);
337 }
338 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
339 }
340 }
341 winMsg->message = WINWM_WINDOWPOSCHANGED;
342 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
343 break;
344 }
345
346 case WM_ACTIVATE:
347 {
348 HWND hwndActivate = (HWND)os2Msg->mp2;
349 BOOL fMinimized = FALSE;
350
351 hwndActivate = OS2ToWin32Handle(hwndActivate);
352 if(hwndActivate == 0) {
353 //another (non-win32) application's window
354 //set to desktop window handle
355 hwndActivate = windowDesktop->getWindowHandle();
356 }
357
358 if(win32wnd->getStyle() & WS_MINIMIZE_W)
359 {
360 fMinimized = TRUE;
361 }
362
363 winMsg->message = WINWM_ACTIVATE;
364 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
365 winMsg->lParam = (LPARAM)hwndActivate;
366 break;
367 }
368
369 case WM_SETFOCUS:
370 {
371 HWND hwndFocus = (HWND)os2Msg->mp1;
372
373 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
374 //another (non-win32) application's window
375 //set to NULL (allowed according to win32 SDK) to avoid problems
376 hwndFocus = NULL;
377 }
378 else hwndFocus = OS2ToWin32Handle(hwndFocus);
379
380 if((ULONG)os2Msg->mp2 == TRUE) {
381 winMsg->message = WINWM_SETFOCUS;
382 winMsg->wParam = (WPARAM)hwndFocus;
383 }
384 else {
385 //If SetFocus(0) was called, then the window has already received
386 //a WM_KILLFOCUS; don't send another one
387 if(!fIgnoreKeystrokes) {
388 winMsg->message = WINWM_KILLFOCUS;
389 winMsg->wParam = (WPARAM)hwndFocus;
390 }
391 else {
392 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
393 goto dummymessage;
394 }
395 }
396 break;
397 }
398
399 //**************************************************************************
400 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
401 //**************************************************************************
402 case WM_BUTTON1DOWN:
403 case WM_BUTTON1UP:
404 case WM_BUTTON1DBLCLK:
405 case WM_BUTTON2DOWN:
406 case WM_BUTTON2UP:
407 case WM_BUTTON2DBLCLK:
408 case WM_BUTTON3DOWN:
409 case WM_BUTTON3UP:
410 case WM_BUTTON3DBLCLK:
411 {
412 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
413
414 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));
415
416 HWND hwnd;
417
418 DisableLogging();
419 if(GetCapture() != winMsg->hwnd)
420 {
421 hwnd = WindowFromPoint(winMsg->pt);
422 if(win32wnd->getWindowHandle() != hwnd) {
423 RELEASE_WNDOBJ(win32wnd);
424 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
425 if(win32wnd == NULL) {
426 DebugInt3();
427 EnableLogging();
428 goto dummymessage;
429 }
430 winMsg->hwnd = hwnd;
431 }
432 }
433
434 //if a window is disabled, its parent receives the mouse messages
435 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
436 if(win32wnd->getParent()) {
437 Win32BaseWindow *parent = win32wnd->getParent();;
438 if(parent) parent->addRef();
439 RELEASE_WNDOBJ(win32wnd);
440 win32wnd = parent;
441 }
442 fWasDisabled = TRUE;
443 }
444
445 if(IsNCMouseMsg(win32wnd)) {
446 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
447 winMsg->wParam = win32wnd->getLastHitTestVal();
448 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
449 }
450 else {
451 ClientPoint.x = winMsg->pt.x;
452 ClientPoint.y = winMsg->pt.y;
453 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
454 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
455 winMsg->wParam = GetMouseKeyState();
456 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
457 }
458 EnableLogging();
459
460 if(fWasDisabled) {
461 if(win32wnd) {
462 winMsg->hwnd = win32wnd->getWindowHandle();
463 }
464 else goto dummymessage; //don't send mouse messages to disabled windows
465 }
466
467 DisableLogging();
468 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
469 (winMsg->message == WINWM_RBUTTONDOWN) ||
470 (winMsg->message == WINWM_MBUTTONDOWN) ||
471 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
472 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
473 (winMsg->message == WINWM_NCMBUTTONDOWN))
474 {
475 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
476 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
477 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
478 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
479 {
480 dprintf(("single -> double click"));
481 if(winMsg->message >= WINWM_LBUTTONDOWN) {
482 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
483 }
484 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
485 if(fMsgRemoved) doubleClickMsg.message = 0;
486 }
487 else {
488 dprintf(("save for double click"));
489 if(fMsgRemoved) {
490 doubleClickMsg = *winMsg;
491 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
492 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
493 }
494 }
495 }
496 }
497 EnableLogging();
498
499 if(fMsgRemoved == MSG_REMOVE)
500 {
501 MSLLHOOKSTRUCT hook;
502 ULONG msg;
503
504 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
505 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
506 }
507 else msg = winMsg->message;
508
509 if(msg == WINWM_LBUTTONDBLCLK) {
510 msg = WINWM_LBUTTONDOWN;
511 }
512 else
513 if(msg == WINWM_RBUTTONDBLCLK) {
514 msg = WINWM_RBUTTONDOWN;
515 }
516 else
517 if(msg == WINWM_MBUTTONDBLCLK) {
518 msg = WINWM_MBUTTONDOWN;
519 }
520
521 // First the low-level mouse hook
522 hook.pt = winMsg->pt;
523 hook.mouseData = 0; //todo: XBUTTON1/2 (XP feature) or wheel data
524 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
525 hook.time = winMsg->time;
526 hook.dwExtraInfo = 0;
527
528 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
529 goto dummymessage; //hook swallowed message
530 }
531 }
532 MOUSEHOOKSTRUCT mousehk;
533
534 // Now inform the WH_MOUSE hook
535 mousehk.pt = winMsg->pt;
536 mousehk.hwnd = winMsg->hwnd;
537 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
538 mousehk.dwExtraInfo = 0;
539
540 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk)) {
541 //TODO: WH_CBT HCBT_CLICKSKIPPED
542 goto dummymessage; //hook swallowed message
543 }
544 break;
545 }
546
547 case WM_BUTTON2CLICK:
548 case WM_BUTTON1CLICK:
549 case WM_BUTTON3CLICK:
550 goto dummymessage;
551
552 case WM_BUTTON2MOTIONSTART:
553 case WM_BUTTON2MOTIONEND:
554 case WM_BUTTON1MOTIONSTART:
555 case WM_BUTTON1MOTIONEND:
556 case WM_BUTTON3MOTIONSTART:
557 case WM_BUTTON3MOTIONEND:
558 //no break; translate to WM_MOUSEMOVE
559 //Some applications (e.g. Unreal) retrieve all mouse messages
560 //when a mouse button is pressed and don't expect WM_NULL
561
562 case WM_MOUSEMOVE:
563 {
564 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
565
566 HWND hwnd;
567
568 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
569 DisableLogging();
570 if(GetCapture() != winMsg->hwnd)
571 {
572 hwnd = WindowFromPoint(winMsg->pt);
573 if(win32wnd->getWindowHandle() != hwnd) {
574 RELEASE_WNDOBJ(win32wnd);
575 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
576 if(win32wnd == NULL) {
577 DebugInt3();
578 EnableLogging();
579 goto dummymessage;
580 }
581 winMsg->hwnd = hwnd;
582 }
583 }
584
585 //if a window is disabled, its parent receives the mouse messages
586 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
587 if(win32wnd->getParent()) {
588 Win32BaseWindow *parent = win32wnd->getParent();;
589 if(parent) parent->addRef();
590 RELEASE_WNDOBJ(win32wnd);
591 win32wnd = parent;
592 }
593 fWasDisabled = TRUE;
594 }
595 if(IsNCMouseMsg(win32wnd))
596 {
597 winMsg->message = WINWM_NCMOUSEMOVE;
598 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
599 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
600 }
601 else
602 {
603 ClientPoint.x = winMsg->pt.x;
604 ClientPoint.y = winMsg->pt.y;
605 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
606
607 winMsg->message = WINWM_MOUSEMOVE;
608 winMsg->wParam = GetMouseKeyState();
609 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
610 }
611 EnableLogging();
612 if(fWasDisabled) {
613 if(win32wnd) {
614 winMsg->hwnd = win32wnd->getWindowHandle();
615 }
616 else {
617 goto dummymessage; //don't send mouse messages to disabled windows
618 }
619 }
620 MSLLHOOKSTRUCT hook;
621 if(fMsgRemoved == MSG_REMOVE)
622 {
623 hook.pt = winMsg->pt;
624 hook.mouseData = 0;
625 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
626 hook.time = winMsg->time;
627 hook.dwExtraInfo = 0;
628
629 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, winMsg->message, (LPARAM)&hook)) {
630 goto dummymessage; //hook swallowed message
631 }
632 }
633 MOUSEHOOKSTRUCT mousehk;
634
635 // Now inform the WH_MOUSE hook
636 mousehk.pt = winMsg->pt;
637 mousehk.hwnd = winMsg->hwnd;
638 mousehk.wHitTestCode = win32wnd->getLastHitTestVal();
639 mousehk.dwExtraInfo = 0;
640
641 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk))
642 {
643 goto dummymessage; //hook swallowed message
644 }
645 break;
646 }
647
648 case WM_CONTROL:
649 goto dummymessage;
650
651 case WM_COMMAND:
652 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
653 winMsg->message = WINWM_COMMAND;
654 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
655 break;
656 }
657 //todo controls
658 goto dummymessage;
659
660 case WM_SYSCOMMAND:
661 {
662 ULONG x = 0, y = 0;
663 ULONG win32sc;
664
665 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
666 POINTL pointl;
667 WinQueryPointerPos(HWND_DESKTOP, &pointl);
668 x = pointl.x;
669 y = mapScreenY(y);
670 }
671 switch(SHORT1FROMMP(os2Msg->mp1)) {
672 case SC_MOVE:
673 win32sc = SC_MOVE_W;
674 break;
675 case SC_CLOSE:
676 {
677 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
678 //TRUE -> user clicked on close button -> close window
679 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
680 {
681 HWND hwnd = win32wnd->GetTopParent();
682 if(win32wnd->getWindowHandle() != hwnd) {
683 RELEASE_WNDOBJ(win32wnd);
684 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
685 if(win32wnd == NULL) {
686 DebugInt3();
687 goto dummymessage;
688 }
689 winMsg->hwnd = hwnd;
690 }
691 }
692 win32sc = SC_CLOSE_W;
693 break;
694 }
695 case SC_MAXIMIZE:
696 win32sc = SC_MAXIMIZE_W;
697 break;
698 case SC_MINIMIZE:
699 win32sc = SC_MINIMIZE_W;
700 break;
701 case SC_NEXTFRAME:
702 case SC_NEXTWINDOW:
703 win32sc = SC_NEXTWINDOW_W;
704 break;
705 case SC_RESTORE:
706 win32sc = SC_RESTORE_W;
707 break;
708 case SC_TASKMANAGER:
709 win32sc = SC_TASKLIST_W;
710 break;
711 case SC_SYSMENU:
712 win32sc = SC_KEYMENU_W; //??
713 break;
714 default:
715 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
716 goto dummymessage;
717 }
718 winMsg->message= WINWM_SYSCOMMAND;
719 winMsg->wParam = (WPARAM)win32sc;
720 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
721 break;
722 }
723
724 case WM_CHAR_SPECIAL_ALTGRCONTROL:
725 {
726 // special char message from the keyboard hook
727 dprintf(("PM: WM_CHAR_SPECIAL_ALTGRCONTROL"));
728 // NO BREAK! FALLTHRU CASE!
729 }
730
731 case WM_CHAR_SPECIAL:
732 {
733 // @@@PH
734 // special char message from the keyboard hook
735 if(os2Msg->msg == WM_CHAR_SPECIAL) {
736 dprintf(("PM: WM_CHAR_SPECIAL"));
737 }
738 // NO BREAK! FALLTHRU CASE!
739 }
740
741 case WM_CHAR:
742 {
743 ULONG repeatCount=0;
744 ULONG virtualKey=0;
745 ULONG keyFlags=0;
746 USHORT scanCode=0;
747 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
748 BOOL keyWasPressed;
749 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
750 char c;
751 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
752
753 teb->o.odin.fTranslated = FALSE;
754 repeatCount = CHAR3FROMMP(os2Msg->mp1);
755 scanCode = CHAR4FROMMP(os2Msg->mp1);
756 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
757
758 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
759 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
760
761 BOOL fWinExtended;
762 UCHAR uchWinVKey;
763 WORD wWinScan;
764
765 if ( (!IsDBCSEnv() && scanCode == 0) ||
766 (scanCode==0 ) && !( flags & KC_CHAR ) )
767 {
768 goto dummymessage;
769 }
770
771 if( scanCode != 0 )
772 {
773 switch( SHORT2FROMMP( os2Msg->mp2 ))
774 {
775 // for Korean
776 case VK_DBE_HANJA :
777 uchWinVKey = 0x19;
778 break;
779
780 case VK_DBE_HANGEUL :
781 uchWinVKey = 0x15;
782 break;
783
784 case VK_DBE_JAMO :
785 uchWinVKey = 0;
786 break;
787
788 // for Japan
789 case VK_DBE_KATAKANA :
790 uchWinVKey = 0;
791 break;
792
793 case VK_DBE_HIRAGANA :
794 uchWinVKey = 0;
795 break;
796
797 case VK_DBE_SBCSCHAR :
798 uchWinVKey = 0;
799 break;
800
801 case VK_DBE_DBCSCHAR :
802 uchWinVKey = 0;
803 break;
804
805 case VK_DBE_SBCSDBCSCHAR :
806 uchWinVKey = 0;
807 break;
808
809 case VK_DBE_ROMAN :
810 uchWinVKey = 0;
811 break;
812
813 // for PRC-Chinese
814 case VK_DBE_HANZI :
815 uchWinVKey = 0;
816 break;
817
818 // for Taiwan
819 case VK_DBE_TSANGJYE :
820 uchWinVKey = 0;
821 break;
822
823 case VK_DBE_PHONETIC :
824 uchWinVKey = 0;
825 break;
826
827 case VK_DBE_CONV :
828 uchWinVKey = 0;
829 break;
830
831 case VK_DBE_NOCONV :
832 uchWinVKey = 0;
833 break;
834
835 case VK_DBE_ALPHANUMERIC :
836 switch( GetACP())
837 {
838 case 949 : // Korea
839 case 1361 :
840 uchWinVKey = 0x15;
841 break;
842
843 case 932 : // Japan
844 case 942 :
845 case 943 :
846
847 case 936 : // PRC
848 case 1381 :
849
850 case 950 : // Taiwan
851 default :
852 uchWinVKey = 0;
853 }
854 break;
855
856 default :
857 KeyTranslatePMScanToWinVKey(usPMScanCode,
858 FALSE,
859 &uchWinVKey,
860 &wWinScan,
861 &fWinExtended);
862 }
863
864 winMsg->wParam = uchWinVKey;
865 }
866 else
867 {
868 dprintf(("PM: WM_CHAR: DBCS processing "));
869
870 winMsg->wParam = CHAR1FROMMP( os2Msg->mp2 );
871
872 wWinScan = 0;
873 fWinExtended = 0;
874
875 if( CHAR2FROMMP( os2Msg->mp2 )) // DBCS character
876 {
877 CHAR dbcsCh[ 2 ] = { CHAR1FROMMP( os2Msg->mp2 ), CHAR2FROMMP( os2Msg->mp2 )};
878
879 if( isUnicode )
880 {
881 WCHAR uniChar;
882
883 MultiByteToWideChar( CP_ACP, 0, dbcsCh, 2, &uniChar, 1 );
884 winMsg->wParam = ( WPARAM )uniChar;
885 }
886 else
887 winMsg->wParam = ( dbcsCh[ 0 ] << 8 ) | dbcsCh[ 1 ];
888 }
889 }
890 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
891 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
892
893 // Set the extended bit when appropriate
894 if (fWinExtended)
895 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
896
897 //PF When we press shift we enable non-numeric functions of Numpad
898 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
899 winMsg->wParam = ConvertNumPadKey(scanCode);
900
901 //@PF This looks ugly but this is just what we have in win32 both in win98/win2k
902 //what happens is that lParam is tweaked in win32 to contain some illegal codes
903 //I simply reproduce here all situation. Absolute values can be kept because
904 //Break scancode can be acheived only by pressing Ctrl-Break combination
905 if ((usPMScanCode == PMSCAN_BREAK) && !(flags & KC_KEYUP) && (flags & KC_CTRL)
906 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
907 {
908 MSG extramsg;
909 memcpy(&extramsg, winMsg, sizeof(MSG));
910 // adjust our WM_CHAR code
911 extramsg.lParam = 0x01460001;
912
913 //After SetFocus(0), all keystrokes are converted in WM_SYS*
914 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
915
916 setThreadQueueExtraCharMessage(teb, &extramsg);
917 // and finally adjust our WM_KEYDOWN code
918 winMsg->lParam = 0x01460001;
919 }
920
921 if (!(flags & KC_ALT))
922 {
923 //
924 // the Alt key is not pressed
925 // or no more pressed
926 //
927 if (flags & KC_KEYUP)
928 {
929 // check for a lonesome ALT key ...
930 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
931 if ( (flags & KC_LONEKEY) &&
932 (winMsg->wParam == VK_LMENU_W) )
933 {
934 winMsg->message = WINWM_SYSKEYUP;
935 // held ALT-key when current key is released
936 // generates additional flag 0x2000000
937 // Note: PM seems to do this differently,
938 // KC_ALT is already reset
939 }
940 else
941 {
942 // send WM_KEYUP message
943 winMsg->message = WINWM_KEYUP;
944 }
945 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
946 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
947 }
948 else if( scanCode == 0 )
949 {
950 if( CHAR2FROMMP( os2Msg->mp2 ))
951 winMsg->message = WINWM_IME_CHAR;
952 else
953 {
954 //After SetFocus(0), all keystrokes are converted in WM_SYS*
955 winMsg->message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
956 }
957 }
958 else
959 { // send WM_KEYDOWN message
960 winMsg->message = WINWM_KEYDOWN;
961
962 if (keyWasPressed)
963 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
964
965 //Shift-Enter and possibly others need to have special handling
966 if (flags & KC_SHIFT)
967 {
968 if(fMsgRemoved && !(teb->o.odin.fTranslated))
969 {
970 dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
971 if (winMsg->wParam == VK_RETURN_W)
972 {
973 MSG extramsg;
974 memcpy(&extramsg, winMsg, sizeof(MSG));
975
976 //After SetFocus(0), all keystrokes are converted in WM_SYS*
977 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
978
979 // insert message into the queue
980 setThreadQueueExtraCharMessage(teb, &extramsg);
981 winMsg->lParam &= 0x3FFFFFFF;
982 }
983 } // else ???
984 } // KC_SHIFT
985 else
986 {
987 // in case we handle Enter directly through PMKBDHOOK
988 if ((os2Msg->msg == WM_CHAR_SPECIAL) && (winMsg->wParam == VK_RETURN_W)
989 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
990 {
991 MSG extramsg;
992 memcpy(&extramsg, winMsg, sizeof(MSG));
993
994 //After SetFocus(0), all keystrokes are converted in WM_SYS*
995 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
996
997 // insert message into the queue
998 setThreadQueueExtraCharMessage(teb, &extramsg);
999 }
1000 }
1001 }
1002 // if right alt is down, then we need to set the alt down bit too
1003 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
1004 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
1005 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
1006 {
1007 winMsg->lParam |= WIN_KEY_ALTHELD;
1008 }
1009 }
1010 else
1011 {
1012 //
1013 // the Alt key is pressed
1014 //
1015 if (flags & KC_KEYUP)
1016 {
1017 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
1018 winMsg->message = WINWM_SYSKEYUP;
1019 winMsg->lParam |= WIN_KEY_PREVSTATE;
1020 // No ALTHELD for Alt itself ;)
1021 winMsg->lParam |= WIN_KEY_ALTHELD;
1022 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
1023 }
1024 else
1025 {
1026 // send WM_SYSKEYDOWN message
1027 winMsg->message = WINWM_SYSKEYDOWN;
1028 if (keyWasPressed)
1029 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
1030
1031 // pressed ALT-key generates additional flag 0x2000000
1032 // if the current window has keyboard focus
1033 winMsg->lParam |= WIN_KEY_ALTHELD;
1034 }
1035 }
1036
1037 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1038 if(fIgnoreKeystrokes) {
1039 if(winMsg->message == WINWM_KEYDOWN) {
1040 winMsg->message = WINWM_SYSKEYDOWN;
1041 }
1042 else
1043 if(winMsg->message == WINWM_KEYUP) {
1044 winMsg->message = WINWM_SYSKEYUP;
1045 }
1046 }
1047 break;
1048 }
1049
1050 case WM_TIMER:
1051//Why was this check here????
1052// if (os2Msg->mp2)
1053// {
1054 BOOL sys;
1055 ULONG id, proc;
1056
1057 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
1058 {
1059 winMsg->wParam = (WPARAM)id;
1060 winMsg->lParam = (LPARAM)proc;
1061 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
1062 break;
1063 }
1064// }
1065 goto dummymessage; //for caret blinking
1066
1067 case WM_SETWINDOWPARAMS:
1068 {
1069 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
1070
1071 if(wndParams->fsStatus & WPM_TEXT) {
1072 winMsg->message = WINWM_SETTEXT;
1073 winMsg->lParam = (LPARAM)wndParams->pszText;
1074 break;
1075 }
1076 goto dummymessage;
1077 }
1078
1079#if 0
1080 case WM_QUERYWINDOWPARAMS:
1081 {
1082 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
1083 ULONG textlen;
1084 PSZ wintext;
1085
1086 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
1087 {
1088 if(wndpars->fsStatus & WPM_CCHTEXT)
1089 wndpars->cchText = win32wnd->MsgGetTextLength();
1090 if(wndpars->fsStatus & WPM_TEXT)
1091 wndpars->pszText = win32wnd->MsgGetText();
1092
1093 wndpars->fsStatus = 0;
1094 wndpars->cbCtlData = 0;
1095 wndpars->cbPresParams = 0;
1096 goto dummymessage;
1097 }
1098 }
1099#endif
1100
1101 case WM_PAINT:
1102 {
1103 if(win32wnd->IsWindowIconic()) {
1104 winMsg->message = WINWM_PAINTICON;
1105 }
1106 else winMsg->message = WINWM_PAINT;
1107 break;
1108 }
1109
1110 case WM_CONTEXTMENU:
1111 winMsg->message = WINWM_CONTEXTMENU;
1112 winMsg->wParam = win32wnd->getWindowHandle();
1113 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
1114 break;
1115
1116 case WM_RENDERFMT:
1117 winMsg->message = WINWM_RENDERFORMAT;
1118 winMsg->wParam = (UINT)clipboardPMToOdinFormat((ULONG)os2Msg->mp1);
1119 if (!winMsg->wParam)
1120 {
1121 dprintf(("WM_RENDERFMT: failed to convert clipboard format (%d)!!!\n", os2Msg->mp1));
1122 DebugInt3();
1123 }
1124 break;
1125
1126 case WM_RENDERALLFMTS:
1127 winMsg->message = WINWM_RENDERALLFORMATS;
1128 break;
1129
1130 case WM_DESTROYCLIPBOARD:
1131 winMsg->message = WINWM_DESTROYCLIPBOARD;
1132 break;
1133
1134 case WM_DRAWCLIPBOARD:
1135 winMsg->message = WINWM_DRAWCLIPBOARD;
1136 break;
1137
1138 case WM_HSCROLL:
1139 case WM_VSCROLL:
1140 //PF For win32 we support only vertical scrolling for WM_MOUSEWHEEL
1141 if (os2Msg->msg == WM_VSCROLL)
1142 {
1143 POINT CursorPoint;
1144 winMsg->message = WINWM_MOUSEWHEEL;
1145 if (OSLibWinQueryPointerPos(&CursorPoint))
1146 mapScreenPoint((OSLIBPOINT*)&CursorPoint);
1147
1148 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1149 winMsg->wParam = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1150 else
1151 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1152 winMsg->wParam = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1153 else
1154 winMsg->wParam = MAKELONG(GetMouseKeyState(), 0);
1155
1156 winMsg->lParam = MAKELONG(CursorPoint.x, CursorPoint.y);
1157
1158 dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
1159 if (fMsgRemoved == MSG_REMOVE)
1160 {
1161 MSLLHOOKSTRUCT hook;
1162 MOUSEHOOKSTRUCT mousehk;
1163
1164 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
1165 hook.pt.y = mapScreenY(os2Msg->ptl.y);
1166 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1167 hook.mouseData = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1168 else
1169 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1170 hook.mouseData = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1171 else goto dummymessage; // IBM driver produces other messages as well sometimes
1172
1173 hook.flags = LLMHF_INJECTED;
1174 hook.time = winMsg->time;
1175 hook.dwExtraInfo = 0;
1176 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
1177 goto dummymessage; //hook swallowed message
1178 }
1179 break;
1180 }
1181 goto dummymessage; //eat this message
1182 break;
1183
1184 case WM_IMENOTIFY:
1185 dprintf(("WM_IMENOTIFY"));
1186
1187 winMsg->wParam = 0;
1188 winMsg->lParam = 0;
1189
1190 switch(( ULONG )os2Msg->mp1 )
1191 {
1192 case IMN_STARTCONVERSION :
1193 winMsg->message = WM_IME_STARTCOMPOSITION_W;
1194 break;
1195
1196 case IMN_ENDCONVERSION :
1197 winMsg->message = WM_IME_ENDCOMPOSITION_W;
1198 break;
1199
1200 case IMN_CONVERSIONFULL :
1201 winMsg->message = WM_IME_COMPOSITIONFULL_W;
1202 break;
1203
1204 case IMN_IMECHANGED :
1205 winMsg->message = WM_IME_SELECT_W;
1206 // todo
1207 // fall through
1208
1209 default :
1210 goto dummymessage;
1211
1212 }
1213 break;
1214
1215 case WM_IMEREQUEST:
1216 winMsg->wParam = 0;
1217 winMsg->lParam = 0;
1218
1219 switch(( ULONG )os2Msg->mp1 )
1220 {
1221 case IMR_INSTANCEACTIVATE :
1222 {
1223 USHORT usIMR_IA = LOUSHORT( os2Msg->mp2 );
1224
1225 winMsg->message = WM_IME_SETCONTEXT_W;
1226 winMsg->wParam = HIUSHORT( os2Msg->mp2 );
1227
1228 if( usIMR_IA & IMR_IA_STATUS )
1229 winMsg->lParam |= ISC_SHOWUIGUIDELINE_W;
1230
1231 if( usIMR_IA & IMR_IA_CONVERSION )
1232 winMsg->lParam |= ISC_SHOWUICOMPOSITIONWINDOW_W;
1233
1234 if( usIMR_IA & IMR_IA_CANDIDATE )
1235 winMsg->lParam |= ISC_SHOWUIALLCANDIDATEWINDOW_W;
1236
1237 if( usIMR_IA & IMR_IA_INFOMSG )
1238 winMsg->lParam |= 0; // todo
1239
1240 if( usIMR_IA & IMR_IA_REGWORD )
1241 winMsg->lParam |= 0; // todo
1242 break;
1243 }
1244
1245 case IMR_STATUS :
1246 winMsg->message = WM_IME_NOTIFY_W;
1247
1248 switch(( ULONG )os2Msg->mp2 )
1249 {
1250 case IMR_STATUS_SHOW :
1251 winMsg->wParam = IMN_OPENSTATUSWINDOW_W;
1252 break;
1253
1254 case IMR_STATUS_HIDE :
1255 winMsg->wParam = IMN_CLOSESTATUSWINDOW_W;
1256 break;
1257
1258 case IMR_STATUS_INPUTMODE : // IMN_SETOPENSTATUS followed by IMN_SETCONVERSIONMODE
1259 winMsg->wParam = IMN_SETOPENSTATUS_W;
1260 break;
1261
1262 case IMR_STATUS_CONVERSIONMODE :
1263 winMsg->wParam = IMN_SETSENTENCEMODE_W;
1264 break;
1265
1266 case IMR_STATUS_STATUSPOS :
1267 winMsg->wParam = IMN_SETSTATUSWINDOWPOS_W;
1268 break;
1269
1270 case IMR_STATUS_STRING :
1271 case IMR_STATUS_STRINGATTR :
1272 case IMR_STATUS_CURSORPOS :
1273 case IMR_STATUS_CURSORATTR :
1274
1275 default :
1276 // todo
1277 goto dummymessage;
1278
1279 }
1280 break;
1281
1282 case IMR_CONVRESULT :
1283 {
1284 ULONG ulIMR = ( ULONG )os2Msg->mp2;
1285
1286 winMsg->message = WM_IME_COMPOSITION_W;
1287 winMsg->wParam = 0; // todo : current DBCS char
1288
1289 if( ulIMR & IMR_CONV_CONVERSIONSTRING )
1290 winMsg->lParam |= GCS_COMPSTR_W;
1291
1292 if( ulIMR & IMR_CONV_CONVERSIONATTR )
1293 winMsg->lParam |= GCS_COMPATTR_W;
1294
1295 if( ulIMR & IMR_CONV_CONVERSIONCLAUSE )
1296 winMsg->lParam |= GCS_COMPCLAUSE_W;
1297
1298 if( ulIMR & IMR_CONV_READINGSTRING )
1299 winMsg->lParam |= GCS_COMPREADSTR_W;
1300
1301 if( ulIMR & IMR_CONV_READINGATTR )
1302 winMsg->lParam |= GCS_COMPREADATTR_W;
1303
1304 if( ulIMR & IMR_CONV_READINGCLAUSE )
1305 winMsg->lParam |= GCS_COMPREADCLAUSE_W;
1306
1307 if( ulIMR & IMR_CONV_CURSORPOS )
1308 winMsg->lParam |= GCS_CURSORPOS_W;
1309
1310 if( ulIMR & IMR_CONV_CURSORATTR )
1311 winMsg->lParam |= 0; // todo
1312
1313 if( ulIMR & IMR_CONV_CHANGESTART )
1314 winMsg->lParam |= GCS_DELTASTART_W;
1315
1316 if( ulIMR & IMR_CONV_INSERTCHAR )
1317 winMsg->lParam |= CS_INSERTCHAR_W;
1318
1319 if( ulIMR & IMR_CONV_NOMOVECARET )
1320 winMsg->lParam |= CS_NOMOVECARET_W;
1321
1322 if( ulIMR & IMR_CONV_CONVERSIONFONT )
1323 winMsg->lParam |= 0; // todo
1324
1325 if( ulIMR & IMR_CONV_CONVERSIONPOS )
1326 winMsg->lParam |= 0; // todo
1327
1328 if( ulIMR & IMR_RESULT_RESULTSTRING )
1329 winMsg->lParam = GCS_RESULTSTR_W; // clear all composition info
1330
1331 if( ulIMR & IMR_RESULT_RESULTATTR )
1332 winMsg->lParam |= 0; // todo
1333
1334 if( ulIMR & IMR_RESULT_RESULTCLAUSE )
1335 winMsg->lParam |= GCS_RESULTCLAUSE_W;
1336
1337 if( ulIMR & IMR_RESULT_READINGSTRING )
1338 winMsg->lParam |= GCS_RESULTREADSTR_W;
1339
1340 if( ulIMR & IMR_RESULT_READINGATTR )
1341 winMsg->lParam |= 0; // todo
1342
1343 if( ulIMR & IMR_RESULT_READINGCLAUSE )
1344 winMsg->lParam |= GCS_RESULTREADCLAUSE_W;
1345
1346 if( ulIMR && ( winMsg->lParam == 0 ))
1347 goto dummymessage;
1348 break;
1349 }
1350
1351 case IMR_CANDIDATE :
1352 winMsg->message = WM_IME_NOTIFY_W;
1353 switch(( ULONG )os2Msg->mp2 )
1354 {
1355 case IMR_CANDIDATE_SHOW :
1356 case IMR_CANDIDATE_HIDE :
1357 case IMR_CANDIDATE_SELECT :
1358 case IMR_CANDIDATE_CHANGE :
1359 case IMR_CANDIDATE_CANDIDATEPOS :
1360 default :
1361 // todo
1362 goto dummymessage;
1363 }
1364 break;
1365
1366 case IMR_INFOMSG :
1367 winMsg->message = WM_IME_NOTIFY_W;
1368 winMsg->wParam = IMN_GUIDELINE_W;
1369 break;
1370
1371 case IMR_REGWORD :
1372 goto dummymessage;
1373
1374 case IMR_IMECHANGE :
1375 winMsg->message = WM_IME_SELECT_W;
1376 // todo
1377 goto dummymessage;
1378
1379 case IMR_CONFIG :
1380 // todo
1381 goto dummymessage;
1382
1383 case IMR_DICTIONARY :
1384 // todo
1385 goto dummymessage;
1386
1387 case IMR_OTHERINFO :
1388 // todo
1389 goto dummymessage;
1390 }
1391 break;
1392
1393#if 0 // application cannot receive this message
1394 case WM_IMECONTROL:
1395#endif
1396 case WM_INITMENU:
1397 case WM_MENUSELECT:
1398 case WM_MENUEND:
1399 case WM_NEXTMENU:
1400 case WM_SYSCOLORCHANGE:
1401 case WM_SYSVALUECHANGED:
1402 case WM_SETSELECTION:
1403 case WM_PPAINT:
1404 case WM_PSETFOCUS:
1405 case WM_PSYSCOLORCHANGE:
1406 case WM_PSIZE:
1407 case WM_PACTIVATE:
1408 case WM_PCONTROL:
1409 case WM_HELP:
1410 case WM_APPTERMINATENOTIFY:
1411 case WM_PRESPARAMCHANGED:
1412 case WM_DRAWITEM:
1413 case WM_MEASUREITEM:
1414 case WM_CONTROLPOINTER:
1415 case WM_QUERYDLGCODE:
1416 case WM_SUBSTITUTESTRING:
1417 case WM_MATCHMNEMONIC:
1418 case WM_SAVEAPPLICATION:
1419 case WM_SEMANTICEVENT:
1420 default:
1421dummymessage:
1422 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
1423 winMsg->message = 0;
1424 winMsg->wParam = 0;
1425 winMsg->lParam = 0;
1426 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1427 return FALSE;
1428 }
1429msgdone:
1430 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1431 return TRUE;
1432}
1433//******************************************************************************
1434//******************************************************************************
1435BOOL OSLibWinTranslateMessage(MSG *msg)
1436{
1437 TEB *teb;
1438 MSG extramsg;
1439 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
1440 teb = GetThreadTEB();
1441 if(!teb)
1442 return FALSE;
1443
1444 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1445 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
1446
1447
1448 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1449 // the newly generated WM_CHAR message.
1450 if(!teb->o.odin.fTranslated &&
1451 teb->o.odin.os2msg.msg == WM_CHAR &&
1452 !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
1453 {
1454 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
1455 memcpy(&extramsg, msg, sizeof(MSG));
1456 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1457 extramsg.lParam = 0;
1458
1459 // ESCAPE generates a WM_CHAR under windows, so take
1460 // special care for this here.
1461 switch (ucPMScanCode)
1462 {
1463 case PMSCAN_ESC:
1464 extramsg.wParam = VK_ESCAPE_W;
1465 fl |= KC_CHAR;
1466 break;
1467 }
1468
1469 // PF With NumLock off do not generate any WM_CHAR messages at all
1470 // PADMINUS,PADPLUS fall in range of PAD7..PADPERIOD but they should generate WM_CHAR
1471 // other PAD(X) buttons miss that range at all and thus generate WM_CHAR
1472 if (!numPressed && (ucPMScanCode != PMSCAN_PADMINUS) && (ucPMScanCode != PMSCAN_PADPLUS) &&
1473 (ucPMScanCode >= PMSCAN_PAD7) && (ucPMScanCode <= PMSCAN_PADPERIOD))
1474 return FALSE;
1475
1476 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1477 {
1478 return FALSE;
1479 }
1480
1481 //the KC_COMPOSITE flag might be set; in that case this key will
1482 //be combined with the previous dead key, so we must use the scancode
1483 //(e.g. ^ on german keyboards)
1484 if((fl & (KC_VIRTUALKEY|KC_COMPOSITE)) == KC_VIRTUALKEY)
1485 {
1486 if(!msg->wParam)
1487 {//TODO: Why is this here????
1488 DebugInt3();
1489 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1490 }
1491 }
1492
1493 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1494 if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
1495 extramsg.message = WINWM_SYSCHAR;
1496 else
1497 extramsg.message = WINWM_CHAR;
1498
1499 if(fl & KC_DEADKEY)
1500 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1501
1502
1503 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1504 if ((fl & KC_ALT) || (msg->lParam & WIN_KEY_ALTHELD))
1505 extramsg.lParam |= WIN_KEY_ALTHELD;
1506 if(fl & KC_PREVDOWN)
1507 extramsg.lParam |= WIN_KEY_PREVSTATE;
1508 if(fl & KC_KEYUP)
1509 extramsg.lParam |= (1<<31);
1510
1511 // insert message into the queue
1512 setThreadQueueExtraCharMessage(teb, &extramsg);
1513
1514 return TRUE;
1515 }
1516 return FALSE;
1517}
1518//******************************************************************************
1519//******************************************************************************
1520
1521/**
1522 * Checks if the message is one that should be forwarded.
1523 *
1524 * @returns True if the message should be forwarded.
1525 * @returns False if the message doesn't fall in to that group.
1526 * @param pMsg Message to examin.
1527 * @remark Are there more messages???
1528 */
1529BOOL OSLibForwardableMessage(const MSG *pMsg)
1530{
1531 return ( (pMsg->message >= WINWM_KEYFIRST && pMsg->message <= WINWM_KEYLAST)
1532 || (pMsg->message >= WINWM_MOUSEFIRST && pMsg->message <= WINWM_MOUSELAST) );
1533}
1534
1535/**
1536 * Forwards this message to the attached thread if it's in the group of messages
1537 * which is supposed to be forwarded.
1538 *
1539 * @returns True if forwarded.
1540 * @returns False if not forwarded.
1541 * @param pTeb Pointer to the TEB of the current thread.
1542 * @param pMsg Message to forward.
1543 * @author knut st. osmundsen <bird-srcspam@anduin.net>
1544 */
1545BOOL OSLibForwardMessageToAttachedThread(void *pvTeb, MSG *pMsg, void *hmm)
1546{
1547 TEB *pTeb = (TEB *)pvTeb;
1548 dprintf(("OSLibForwardMessageToAttachedThread: %p %p (msg=%x)\n", pvTeb, pMsg, pMsg->message));
1549 if (!OSLibForwardableMessage(pMsg))
1550 return FALSE;
1551
1552 /*
1553 * Find the actual receiver thread.
1554 */
1555 int c = 100;
1556 TEB *pTebTo = pTeb;
1557 do
1558 {
1559 pTebTo = GetTEBFromThreadId(pTebTo->o.odin.tidAttachedInputThread);
1560 } while (c-- > 0 && !pTebTo && pTebTo->o.odin.tidAttachedInputThread);
1561 if (!c || !pTebTo)
1562 {
1563 if (c) dprintf(("OSLibForwardMessageToAttachedThread: The receiver thread is dead or non existing.\n"));
1564 else dprintf(("OSLibForwardMessageToAttachedThread: threads are attached in looooop.\n"));
1565 return FALSE; /* hmm.... */
1566 }
1567 dprintf(("OSLibForwardMessageToAttachedThread: Forwarding message %#x to %#x\n",
1568 pMsg->message, pTeb->o.odin.tidAttachedInputThread));
1569
1570 /*
1571 * Pack down the message into shared memory.
1572 */
1573 MSG *pMsgCopy = (MSG *)_smalloc(sizeof(MSG));
1574 if (!pMsgCopy)
1575 return FALSE;
1576 *pMsgCopy = *pMsg;
1577
1578 /*
1579 * Figure out how we should send the message.
1580 */
1581 if (WinInSendMsg(pTebTo->o.odin.hab))
1582 {
1583#if 0
1584 /*
1585 * Hmm what do we do here....
1586 */
1587 MRESULT rc = WinSendQueueMsg(pTebTo->o.odin.hmq, /*special! */, pMsgCopy, /*magic*/ );
1588 /* if (hmmSendMsgResult)
1589 *hmmSendMsgResult = (???)rc; */
1590#else
1591 dprintf(("OSLibForwardMessage: ERROR! %x in sendmsg!!!\n", pMsg->message));
1592 DebugInt3();
1593
1594 _sfree(pMsgCopy);
1595 return FALSE;
1596#endif
1597 }
1598 else
1599 {
1600 if (!WinPostQueueMsg(pTebTo->o.odin.hmq, WIN32APP_FORWARDEDPOSTMSG, pMsgCopy, (MPARAM)WIN32APP_FORWARDEDPOSTMSG_MAGIC))
1601 {
1602 dprintf(("OSLibForwardMessage: Failed to post queue message to hmq=%#x\n", pTebTo->o.odin.hmq));
1603 _sfree(pMsgCopy);
1604 }
1605 }
1606
1607 return TRUE;
1608}
Note: See TracBrowser for help on using the repository browser.