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

Last change on this file since 10185 was 10185, checked in by sandervl, 22 years ago

Updates

File size: 40.3 KB
Line 
1/* $Id: oslibmsgtranslate.cpp,v 1.111 2003-07-28 11:27:46 sandervl Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Daniela Engert (dani@ngrt.de)
8 * Copyright 1999 Rene Pronk (R.Pronk@twi.tudelft.nl)
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 * TODO: Extra msgs: which messages must be put into the queue and which can be sent directly?
13 * (According to the docs TranslateMessage really inserts a msg in the queue)
14 * TODO: Filter translation isn't correct for posted messages
15 *
16 */
17#define INCL_WIN
18#define INCL_PM
19#define INCL_DOSPROCESS
20#include <os2wrap.h>
21#include <string.h>
22#include <misc.h>
23#include <winconst.h>
24#include <win32api.h>
25#include "oslibmsg.h"
26#include <winuser32.h>
27#include "win32wdesktop.h"
28#include "oslibutil.h"
29#include "timer.h"
30#include <thread.h>
31#include <wprocess.h>
32#include "pmwindow.h"
33#include "oslibwin.h"
34#include "winmouse.h"
35#include <pmkbdhk.h>
36#include <pmscan.h>
37#include <winscan.h>
38#include <winkeyboard.h>
39#include "hook.h"
40#include "user32api.h"
41
42
43#define DBG_LOCALLOG DBG_oslibmsgtranslate
44#include "dbglocal.h"
45
46static BOOL fGenerateDoubleClick = FALSE;
47static MSG doubleClickMsg = {0};
48
49//For wheel mouse translation
50#define WHEEL_DELTA 120
51#define OS2_WHEEL_CORRECTION 1
52//PF Correction is different for different mouse drivers. For now no correction
53//is ok because lots of Odin controls rely on minimum delta. However in future
54//we will possibly detect mouse driver and use correction if speed will be
55//too high or too low.
56
57//******************************************************************************
58//******************************************************************************
59BOOL setThreadQueueExtraCharMessage(TEB* teb, MSG* pExtraMsg)
60{
61 // check if the single slot is occupied already
62 if (teb->o.odin.fTranslated == TRUE)
63 // there's still an already translated message to be processed
64 return FALSE;
65 teb->o.odin.fTranslated = TRUE;
66 memcpy(&teb->o.odin.msgWCHAR, pExtraMsg, sizeof(MSG));
67 return TRUE;
68}
69
70//******************************************************************************
71//******************************************************************************
72ULONG ConvertNumPadKey(ULONG pmScan)
73{
74 ULONG ret;
75 BYTE winKey;
76
77 switch (pmScan)
78 {
79 case PMSCAN_PAD7: ret = PMSCAN_HOME; break;
80 case PMSCAN_PAD8: ret = PMSCAN_UP; break;
81 case PMSCAN_PAD9: ret = PMSCAN_PAGEUP; break;
82 case PMSCAN_PAD4: ret = PMSCAN_LEFT; break;
83 case PMSCAN_PAD6: ret = PMSCAN_RIGHT; break;
84 case PMSCAN_PAD1: ret = PMSCAN_END; break;
85 case PMSCAN_PAD2: ret = PMSCAN_DOWN; break;
86 case PMSCAN_PAD3: ret = PMSCAN_PAGEDOWN; break;
87 case PMSCAN_PAD0: ret = PMSCAN_INSERT; break;
88 case PMSCAN_PADPERIOD: ret = PMSCAN_DELETE; break;
89 default:
90 ret = pmScan;
91 }
92
93 KeyTranslatePMScanToWinVKey(ret, FALSE, (PBYTE)&winKey, NULL, NULL);
94 return winKey;
95
96}
97//******************************************************************************
98//******************************************************************************
99LONG IsNCMouseMsg(Win32BaseWindow *win32wnd)
100{
101 return ((win32wnd->getLastHitTestVal() != HTCLIENT_W) && (WinQueryCapture(HWND_DESKTOP) != win32wnd->getOS2WindowHandle()));
102}
103//******************************************************************************
104//******************************************************************************
105void OSLibSetMenuDoubleClick(BOOL fSet)
106{
107 fGenerateDoubleClick = fSet;
108}
109//******************************************************************************
110
111
112/**
113 * Inter process/thread packet cleanup.
114 * See OSLibPackMessage() for details on the packing.
115 *
116 * @param pTeb Pointer to the thread environment block for the current thread.
117 * @param pPacket Pointer to the packet in question.
118 * @param pWinMsg Pointer to the window message corresponding to the packet.
119 */
120inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
121{
122 switch (pWinMsg->message)
123 {
124 /*
125 * Place this in the TEB freeing any previous WM_COPYDATA packet.
126 * Note! Nested WM_COPYDATA isn't working.
127 */
128 case WINWM_COPYDATA:
129 {
130 dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
131 if (pTeb->o.odin.pWM_COPYDATA)
132 _sfree(pTeb->o.odin.pWM_COPYDATA);
133 pTeb->o.odin.pWM_COPYDATA = pPacket;
134 break;
135 }
136
137 /*
138 * Default packing - free the shared memory here.
139 */
140 default:
141 _sfree(pPacket);
142 break;
143 }
144}
145
146//******************************************************************************
147BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
148{
149 Win32BaseWindow *win32wnd = 0;
150 OSLIBPOINT point, ClientPoint;
151 POSTMSG_PACKET *packet;
152 TEB *teb = (TEB *)pTeb;
153 BOOL fWasDisabled = FALSE;
154 BOOL fIsFrame = FALSE;
155 int i;
156
157 memset(winMsg, 0, sizeof(MSG));
158 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(os2Msg->hwnd);
159 if(!win32wnd) {
160 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(os2Msg->hwnd);
161 if(win32wnd) {
162 fIsFrame = TRUE;
163 }
164 }
165
166 //PostThreadMessage posts WIN32APP_POSTMSG msg without window handle
167 //Realplayer starts a timer with hwnd 0 & proc 0; check this here
168 if(win32wnd == 0 && (os2Msg->msg != WM_CREATE && os2Msg->msg != WM_QUIT && os2Msg->msg != WM_TIMER && os2Msg->msg < WIN32APP_POSTMSG))
169 {
170 goto dummymessage; //not a win32 client window
171 }
172 winMsg->time = os2Msg->time;
173 //CB: PM bug or undocumented feature? ptl.x highword is set!
174 winMsg->pt.x = os2Msg->ptl.x & 0xFFFF;
175 winMsg->pt.y = mapScreenY(os2Msg->ptl.y);
176
177 if(win32wnd) //==0 for WM_CREATE/WM_QUIT
178 winMsg->hwnd = win32wnd->getWindowHandle();
179
180 if(os2Msg->msg >= WIN32APP_POSTMSG) {
181 packet = (POSTMSG_PACKET *)os2Msg->mp2;
182 if(packet && ((ULONG)os2Msg->mp1 == WIN32MSG_MAGICA || (ULONG)os2Msg->mp1 == WIN32MSG_MAGICW)) {
183 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
184 winMsg->wParam = packet->wParam;
185 winMsg->lParam = packet->lParam;
186 if (fMsgRemoved == MSG_REMOVE)
187 OSLibCleanupPacket(teb, packet, winMsg);
188 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
189 return TRUE;
190 }
191 else {//broadcasted message (no packet present)
192 winMsg->message = os2Msg->msg - WIN32APP_POSTMSG;
193 winMsg->wParam = (UINT)os2Msg->mp1;
194 winMsg->lParam = (DWORD)os2Msg->mp2;
195 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
196 return TRUE;
197 }
198 goto dummymessage;
199 }
200
201 switch(os2Msg->msg)
202 {
203 //OS/2 msgs
204 case WM_CREATE:
205 {
206 if(teb->o.odin.newWindow == 0) {
207 DebugInt3();
208 goto dummymessage;
209 }
210
211 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
212 win32wnd->addRef();
213
214 winMsg->message = WINWM_CREATE;
215 winMsg->hwnd = win32wnd->getWindowHandle();
216 winMsg->wParam = 0;
217 winMsg->lParam = (LPARAM)win32wnd->tmpcs;
218 break;
219 }
220
221 case WM_QUIT:
222 winMsg->message = WINWM_QUIT;
223 if (fMsgRemoved && win32wnd && (ULONG)os2Msg->mp2 != 0) {
224 // mp2 != 0 -> sent by window list; be nice and close
225 // the window first
226 win32wnd->MsgClose();
227 }
228 break;
229
230 case WM_CLOSE:
231 winMsg->message = WINWM_CLOSE;
232 break;
233
234 case WM_DESTROY:
235 winMsg->message = WINWM_DESTROY;
236 break;
237
238 case WM_ENABLE:
239 winMsg->message = WINWM_ENABLE;
240 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
241 break;
242
243 case WM_SHOW:
244 winMsg->message = WINWM_SHOWWINDOW;
245 winMsg->wParam = SHORT1FROMMP(os2Msg->mp1);
246 break;
247
248 case WM_REALIZEPALETTE:
249 winMsg->message = WINWM_PALETTECHANGED;
250 break;
251
252 case WM_WINDOWPOSCHANGED:
253 {
254 PSWP pswp = (PSWP)os2Msg->mp1;
255 SWP swpOld = *(pswp + 1);
256 HWND hParent = NULLHANDLE;
257 LONG yDelta = pswp->cy - swpOld.cy;
258 LONG xDelta = pswp->cx - swpOld.cx;
259
260 if(!fIsFrame) goto dummymessage;
261
262 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto dummymessage;
263
264 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
265 if (win32wnd->isChild()) {
266 if(win32wnd->getParent()) {
267 hParent = win32wnd->getParent()->getOS2WindowHandle();
268 }
269 else goto dummymessage; //parent has just been destroyed
270 }
271 }
272 if(win32wnd->getParent()) {
273 OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, win32wnd->getParent()->getClientHeight(),
274 win32wnd->getOS2WindowHandle());
275 }
276 else OSLibMapSWPtoWINDOWPOS(pswp, &teb->o.odin.wp, &swpOld, OSLibQueryScreenHeight(), win32wnd->getOS2WindowHandle());
277
278 if (!win32wnd->CanReceiveSizeMsgs()) goto dummymessage;
279
280 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
281 {
282 teb->o.odin.wp.hwnd = win32wnd->getWindowHandle();
283 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
284 {
285 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
286 if(wndAfter) {
287 teb->o.odin.wp.hwndInsertAfter = wndAfter->getWindowHandle();
288 RELEASE_WNDOBJ(wndAfter);
289 }
290 else teb->o.odin.wp.hwndInsertAfter = HWND_TOP_W;
291 }
292 }
293 winMsg->message = WINWM_WINDOWPOSCHANGED;
294 winMsg->lParam = (LPARAM)&teb->o.odin.wp;
295 break;
296 }
297
298 case WM_ACTIVATE:
299 {
300 HWND hwndActivate = (HWND)os2Msg->mp2;
301 BOOL fMinimized = FALSE;
302
303 hwndActivate = OS2ToWin32Handle(hwndActivate);
304 if(hwndActivate == 0) {
305 //another (non-win32) application's window
306 //set to desktop window handle
307 hwndActivate = windowDesktop->getWindowHandle();
308 }
309
310 if(win32wnd->getStyle() & WS_MINIMIZE_W)
311 {
312 fMinimized = TRUE;
313 }
314
315 winMsg->message = WINWM_ACTIVATE;
316 winMsg->wParam = MAKELONG((SHORT1FROMMP(os2Msg->mp1)) ? WA_ACTIVE_W : WA_INACTIVE_W, fMinimized);
317 winMsg->lParam = (LPARAM)hwndActivate;
318 break;
319 }
320
321 case WM_SETFOCUS:
322 {
323 HWND hwndFocus = (HWND)os2Msg->mp1;
324
325 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
326 //another (non-win32) application's window
327 //set to NULL (allowed according to win32 SDK) to avoid problems
328 hwndFocus = NULL;
329 }
330 else hwndFocus = OS2ToWin32Handle(hwndFocus);
331
332 if((ULONG)os2Msg->mp2 == TRUE) {
333 winMsg->message = WINWM_SETFOCUS;
334 winMsg->wParam = (WPARAM)hwndFocus;
335 }
336 else {
337 //If SetFocus(0) was called, then the window has already received
338 //a WM_KILLFOCUS; don't send another one
339 if(!fIgnoreKeystrokes) {
340 winMsg->message = WINWM_KILLFOCUS;
341 winMsg->wParam = (WPARAM)hwndFocus;
342 }
343 else {
344 dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
345 goto dummymessage;
346 }
347 }
348 break;
349 }
350
351 //**************************************************************************
352 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
353 //**************************************************************************
354 case WM_BUTTON1DOWN:
355 case WM_BUTTON1UP:
356 case WM_BUTTON1DBLCLK:
357 case WM_BUTTON2DOWN:
358 case WM_BUTTON2UP:
359 case WM_BUTTON2DBLCLK:
360 case WM_BUTTON3DOWN:
361 case WM_BUTTON3UP:
362 case WM_BUTTON3DBLCLK:
363 {
364 //WM_NC*BUTTON* is posted when the cursor is in a non-client area of the window
365
366 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));
367
368 HWND hwnd;
369
370 DisableLogging();
371 if(GetCapture() != winMsg->hwnd)
372 {
373 hwnd = WindowFromPoint(winMsg->pt);
374 if(win32wnd->getWindowHandle() != hwnd) {
375 RELEASE_WNDOBJ(win32wnd);
376 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
377 if(win32wnd == NULL) {
378 DebugInt3();
379 EnableLogging();
380 goto dummymessage;
381 }
382 winMsg->hwnd = hwnd;
383 }
384 }
385
386 //if a window is disabled, its parent receives the mouse messages
387 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
388 if(win32wnd->getParent()) {
389 Win32BaseWindow *parent = win32wnd->getParent();;
390 if(parent) parent->addRef();
391 RELEASE_WNDOBJ(win32wnd);
392 win32wnd = parent;
393 }
394 fWasDisabled = TRUE;
395 }
396
397 if(IsNCMouseMsg(win32wnd)) {
398 winMsg->message = WINWM_NCLBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
399 winMsg->wParam = win32wnd->getLastHitTestVal();
400 winMsg->lParam = MAKELONG(winMsg->pt.x, winMsg->pt.y); //screen coordinates
401 }
402 else {
403 ClientPoint.x = winMsg->pt.x;
404 ClientPoint.y = winMsg->pt.y;
405 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
406 winMsg->message = WINWM_LBUTTONDOWN + (os2Msg->msg - WM_BUTTON1DOWN);
407 winMsg->wParam = GetMouseKeyState();
408 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
409 }
410 EnableLogging();
411
412 if(fWasDisabled) {
413 if(win32wnd) {
414 winMsg->hwnd = win32wnd->getWindowHandle();
415 }
416 else goto dummymessage; //don't send mouse messages to disabled windows
417 }
418
419 DisableLogging();
420 if ((winMsg->message == WINWM_LBUTTONDOWN) ||
421 (winMsg->message == WINWM_RBUTTONDOWN) ||
422 (winMsg->message == WINWM_MBUTTONDOWN) ||
423 (winMsg->message == WINWM_NCLBUTTONDOWN) ||
424 (winMsg->message == WINWM_NCRBUTTONDOWN) ||
425 (winMsg->message == WINWM_NCMBUTTONDOWN))
426 {
427 if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
428 winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
429 (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
430 (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
431 {
432 dprintf(("single -> double click"));
433 if(winMsg->message >= WINWM_LBUTTONDOWN) {
434 winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_LBUTTONDOWN);
435 }
436 else winMsg->message += (WINWM_LBUTTONDBLCLK - WINWM_NCLBUTTONDOWN);
437 if(fMsgRemoved) doubleClickMsg.message = 0;
438 }
439 else {
440 dprintf(("save for double click"));
441 if(fMsgRemoved) {
442 doubleClickMsg = *winMsg;
443 if(doubleClickMsg.message >= WINWM_NCLBUTTONDOWN && doubleClickMsg.message <= WINWM_NCMBUTTONDOWN) {
444 doubleClickMsg.message += (WINWM_LBUTTONDOWN - WINWM_NCLBUTTONDOWN);
445 }
446 }
447 }
448 }
449 EnableLogging();
450
451 if(fMsgRemoved == MSG_REMOVE)
452 {
453 MSLLHOOKSTRUCT hook;
454 ULONG msg;
455
456 if(winMsg->message >= WINWM_NCLBUTTONDOWN && winMsg->message <= WINWM_NCMBUTTONDBLCLK) {
457 msg = winMsg->message - WINWM_NCLBUTTONDOWN + WINWM_LBUTTONDOWN;
458 }
459 else msg = winMsg->message;
460
461 if(msg == WINWM_LBUTTONDBLCLK) {
462 msg = WINWM_LBUTTONDOWN;
463 }
464 else
465 if(msg == WINWM_RBUTTONDBLCLK) {
466 msg = WINWM_RBUTTONDOWN;
467 }
468 else
469 if(msg == WINWM_MBUTTONDBLCLK) {
470 msg = WINWM_MBUTTONDOWN;
471 }
472
473 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
474 hook.pt.y = mapScreenY(os2Msg->ptl.y);
475 hook.mouseData = 0; //todo: XBUTTON1/2 (XP feature) or wheel data
476 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
477 hook.time = winMsg->time;
478 hook.dwExtraInfo = 0;
479
480 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, msg, (LPARAM)&hook)) {
481 goto dummymessage; //hook swallowed message
482 }
483 }
484 break;
485 }
486
487 case WM_BUTTON2CLICK:
488 case WM_BUTTON1CLICK:
489 case WM_BUTTON3CLICK:
490 goto dummymessage;
491
492 case WM_BUTTON2MOTIONSTART:
493 case WM_BUTTON2MOTIONEND:
494 case WM_BUTTON1MOTIONSTART:
495 case WM_BUTTON1MOTIONEND:
496 case WM_BUTTON3MOTIONSTART:
497 case WM_BUTTON3MOTIONEND:
498 //no break; translate to WM_MOUSEMOVE
499 //Some applications (e.g. Unreal) retrieve all mouse messages
500 //when a mouse button is pressed and don't expect WM_NULL
501
502 case WM_MOUSEMOVE:
503 {
504 //WM_NCMOUSEMOVE is posted when the cursor moves into a non-client area of the window
505
506 HWND hwnd;
507
508 dprintf2(("WM_MOUSEMOVE (%d,%d)", winMsg->pt.x, winMsg->pt.y));
509 DisableLogging();
510 if(GetCapture() != winMsg->hwnd)
511 {
512 hwnd = WindowFromPoint(winMsg->pt);
513 if(win32wnd->getWindowHandle() != hwnd) {
514 RELEASE_WNDOBJ(win32wnd);
515 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
516 if(win32wnd == NULL) {
517 DebugInt3();
518 EnableLogging();
519 goto dummymessage;
520 }
521 winMsg->hwnd = hwnd;
522 }
523 }
524
525 //if a window is disabled, its parent receives the mouse messages
526 if(!IsWindowEnabled(win32wnd->getWindowHandle())) {
527 if(win32wnd->getParent()) {
528 Win32BaseWindow *parent = win32wnd->getParent();;
529 if(parent) parent->addRef();
530 RELEASE_WNDOBJ(win32wnd);
531 win32wnd = parent;
532 }
533 fWasDisabled = TRUE;
534 }
535 if(IsNCMouseMsg(win32wnd))
536 {
537 winMsg->message = WINWM_NCMOUSEMOVE;
538 winMsg->wParam = (WPARAM)win32wnd->getLastHitTestVal();
539 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
540 }
541 else
542 {
543 ClientPoint.x = winMsg->pt.x;
544 ClientPoint.y = winMsg->pt.y;
545 MapWindowPoints(0, win32wnd->getWindowHandle(), (LPPOINT)&ClientPoint, 1);
546
547 winMsg->message = WINWM_MOUSEMOVE;
548 winMsg->wParam = GetMouseKeyState();
549 winMsg->lParam = MAKELONG(ClientPoint.x, ClientPoint.y); //client coordinates
550 }
551 EnableLogging();
552 if(fWasDisabled) {
553 if(win32wnd) {
554 winMsg->hwnd = win32wnd->getWindowHandle();
555 }
556 else {
557 goto dummymessage; //don't send mouse messages to disabled windows
558 }
559 }
560 if(fMsgRemoved == MSG_REMOVE)
561 {
562 MSLLHOOKSTRUCT hook;
563
564 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
565 hook.pt.y = mapScreenY(os2Msg->ptl.y);
566 hook.mouseData = 0;
567 hook.flags = 0; //todo: injected (LLMHF_INJECTED)
568 hook.time = winMsg->time;
569 hook.dwExtraInfo = 0;
570
571 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, winMsg->message, (LPARAM)&hook)) {
572 goto dummymessage; //hook swallowed message
573 }
574 }
575 break;
576 }
577
578 case WM_CONTROL:
579 goto dummymessage;
580
581 case WM_COMMAND:
582 if(SHORT1FROMMP(os2Msg->mp2) == CMDSRC_MENU) {
583 winMsg->message = WINWM_COMMAND;
584 winMsg->wParam = (WPARAM)SHORT1FROMMP(os2Msg->mp1); //id
585 break;
586 }
587 //todo controls
588 goto dummymessage;
589
590 case WM_SYSCOMMAND:
591 {
592 ULONG x = 0, y = 0;
593 ULONG win32sc;
594
595 if(SHORT2FROMMP(os2Msg->mp2) == TRUE) {//syscommand caused by mouse action
596 POINTL pointl;
597 WinQueryPointerPos(HWND_DESKTOP, &pointl);
598 x = pointl.x;
599 y = mapScreenY(y);
600 }
601 switch(SHORT1FROMMP(os2Msg->mp1)) {
602 case SC_MOVE:
603 win32sc = SC_MOVE_W;
604 break;
605 case SC_CLOSE:
606 {
607 //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
608 //TRUE -> user clicked on close button -> close window
609 if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
610 {
611 HWND hwnd = win32wnd->GetTopParent();
612 if(win32wnd->getWindowHandle() != hwnd) {
613 RELEASE_WNDOBJ(win32wnd);
614 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
615 if(win32wnd == NULL) {
616 DebugInt3();
617 goto dummymessage;
618 }
619 winMsg->hwnd = hwnd;
620 }
621 }
622 win32sc = SC_CLOSE_W;
623 break;
624 }
625 case SC_MAXIMIZE:
626 win32sc = SC_MAXIMIZE_W;
627 break;
628 case SC_MINIMIZE:
629 win32sc = SC_MINIMIZE_W;
630 break;
631 case SC_NEXTFRAME:
632 case SC_NEXTWINDOW:
633 win32sc = SC_NEXTWINDOW_W;
634 break;
635 case SC_RESTORE:
636 win32sc = SC_RESTORE_W;
637 break;
638 case SC_TASKMANAGER:
639 win32sc = SC_TASKLIST_W;
640 break;
641 case SC_SYSMENU:
642 win32sc = SC_KEYMENU_W; //??
643 break;
644 default:
645 dprintf(("Unknown/unsupported SC command %d", SHORT1FROMMP(os2Msg->mp1)));
646 goto dummymessage;
647 }
648 winMsg->message= WINWM_SYSCOMMAND;
649 winMsg->wParam = (WPARAM)win32sc;
650 winMsg->lParam = MAKELONG((USHORT)x, (USHORT)y);
651 break;
652 }
653
654 case WM_CHAR_SPECIAL_CONSOLE_BREAK:
655 {
656 dprintf(("PM: WM_CHAR_SPECIAL_CONSOLE_BREAK for %x", winMsg->hwnd));
657 if(fMsgRemoved)
658 {
659 GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT_W,0);
660 // It is our internal message, do not work with it more, its function
661 // is over, otherwise it will return FALSE and will be dispatched,
662 // and retranslated once again.
663
664 winMsg->message = 0;
665 winMsg->wParam = 0;
666 winMsg->lParam = 0;
667 goto msgdone;
668 }
669 goto dummymessage;
670 }
671
672 case WM_CHAR_SPECIAL_ALTGRCONTROL:
673 {
674 // special char message from the keyboard hook
675 dprintf(("PM: WM_CHAR_SPECIAL_ALTGRCONTROL"));
676 // NO BREAK! FALLTHRU CASE!
677 }
678
679 case WM_CHAR_SPECIAL:
680 {
681 // @@@PH
682 // special char message from the keyboard hook
683 if(os2Msg->msg == WM_CHAR_SPECIAL) {
684 dprintf(("PM: WM_CHAR_SPECIAL"));
685 }
686 // NO BREAK! FALLTHRU CASE!
687 }
688
689 case WM_CHAR:
690 {
691 ULONG repeatCount=0;
692 ULONG virtualKey=0;
693 ULONG keyFlags=0;
694 USHORT scanCode=0;
695 ULONG flags = SHORT1FROMMP(os2Msg->mp1);
696 BOOL keyWasPressed;
697 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
698 char c;
699 USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
700
701 teb->o.odin.fTranslated = FALSE;
702 repeatCount = CHAR3FROMMP(os2Msg->mp1);
703 scanCode = CHAR4FROMMP(os2Msg->mp1);
704 keyWasPressed = ((SHORT1FROMMP (os2Msg->mp1) & KC_PREVDOWN) == KC_PREVDOWN);
705
706 dprintf(("PM: WM_CHAR: %x %x rep=%d scancode=%x num=%d", SHORT1FROMMP(os2Msg->mp2), SHORT2FROMMP(os2Msg->mp2), repeatCount, scanCode, numPressed));
707 dprintf(("PM: WM_CHAR: hwnd %x flags %x mp1 %x, mp2 %x, time=%08xh", win32wnd->getWindowHandle(), flags, os2Msg->mp1, os2Msg->mp2, os2Msg->time));
708
709 BOOL fWinExtended;
710 BYTE bWinVKey;
711 WORD wWinScan;
712
713 if (scanCode==0) goto dummymessage;
714
715 KeyTranslatePMScanToWinVKey(usPMScanCode,
716 FALSE,
717 &bWinVKey,
718 &wWinScan,
719 &fWinExtended);
720 winMsg->wParam = bWinVKey;
721 winMsg->lParam = repeatCount & 0x0FFFF; // bit 0-15, repeatcount
722 winMsg->lParam |= (wWinScan & 0x1FF) << 16; // bit 16-23, scancode + bit 15 extended
723
724 // Set the extended bit when appropriate
725 if (fWinExtended)
726 winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
727
728 //PF When we press shift we enable non-numeric functions of Numpad
729 if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
730 winMsg->wParam = ConvertNumPadKey(scanCode);
731
732 //@PF This looks ugly but this is just what we have in win32 both in win98/win2k
733 //what happens is that lParam is tweaked in win32 to contain some illegal codes
734 //I simply reproduce here all situation. Absolute values can be kept because
735 //Break scancode can be acheived only by pressing Ctrl-Break combination
736 if ((usPMScanCode == PMSCAN_BREAK) && !(flags & KC_KEYUP) && (flags & KC_CTRL)
737 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
738 {
739 MSG extramsg;
740 memcpy(&extramsg, winMsg, sizeof(MSG));
741 // adjust our WM_CHAR code
742 extramsg.lParam = 0x01460001;
743
744 //After SetFocus(0), all keystrokes are converted in WM_SYS*
745 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
746
747 setThreadQueueExtraCharMessage(teb, &extramsg);
748 // and finally adjust our WM_KEYDOWN code
749 winMsg->lParam = 0x01460001;
750 }
751
752 if (!(flags & KC_ALT))
753 {
754 //
755 // the Alt key is not pressed
756 // or no more pressed
757 //
758 if (flags & KC_KEYUP)
759 {
760 // check for a lonesome ALT key ...
761 // SvL: Only Left Alt; AltGr generates a WM_KEYUP when released
762 if ( (flags & KC_LONEKEY) &&
763 (winMsg->wParam == VK_LMENU_W) )
764 {
765 winMsg->message = WINWM_SYSKEYUP;
766 // held ALT-key when current key is released
767 // generates additional flag 0x2000000
768 // Note: PM seems to do this differently,
769 // KC_ALT is already reset
770 }
771 else
772 {
773 // send WM_KEYUP message
774 winMsg->message = WINWM_KEYUP;
775 }
776 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, always 1 for a WM_KEYUP message
777 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
778 }
779 else
780 { // send WM_KEYDOWN message
781 winMsg->message = WINWM_KEYDOWN;
782
783 if (keyWasPressed)
784 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
785
786 //Shift-Enter and possibly others need to have special handling
787 if (flags & KC_SHIFT)
788 {
789 if(fMsgRemoved && !(teb->o.odin.fTranslated))
790 {
791 dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
792 if (winMsg->wParam == VK_RETURN_W)
793 {
794 MSG extramsg;
795 memcpy(&extramsg, winMsg, sizeof(MSG));
796
797 //After SetFocus(0), all keystrokes are converted in WM_SYS*
798 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
799
800 // insert message into the queue
801 setThreadQueueExtraCharMessage(teb, &extramsg);
802 winMsg->lParam &= 0x3FFFFFFF;
803 }
804 } // else ???
805 } // KC_SHIFT
806 else
807 {
808 // in case we handle Enter directly through PMKBDHOOK
809 if ((os2Msg->msg == WM_CHAR_SPECIAL) && (winMsg->wParam == VK_RETURN_W)
810 && (fMsgRemoved && !(teb->o.odin.fTranslated)))
811 {
812 MSG extramsg;
813 memcpy(&extramsg, winMsg, sizeof(MSG));
814
815 //After SetFocus(0), all keystrokes are converted in WM_SYS*
816 extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
817
818 // insert message into the queue
819 setThreadQueueExtraCharMessage(teb, &extramsg);
820 }
821 }
822 }
823 // if right alt is down, then we need to set the alt down bit too
824 // except for the fake Ctrl WM_CHAR sent for AltGr emulation
825 if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
826 (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
827 {
828 winMsg->lParam |= WIN_KEY_ALTHELD;
829 }
830 }
831 else
832 {
833 //
834 // the Alt key is pressed
835 //
836 if (flags & KC_KEYUP)
837 {
838 //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
839 winMsg->message = WINWM_SYSKEYUP;
840 winMsg->lParam |= WIN_KEY_PREVSTATE;
841 // No ALTHELD for Alt itself ;)
842 winMsg->lParam |= WIN_KEY_ALTHELD;
843 winMsg->lParam |= 1 << 31; // bit 31, transition state, always 1 for WM_KEYUP
844 }
845 else
846 {
847 // send WM_SYSKEYDOWN message
848 winMsg->message = WINWM_SYSKEYDOWN;
849 if (keyWasPressed)
850 winMsg->lParam |= WIN_KEY_PREVSTATE; // bit 30, previous state, 1 means key was pressed
851
852 // pressed ALT-key generates additional flag 0x2000000
853 // if the current window has keyboard focus
854 winMsg->lParam |= WIN_KEY_ALTHELD;
855 }
856 }
857#if 0
858 //
859 // AltGr needs special handling
860 //
861 // AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
862 // WM_SYSKEYUP (VK_CONTROL)
863 // WM_KEYUP (VK_MENU)
864 //
865 // Ctrl+AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYUP (VK_CONTROL)
866 // WM_KEYDOWN (VK_MENU)
867 // WM_KEYUP (VK_MENU)
868 // WM_KEYUP (VK_CONTROL)
869 //
870 // AltGr+Ctrl -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
871 // WM_KEYDOWN (VK_CONTROL)
872 // WM_SYSKEYUP (VK_CONTROL)
873 // WM_SYSKEYUP (VK_CONTROL)
874 // WM_KEYUP (VK_MENU)
875 //
876 // AltGr down -> if Ctrl down, send WM_KEYUP (VK_CONTROL)
877 // endif
878 // Send WM_KEYDOWN (VK_CONTROL)
879 // Send WM_KEYDOWN (VK_MENU)
880 // AltGr up -> if !(Ctrl down before AltGr was pressed || Ctrl up)
881 // Send WM_SYSKEYUP (VK_CONTROL)
882 // endif
883 // Send WM_KEYDOWN (VK_MENU)
884 //
885 if(winMsg->wParam == VK_MENU_W && (winMsg->lParam & WIN_KEY_EXTENDED))
886 {//AltGr
887 if(GetKeyState(VK_CONTROL_W) & 0x8000)
888 {//Ctrl key pressed, send WM_KEYUP
889
890 }
891 }
892#endif
893
894 //After SetFocus(0), all keystrokes are converted in WM_SYS*
895 if(fIgnoreKeystrokes) {
896 if(winMsg->message == WINWM_KEYDOWN) {
897 winMsg->message = WINWM_SYSKEYDOWN;
898 }
899 else
900 if(winMsg->message == WINWM_KEYUP) {
901 winMsg->message = WINWM_SYSKEYUP;
902 }
903 }
904 break;
905 }
906
907 case WM_TIMER:
908//Why was this check here????
909// if (os2Msg->mp2)
910// {
911 BOOL sys;
912 ULONG id, proc;
913
914 if (TIMER_GetTimerInfo(os2Msg->hwnd,(ULONG)os2Msg->mp1,&sys,&id, &proc))
915 {
916 winMsg->wParam = (WPARAM)id;
917 winMsg->lParam = (LPARAM)proc;
918 winMsg->message= (sys) ? WINWM_SYSTIMER : WINWM_TIMER;
919 break;
920 }
921// }
922 goto dummymessage; //for caret blinking
923
924 case WM_SETWINDOWPARAMS:
925 {
926 WNDPARAMS *wndParams = (WNDPARAMS *)os2Msg->mp1;
927
928 if(wndParams->fsStatus & WPM_TEXT) {
929 winMsg->message = WINWM_SETTEXT;
930 winMsg->lParam = (LPARAM)wndParams->pszText;
931 break;
932 }
933 goto dummymessage;
934 }
935
936#if 0
937 case WM_QUERYWINDOWPARAMS:
938 {
939 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
940 ULONG textlen;
941 PSZ wintext;
942
943 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
944 {
945 if(wndpars->fsStatus & WPM_CCHTEXT)
946 wndpars->cchText = win32wnd->MsgGetTextLength();
947 if(wndpars->fsStatus & WPM_TEXT)
948 wndpars->pszText = win32wnd->MsgGetText();
949
950 wndpars->fsStatus = 0;
951 wndpars->cbCtlData = 0;
952 wndpars->cbPresParams = 0;
953 goto dummymessage;
954 }
955 }
956#endif
957
958 case WM_PAINT:
959 {
960 if(win32wnd->IsWindowIconic()) {
961 winMsg->message = WINWM_PAINTICON;
962 }
963 else winMsg->message = WINWM_PAINT;
964 break;
965 }
966
967 case WM_CONTEXTMENU:
968 winMsg->message = WINWM_CONTEXTMENU;
969 winMsg->wParam = win32wnd->getWindowHandle();
970 winMsg->lParam = MAKELONG(winMsg->pt.x,winMsg->pt.y);
971 break;
972
973 case WM_RENDERFMT:
974 winMsg->message = WINWM_RENDERFORMAT;
975 winMsg->wParam = (UINT) os2Msg->mp1;
976 break;
977
978 case WM_RENDERALLFMTS:
979 winMsg->message = WINWM_RENDERALLFORMATS;
980 break;
981
982 case WM_DESTROYCLIPBOARD:
983 winMsg->message = WINWM_DESTROYCLIPBOARD;
984 break;
985
986 case WM_DRAWCLIPBOARD:
987 winMsg->message = WINWM_DRAWCLIPBOARD;
988 break;
989
990 case WM_HSCROLL:
991 case WM_VSCROLL:
992 //PF For win32 we support only vertical scrolling for WM_MOUSEWHEEL
993 if (os2Msg->msg == WM_VSCROLL)
994 {
995 POINT CursorPoint;
996 winMsg->message = WINWM_MOUSEWHEEL;
997 if (OSLibWinQueryPointerPos(&CursorPoint))
998 mapScreenPoint((OSLIBPOINT*)&CursorPoint);
999
1000 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1001 winMsg->wParam = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1002 else
1003 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1004 winMsg->wParam = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1005 else
1006 winMsg->wParam = MAKELONG(GetMouseKeyState(), 0);
1007
1008 winMsg->lParam = MAKELONG(CursorPoint.x, CursorPoint.y);
1009
1010 dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
1011 if (fMsgRemoved == MSG_REMOVE)
1012 {
1013 MSLLHOOKSTRUCT hook;
1014
1015 hook.pt.x = os2Msg->ptl.x & 0xFFFF;
1016 hook.pt.y = mapScreenY(os2Msg->ptl.y);
1017 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
1018 hook.mouseData = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1019 else
1020 if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
1021 hook.mouseData = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
1022 else goto dummymessage; // IBM driver produces other messages as well sometimes
1023
1024 hook.flags = LLMHF_INJECTED;
1025 hook.time = winMsg->time;
1026 hook.dwExtraInfo = 0;
1027 if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
1028 goto dummymessage; //hook swallowed message
1029 }
1030 break;
1031 }
1032 goto dummymessage; //eat this message
1033 break;
1034
1035 case WM_INITMENU:
1036 case WM_MENUSELECT:
1037 case WM_MENUEND:
1038 case WM_NEXTMENU:
1039 case WM_SYSCOLORCHANGE:
1040 case WM_SYSVALUECHANGED:
1041 case WM_SETSELECTION:
1042 case WM_PPAINT:
1043 case WM_PSETFOCUS:
1044 case WM_PSYSCOLORCHANGE:
1045 case WM_PSIZE:
1046 case WM_PACTIVATE:
1047 case WM_PCONTROL:
1048 case WM_HELP:
1049 case WM_APPTERMINATENOTIFY:
1050 case WM_PRESPARAMCHANGED:
1051 case WM_DRAWITEM:
1052 case WM_MEASUREITEM:
1053 case WM_CONTROLPOINTER:
1054 case WM_QUERYDLGCODE:
1055 case WM_SUBSTITUTESTRING:
1056 case WM_MATCHMNEMONIC:
1057 case WM_SAVEAPPLICATION:
1058 case WM_SEMANTICEVENT:
1059 default:
1060dummymessage:
1061 dprintf2(("dummy message %x %x %x %x", os2Msg->hwnd, os2Msg->msg, os2Msg->mp1, os2Msg->mp2));
1062 winMsg->message = 0;
1063 winMsg->wParam = 0;
1064 winMsg->lParam = 0;
1065 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1066 return FALSE;
1067 }
1068msgdone:
1069 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1070 return TRUE;
1071}
1072//******************************************************************************
1073//******************************************************************************
1074BOOL OSLibWinTranslateMessage(MSG *msg)
1075{
1076 TEB *teb;
1077 MSG extramsg;
1078 BOOL numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
1079 teb = GetThreadTEB();
1080 if(!teb)
1081 return FALSE;
1082
1083 UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
1084 ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
1085
1086
1087 //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
1088 // the newly generated WM_CHAR message.
1089 if(!teb->o.odin.fTranslated &&
1090 teb->o.odin.os2msg.msg == WM_CHAR &&
1091 !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
1092 {
1093 //TranslatedMessage was called before DispatchMessage, so queue WM_CHAR message
1094 memcpy(&extramsg, msg, sizeof(MSG));
1095 extramsg.wParam = SHORT1FROMMP(teb->o.odin.os2msg.mp2);
1096 extramsg.lParam = 0;
1097
1098 // ESCAPE generates a WM_CHAR under windows, so take
1099 // special care for this here.
1100 switch (ucPMScanCode)
1101 {
1102 case PMSCAN_ESC:
1103 extramsg.wParam = VK_ESCAPE_W;
1104 fl |= KC_CHAR;
1105 break;
1106 }
1107
1108 // PF With NumLock off do not generate any WM_CHAR messages at all
1109 // PADMINUS,PADPLUS fall in range of PAD7..PADPERIOD but they should generate WM_CHAR
1110 // other PAD(X) buttons miss that range at all and thus generate WM_CHAR
1111 if (!numPressed && (ucPMScanCode != PMSCAN_PADMINUS) && (ucPMScanCode != PMSCAN_PADPLUS) &&
1112 (ucPMScanCode >= PMSCAN_PAD7) && (ucPMScanCode <= PMSCAN_PADPERIOD))
1113 return FALSE;
1114
1115 if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
1116 {
1117 return FALSE;
1118 }
1119
1120 //the KC_COMPOSITE flag might be set; in that case this key will
1121 //be combined with the previous dead key, so we must use the scancode
1122 //(e.g. ^ on german keyboards)
1123 if((fl & (KC_VIRTUALKEY|KC_COMPOSITE)) == KC_VIRTUALKEY)
1124 {
1125 if(msg->wParam)
1126 {
1127 if ((msg->wParam >= VK_NUMPAD0_W) &&
1128 (msg->wParam <= VK_NUMPAD9_W))
1129 extramsg.wParam = msg->wParam - 0x30;
1130 else
1131 if (msg->wParam == VK_DECIMAL_W)
1132 extramsg.wParam = VK_DELETE_W;
1133 else
1134 /* PM Sends Bogus Things when pressing Shift+NUMAsterisk */
1135 if (msg->wParam != VK_MULTIPLY_W)
1136 extramsg.wParam = msg->wParam;
1137 }
1138 else
1139 extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
1140 }
1141
1142
1143 //After SetFocus(0), all keystrokes are converted in WM_SYS*
1144 if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
1145 extramsg.message = WINWM_SYSCHAR;
1146 else
1147 extramsg.message = WINWM_CHAR;
1148
1149 if(fl & KC_DEADKEY)
1150 extramsg.message++; //WM_DEADCHAR/WM_SYSDEADCHAR
1151
1152
1153 extramsg.lParam = msg->lParam & 0x00FFFFFF;
1154 if ((fl & KC_ALT) || (msg->lParam & WIN_KEY_ALTHELD))
1155 extramsg.lParam |= WIN_KEY_ALTHELD;
1156 if(fl & KC_PREVDOWN)
1157 extramsg.lParam |= WIN_KEY_PREVSTATE;
1158 if(fl & KC_KEYUP)
1159 extramsg.lParam |= (1<<31);
1160
1161 // insert message into the queue
1162 setThreadQueueExtraCharMessage(teb, &extramsg);
1163 return TRUE;
1164 }
1165 return FALSE;
1166}
1167//******************************************************************************
1168//******************************************************************************
1169
Note: See TracBrowser for help on using the repository browser.