source: trunk/src/user32/oslibmsgtranslate.cpp

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

Merge branch gcc-kmk to trunk.

File size: 53.4 KB
RevLine 
[10607]1/* $Id: oslibmsgtranslate.cpp,v 1.125 2004-05-24 09:01:59 sandervl Exp $ */
[2469]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 */
[21308]17#define INCL_NLS
18#define INCL_GPI
[2469]19#define INCL_WIN
20#define INCL_PM
21#define INCL_DOSPROCESS
22#include <os2wrap.h>
23#include <string.h>
24#include <misc.h>
[3101]25#include <winconst.h>
[5404]26#include <win32api.h>
[2469]27#include "oslibmsg.h"
[4848]28#include <winuser32.h>
[2469]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"
[2956]36#include "winmouse.h"
[7155]37#include <pmkbdhk.h>
[7166]38#include <pmscan.h>
[7205]39#include <winscan.h>
[7212]40#include <winkeyboard.h>
[10189]41#include <winnls.h>
[10190]42#include <heapstring.h>
[8347]43#include "hook.h"
[9791]44#include "user32api.h"
[2469]45
[21308]46#include <os2im.h>
47#include <im32.h>
[9935]48
[2956]49#define DBG_LOCALLOG DBG_oslibmsgtranslate
[2804]50#include "dbglocal.h"
51
[7195]52static BOOL fGenerateDoubleClick = FALSE;
53static MSG doubleClickMsg = {0};
54
[21916]55extern "C" UINT WINAPI GetACP(void); // from winnls.h
56extern "C" UINT WIN32API clipboardPMToOdinFormat(ULONG ulPMFormat);
[21308]57
[9230]58//For wheel mouse translation
59#define WHEEL_DELTA 120
[9258]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
[10012]63//we will possibly detect mouse driver and use correction if speed will be
[9258]64//too high or too low.
[10012]65
[2469]66//******************************************************************************
[10189]67//
68// setThreadQueueExtraCharMessage: queues WM_CHAR message so it is retrieved
69// by GetMessage & PeekMessage
70//
[10212]71// NOTE: WM_CHAR message always in ascii format
[10189]72//
[2469]73//******************************************************************************
[7205]74BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
75{
[10430]76 if ( teb->o.odin.tidAttachedInputThread
77 && OSLibForwardMessageToAttachedThread(teb, pExtraMsg, NULL))
78 return TRUE;
79
[7205]80 // check if the single slot is occupied already
[10275]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 }
[10189]86
[7205]87 teb->o.odin.fTranslated = TRUE;
88 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
89 return TRUE;
90}
91
92//******************************************************************************
93//******************************************************************************
[9897]94ULONG ConvertNumPadKey(ULONG pmScan)
95{
96 ULONG ret;
[21916]97 UCHAR winKey;
[9897]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 }
[10012]114
[21916]115 KeyTranslatePMScanToWinVKey(ret, FALSE, &winKey, NULL, NULL);
[9897]116 return winKey;
117
118}
119//******************************************************************************
120//******************************************************************************
[2469]121LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
122{
123 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
124}
125//******************************************************************************
126//******************************************************************************
[9598]127void OSLibSetMenuDoubleClick(BOOL fSet)
[7195]128{
129 fGenerateDoubleClick = fSet;
130}
131//******************************************************************************
[10012]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
[7195]168//******************************************************************************
[4658]169BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
[2469]170{
171 Win32BaseWindow *win32wnd = 0;
172 OSLIBPOINT point, ClientPoint;
173 POSTMSG_PACKET *packet;
[4658]174 TEB *teb = (TEB *)pTeb;
[3388]175 BOOL fWasDisabled = FALSE;
[5713]176 BOOL fIsFrame = FALSE;
[2469]177 int i;
178
[10430]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
[5685]194 memset(winMsg, 0, sizeof(MSG));
195 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
196 if(!win32wnd) {
197 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
[5713]198 if(win32wnd) {
199 fIsFrame = TRUE;
200 }
[5685]201 }
[2469]202
[5685]203 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
204 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
[5805]205 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
[5685]206 {
[2469]207 goto dummymessage; //not a win32 client window
[5685]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);
[2469]213
[5685]214 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
215 winMsg->hwnd = win32wnd->getWindowHandle();
[2469]216
[5805]217 if(os2Msg->msg >= WIN32APP_POSTMSG) {
[2469]218 packet = (POSTMSG_PACKET *)os2Msg->mp2;
219 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
[5805]220 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
[2469]221 winMsg->wParam = packet->wParam;
222 winMsg->lParam = packet->lParam;
[10012]223 if (fMsgRemoved == MSG_REMOVE)
[21341]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 }
[5935]236 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
[5805]237 return TRUE;
[2469]238 }
[5805]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;
[5935]243 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
[5805]244 return TRUE;
245 }
[2469]246 goto dummymessage;
247 }
248
[5805]249 switch(os2Msg->msg)
250 {
[2469]251 //OS/2 msgs
252 case WM_CREATE:
253 {
[4658]254 if(teb->o.odin.newWindow == 0) {
[2469]255 DebugInt3();
256 goto dummymessage;
257 }
258
[4658]259 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
[5935]260 win32wnd->addRef();
[2469]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;
[8129]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 }
[2469]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
[9765]296 case WM_REALIZEPALETTE:
297 winMsg->message = WINWM_PALETTECHANGED;
298 break;
299
[2469]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
[5713]308 if(!fIsFrame) goto dummymessage;
309
[2469]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 }
[3662]320 if(win32wnd->getParent()) {
[5685]321 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
[3662]322 win32wnd->getOS2WindowHandle());
[5382]323 }
[5685]324 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
[2469]325
326 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
327
[5713]328 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
329 {
[4658]330 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
[2483]331 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
332 {
333 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
[5935]334 if(wndAfter) {
[5382]335 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
[5935]336 RELEASE_WNDOBJ(wndAfter);
337 }
[5382]338 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
[2483]339 }
[2469]340 }
[3662]341 winMsg->message = WINWM_WINDOWPOSCHANGED;
[4658]342 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
[3662]343 break;
[2469]344 }
345
346 case WM_ACTIVATE:
347 {
348 HWND hwndActivate = (HWND)os2Msg->mp2;
349 BOOL fMinimized = FALSE;
350
[4848]351 hwndActivate = OS2ToWin32Handle(hwndActivate);
[5382]352 if(hwndActivate == 0) {
[5685]353 //another (non-win32) application's window
354 //set to desktop window handle
355 hwndActivate = windowDesktop->getWindowHandle();
[5382]356 }
[2469]357
[3662]358 if(win32wnd->getStyle() & WS_MINIMIZE_W)
[2469]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 }
[4848]378 else hwndFocus = OS2ToWin32Handle(hwndFocus);
[2469]379
380 if((ULONG)os2Msg->mp2 == TRUE) {
[9792]381 winMsg->message = WINWM_SETFOCUS;
382 winMsg->wParam = (WPARAM)hwndFocus;
[2469]383 }
384 else {
[9792]385 //If SetFocus(0) was called, then the window has already received
386 //a WM_KILLFOCUS; don't send another one
387 if(!fIgnoreKeystrokes) {
[2469]388 winMsg->message = WINWM_KILLFOCUS;
389 winMsg->wParam = (WPARAM)hwndFocus;
[9792]390 }
391 else {
392 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
393 goto dummymessage;
394 }
[2469]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:
[5404]411 {
[2469]412 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
413
[7195]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
[5404]416 HWND hwnd;
417
[5413]418 DisableLogging();
[5685]419 if(GetCapture() != winMsg->hwnd)
[5435]420 {
421 hwnd = WindowFromPoint(winMsg->pt);
422 if(win32wnd->getWindowHandle() != hwnd) {
[5935]423 RELEASE_WNDOBJ(win32wnd);
[5435]424 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
425 if(win32wnd == NULL) {
426 DebugInt3();
427 EnableLogging();
428 goto dummymessage;
429 }
430 winMsg->hwnd = hwnd;
[5404]431 }
432 }
[3603]433
[9020]434 //if a window is disabled, its parent receives the mouse messages
[5586]435 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
[5404]436 if(win32wnd->getParent()) {
[5935]437 Win32BaseWindow *parent = win32wnd->getParent();;
438 if(parent) parent->addRef();
439 RELEASE_WNDOBJ(win32wnd);
440 win32wnd = parent;
[5404]441 }
442 fWasDisabled = TRUE;
[5382]443 }
[3388]444
[2469]445 if(IsNCMouseMsg(win32wnd)) {
446 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
[3284]447 winMsg->wParam = win32wnd->getLastHitTestVal();
[2469]448 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
449 }
450 else {
[5404]451 ClientPoint.x = winMsg->pt.x;
452 ClientPoint.y = winMsg->pt.y;
453 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
[2469]454 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
455 winMsg->wParam = GetMouseKeyState();
456 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
457 }
[5413]458 EnableLogging();
[2469]459
[5382]460 if(fWasDisabled) {
[5404]461 if(win32wnd) {
462 winMsg->hwnd = win32wnd->getWindowHandle();
463 }
464 else goto dummymessage; //don't send mouse messages to disabled windows
[5382]465 }
[7195]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 {
[10012]475 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
[7195]476 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
477 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
[10012]478 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
[7195]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);
[9598]485 if(fMsgRemoved) doubleClickMsg.message = 0;
[7195]486 }
487 else {
488 dprintf(("save for double click"));
[9598]489 if(fMsgRemoved) {
490 doubleClickMsg = *winMsg;
491 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
492 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
493 }
[7195]494 }
495 }
496 }
497 EnableLogging();
498
[8347]499 if(fMsgRemoved == MSG_REMOVE)
500 {
501 MSLLHOOKSTRUCT hook;
[8380]502 ULONG msg;
[8347]503
[8380]504 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
505 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
506 }
507 else msg = winMsg->message;
[10012]508
[8380]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
[10501]521 // First the low-level mouse hook
[10505]522 hook.pt = winMsg->pt;
[8347]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
[8380]528 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
[8347]529 goto dummymessage; //hook swallowed message
530 }
[10505]531 }
532 MOUSEHOOKSTRUCT mousehk;
[10501]533
[10505]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;
[10501]539
[10505]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
[8347]543 }
[2469]544 break;
[5404]545 }
[2469]546
[5236]547 case WM_BUTTON2CLICK:
548 case WM_BUTTON1CLICK:
549 case WM_BUTTON3CLICK:
550 goto dummymessage;
551
[2469]552 case WM_BUTTON2MOTIONSTART:
553 case WM_BUTTON2MOTIONEND:
554 case WM_BUTTON1MOTIONSTART:
555 case WM_BUTTON1MOTIONEND:
556 case WM_BUTTON3MOTIONSTART:
557 case WM_BUTTON3MOTIONEND:
[5236]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
[2469]561
562 case WM_MOUSEMOVE:
563 {
564 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
565
[5404]566 HWND hwnd;
567
[8702]568 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
[5413]569 DisableLogging();
[5685]570 if(GetCapture() != winMsg->hwnd)
[5435]571 {
572 hwnd = WindowFromPoint(winMsg->pt);
573 if(win32wnd->getWindowHandle() != hwnd) {
[5935]574 RELEASE_WNDOBJ(win32wnd);
[5435]575 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
576 if(win32wnd == NULL) {
577 DebugInt3();
578 EnableLogging();
579 goto dummymessage;
580 }
581 winMsg->hwnd = hwnd;
[5404]582 }
583 }
[3603]584
[9020]585 //if a window is disabled, its parent receives the mouse messages
[5586]586 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
[5404]587 if(win32wnd->getParent()) {
[5935]588 Win32BaseWindow *parent = win32wnd->getParent();;
589 if(parent) parent->addRef();
590 RELEASE_WNDOBJ(win32wnd);
591 win32wnd = parent;
[5404]592 }
593 fWasDisabled = TRUE;
[5382]594 }
[2469]595 if(IsNCMouseMsg(win32wnd))
596 {
[5404]597 winMsg->message = WINWM_NCMOUSEMOVE;
598 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
599 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
[2483]600 }
[2469]601 else
602 {
[5404]603 ClientPoint.x = winMsg->pt.x;
604 ClientPoint.y = winMsg->pt.y;
605 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
[3662]606
[5404]607 winMsg->message = WINWM_MOUSEMOVE;
608 winMsg->wParam = GetMouseKeyState();
609 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
[2469]610 }
[5413]611 EnableLogging();
[8347]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 }
[10505]620 MSLLHOOKSTRUCT hook;
[8347]621 if(fMsgRemoved == MSG_REMOVE)
[2956]622 {
[10505]623 hook.pt = winMsg->pt;
[8347]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
[3108]631 }
[2956]632 }
[10505]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
[10595]641 if(HOOK_CallHooksW( WH_MOUSE_W, (fMsgRemoved == MSG_REMOVE) ? HC_ACTION : HC_NOREMOVE, winMsg->message, (LPARAM)&mousehk))
[10505]642 {
643 goto dummymessage; //hook swallowed message
644 }
[2469]645 break;
646 }
647
648 case WM_CONTROL:
[8347]649 goto dummymessage;
[2469]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:
[6718]676 {
[6745]677 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
678 //TRUE -> user clicked on close button -> close window
[10012]679 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
[6745]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;
[6718]690 }
691 }
[2469]692 win32sc = SC_CLOSE_W;
693 break;
[6718]694 }
[2469]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;
[10017]711 case SC_SYSMENU:
712 win32sc = SC_KEYMENU_W; //??
713 break;
[2469]714 default:
[6008]715 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
[2469]716 goto dummymessage;
717 }
[6718]718 winMsg->message= WINWM_SYSCOMMAND;
[2469]719 winMsg->wParam = (WPARAM)win32sc;
720 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
721 break;
722 }
[9814]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 }
[10012]730
[7155]731 case WM_CHAR_SPECIAL:
[7191]732 {
[7155]733 // @@@PH
734 // special char message from the keyboard hook
[9814]735 if(os2Msg->msg == WM_CHAR_SPECIAL) {
736 dprintf(("PM: WM_CHAR_SPECIAL"));
737 }
[7205]738 // NO BREAK! FALLTHRU CASE!
739 }
[10012]740
[2469]741 case WM_CHAR:
742 {
[7221]743 ULONG repeatCount=0;
744 ULONG virtualKey=0;
745 ULONG keyFlags=0;
746 USHORT scanCode=0;
747 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
[7620]748 BOOL keyWasPressed;
[10012]749 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
[7221]750 char c;
751 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
[2469]752
[7620]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);
[2469]757
[9897]758 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
[7211]759 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
[9897]760
[7212]761 BOOL fWinExtended;
[21916]762 UCHAR uchWinVKey;
[7212]763 WORD wWinScan;
[7216]764
[10216]765 if ( (!IsDBCSEnv() && scanCode == 0) ||
766 (scanCode==0 ) && !( flags & KC_CHAR ) )
[10190]767 {
768 goto dummymessage;
769 }
[7896]770
[10190]771 if( scanCode != 0 )
772 {
[21308]773 switch( SHORT2FROMMP( os2Msg->mp2 ))
774 {
775 // for Korean
776 case VK_DBE_HANJA :
[21916]777 uchWinVKey = 0x19;
[21308]778 break;
779
780 case VK_DBE_HANGEUL :
[21916]781 uchWinVKey = 0x15;
[21308]782 break;
783
784 case VK_DBE_JAMO :
[21916]785 uchWinVKey = 0;
[21308]786 break;
787
788 // for Japan
789 case VK_DBE_KATAKANA :
[21916]790 uchWinVKey = 0;
[21308]791 break;
792
793 case VK_DBE_HIRAGANA :
[21916]794 uchWinVKey = 0;
[21308]795 break;
796
797 case VK_DBE_SBCSCHAR :
[21916]798 uchWinVKey = 0;
[21308]799 break;
800
801 case VK_DBE_DBCSCHAR :
[21916]802 uchWinVKey = 0;
[21308]803 break;
804
805 case VK_DBE_SBCSDBCSCHAR :
[21916]806 uchWinVKey = 0;
[21308]807 break;
808
809 case VK_DBE_ROMAN :
[21916]810 uchWinVKey = 0;
[21308]811 break;
812
813 // for PRC-Chinese
814 case VK_DBE_HANZI :
[21916]815 uchWinVKey = 0;
[21308]816 break;
817
818 // for Taiwan
819 case VK_DBE_TSANGJYE :
[21916]820 uchWinVKey = 0;
[21308]821 break;
822
823 case VK_DBE_PHONETIC :
[21916]824 uchWinVKey = 0;
[21308]825 break;
826
827 case VK_DBE_CONV :
[21916]828 uchWinVKey = 0;
[21308]829 break;
830
831 case VK_DBE_NOCONV :
[21916]832 uchWinVKey = 0;
[21308]833 break;
834
835 case VK_DBE_ALPHANUMERIC :
836 switch( GetACP())
837 {
838 case 949 : // Korea
839 case 1361 :
[21916]840 uchWinVKey = 0x15;
[21308]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 :
[21916]852 uchWinVKey = 0;
[21308]853 }
854 break;
855
856 default :
[10607]857 KeyTranslatePMScanToWinVKey(usPMScanCode,
858 FALSE,
[21916]859 &uchWinVKey,
[10607]860 &wWinScan,
861 &fWinExtended);
[21308]862 }
863
[21916]864 winMsg->wParam = uchWinVKey;
[10190]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 {
[10216]877 CHAR dbcsCh[ 2 ] = { CHAR1FROMMP( os2Msg->mp2 ), CHAR2FROMMP( os2Msg->mp2 )};
878
[10190]879 if( isUnicode )
880 {
[10216]881 WCHAR uniChar;
[10190]882
[10216]883 MultiByteToWideChar( CP_ACP, 0, dbcsCh, 2, &uniChar, 1 );
884 winMsg->wParam = ( WPARAM )uniChar;
[10190]885 }
[10216]886 else
887 winMsg->wParam = ( dbcsCh[ 0 ] << 8 ) | dbcsCh[ 1 ];
[10190]888 }
889 }
[2469]890 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
[7212]891 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
[10012]892
[7213]893 // Set the extended bit when appropriate
894 if (fWinExtended)
[7612]895 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
[2469]896
[10012]897 //PF When we press shift we enable non-numeric functions of Numpad
[9924]898 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
[9897]899 winMsg->wParam = ConvertNumPadKey(scanCode);
[3127]900
[9200]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;
[9791]912
913 //After SetFocus(0), all keystrokes are converted in WM_SYS*
914 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
915
[9200]916 setThreadQueueExtraCharMessage(teb, &extramsg);
917 // and finally adjust our WM_KEYDOWN code
918 winMsg->lParam = 0x01460001;
919 }
[10012]920
[6254]921 if (!(flags & KC_ALT))
[2469]922 {
[7164]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 ...
[9814]930 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
[7164]931 if ( (flags & KC_LONEKEY) &&
[9814]932 (winMsg->wParam == VK_LMENU_W) )
[7164]933 {
934 winMsg->message = WINWM_SYSKEYUP;
935 // held ALT-key when current key is released
936 // generates additional flag 0x2000000
[10012]937 // Note: PM seems to do this differently,
[7164]938 // KC_ALT is already reset
[2469]939 }
[7164]940 else
941 {
942 // send WM_KEYUP message
943 winMsg->message = WINWM_KEYUP;
[2469]944 }
[7612]945 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
[7164]946 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
[7866]947 }
[10190]948 else if( scanCode == 0 )
949 {
[10216]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 }
[10190]957 }
[10012]958 else
[7866]959 { // send WM_KEYDOWN message
960 winMsg->message = WINWM_KEYDOWN;
[8566]961
[7866]962 if (keyWasPressed)
963 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
[10012]964
[7837]965 //Shift-Enter and possibly others need to have special handling
[7866]966 if (flags & KC_SHIFT)
967 {
[7837]968 if(fMsgRemoved && !(teb->o.odin.fTranslated))
[10012]969 {
[7837]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));
[10012]975
[9791]976 //After SetFocus(0), all keystrokes are converted in WM_SYS*
977 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
[7837]978
979 // insert message into the queue
980 setThreadQueueExtraCharMessage(teb, &extramsg);
981 winMsg->lParam &= 0x3FFFFFFF;
982 }
983 } // else ???
984 } // KC_SHIFT
[7866]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));
[10012]993
[9791]994 //After SetFocus(0), all keystrokes are converted in WM_SYS*
995 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
[7866]996
997 // insert message into the queue
998 setThreadQueueExtraCharMessage(teb, &extramsg);
999 }
1000 }
[7164]1001 }
[8566]1002 // if right alt is down, then we need to set the alt down bit too
[9814]1003 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
[10012]1004 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
1005 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
[9814]1006 {
[10012]1007 winMsg->lParam |= WIN_KEY_ALTHELD;
[8566]1008 }
[2469]1009 }
[10012]1010 else
[7164]1011 {
1012 //
1013 // the Alt key is pressed
1014 //
1015 if (flags & KC_KEYUP)
1016 {
[7891]1017 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
1018 winMsg->message = WINWM_SYSKEYUP;
[10012]1019 winMsg->lParam |= WIN_KEY_PREVSTATE;
[8474]1020 // No ALTHELD for Alt itself ;)
[10012]1021 winMsg->lParam |= WIN_KEY_ALTHELD;
1022 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
[7164]1023 }
[10012]1024 else
[7164]1025 {
1026 // send WM_SYSKEYDOWN message
1027 winMsg->message = WINWM_SYSKEYDOWN;
1028 if (keyWasPressed)
[7612]1029 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
[2469]1030
[7164]1031 // pressed ALT-key generates additional flag 0x2000000
1032 // if the current window has keyboard focus
[7612]1033 winMsg->lParam |= WIN_KEY_ALTHELD;
[7164]1034 }
[2469]1035 }
[10012]1036
[9791]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 }
[10012]1042 else
[9791]1043 if(winMsg->message == WINWM_KEYUP) {
1044 winMsg->message = WINWM_SYSKEYUP;
1045 }
1046 }
[2469]1047 break;
1048 }
1049
1050 case WM_TIMER:
[6101]1051//Why was this check here????
1052// if (os2Msg->mp2)
1053// {
[2469]1054 BOOL sys;
[10104]1055 ULONG id, proc;
[2469]1056
[10104]1057 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
[2469]1058 {
1059 winMsg->wParam = (WPARAM)id;
[10104]1060 winMsg->lParam = (LPARAM)proc;
[2469]1061 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
1062 break;
1063 }
[6101]1064// }
[2469]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 {
[2881]1103 if(win32wnd->IsWindowIconic()) {
[2469]1104 winMsg->message = WINWM_PAINTICON;
1105 }
1106 else winMsg->message = WINWM_PAINT;
1107 break;
1108 }
1109
1110 case WM_CONTEXTMENU:
[2483]1111 winMsg->message = WINWM_CONTEXTMENU;
1112 winMsg->wParam = win32wnd->getWindowHandle();
1113 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
1114 break;
1115
[4599]1116 case WM_RENDERFMT:
1117 winMsg->message = WINWM_RENDERFORMAT;
[21303]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 }
[4599]1124 break;
1125
1126 case WM_RENDERALLFMTS:
1127 winMsg->message = WINWM_RENDERALLFORMATS;
1128 break;
1129
[4658]1130 case WM_DESTROYCLIPBOARD:
1131 winMsg->message = WINWM_DESTROYCLIPBOARD;
1132 break;
1133
[8962]1134 case WM_DRAWCLIPBOARD:
1135 winMsg->message = WINWM_DRAWCLIPBOARD;
1136 break;
1137
[6337]1138 case WM_HSCROLL:
1139 case WM_VSCROLL:
[9230]1140 //PF For win32 we support only vertical scrolling for WM_MOUSEWHEEL
[9258]1141 if (os2Msg->msg == WM_VSCROLL)
[9230]1142 {
[10012]1143 POINT CursorPoint;
[9230]1144 winMsg->message = WINWM_MOUSEWHEEL;
[9258]1145 if (OSLibWinQueryPointerPos(&CursorPoint))
1146 mapScreenPoint((OSLIBPOINT*)&CursorPoint);
[10012]1147
[9230]1148 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
[10012]1149 winMsg->wParam = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
[9230]1150 else
1151 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
[10012]1152 winMsg->wParam = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
[9258]1153 else
[10012]1154 winMsg->wParam = MAKELONG(GetMouseKeyState(), 0);
[9230]1155
[10012]1156 winMsg->lParam = MAKELONG(CursorPoint.x, CursorPoint.y);
[9258]1157
[10012]1158 dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
[9258]1159 if (fMsgRemoved == MSG_REMOVE)
1160 {
[10012]1161 MSLLHOOKSTRUCT hook;
[10505]1162 MOUSEHOOKSTRUCT mousehk;
[9258]1163
[10012]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
[9258]1172
[10012]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 }
[9258]1179 break;
[10012]1180 }
[9230]1181 goto dummymessage; //eat this message
[6337]1182 break;
1183
[21308]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
[2469]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:
[5606]1422 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
[3284]1423 winMsg->message = 0;
1424 winMsg->wParam = 0;
1425 winMsg->lParam = 0;
[5935]1426 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
[2469]1427 return FALSE;
[5685]1428 }
[9944]1429msgdone:
[5935]1430 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
[5685]1431 return TRUE;
[2469]1432}
1433//******************************************************************************
1434//******************************************************************************
1435BOOL OSLibWinTranslateMessage(MSG *msg)
1436{
[7216]1437 TEB *teb;
1438 MSG extramsg;
[10012]1439 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
[7216]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);
[10012]1446
1447
[2469]1448 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1449 // the newly generated WM_CHAR message.
[7216]1450 if(!teb->o.odin.fTranslated &&
[10012]1451 teb->o.odin.os2msg.msg == WM_CHAR &&
[7216]1452 !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
[7211]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;
[2469]1458
[7211]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 }
[10012]1468
[9924]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))
[10012]1474 return FALSE;
[2469]1475
[10012]1476 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
[7211]1477 {
[10554]1478 return FALSE;
[7211]1479 }
[2469]1480
[9584]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)
[9897]1484 if((fl & (KC_VIRTUALKEY|KC_COMPOSITE)) == KC_VIRTUALKEY)
[7211]1485 {
[10554]1486 if(!msg->wParam)
[10595]1487 {//TODO: Why is this here????
[10554]1488 DebugInt3();
1489 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
[7211]1490 }
1491 }
[3747]1492
[9791]1493 //After SetFocus(0), all keystrokes are converted in WM_SYS*
[10012]1494 if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
[7211]1495 extramsg.message = WINWM_SYSCHAR;
[10012]1496 else
[7211]1497 extramsg.message = WINWM_CHAR;
[2469]1498
[7211]1499 if(fl & KC_DEADKEY)
1500 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1501
1502
1503 extramsg.lParam = msg->lParam & 0x00FFFFFF;
[8474]1504 if ((fl & KC_ALT) || (msg->lParam & WIN_KEY_ALTHELD))
[7612]1505 extramsg.lParam |= WIN_KEY_ALTHELD;
[7211]1506 if(fl & KC_PREVDOWN)
[7612]1507 extramsg.lParam |= WIN_KEY_PREVSTATE;
[7211]1508 if(fl & KC_KEYUP)
1509 extramsg.lParam |= (1<<31);
1510
1511 // insert message into the queue
1512 setThreadQueueExtraCharMessage(teb, &extramsg);
[10189]1513
[7211]1514 return TRUE;
[2469]1515 }
1516 return FALSE;
1517}
1518//******************************************************************************
1519//******************************************************************************
1520
[10430]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.
[10451]1527 * @remark Are there more messages???
[10430]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.