source: trunk/src/user32/oslibmsg.cpp@ 3831

Last change on this file since 3831 was 3525, checked in by sandervl, 25 years ago

hook, syscolor & message bugfixes

File size: 15.9 KB
Line 
1/* $Id: oslibmsg.cpp,v 1.33 2000-05-12 18:09:40 sandervl Exp $ */
2/*
3 * Window message translation functions for OS/2
4 *
5 *
6 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 * TODO: Some messages that are sent to the frame window are directly passed on to the client
12 * -> Get/PeekMessage never gets them as we return a dummy message for non-client windows
13 * (i.e. menu WM_COMMAND messages)
14 *
15 * TODO: Filter translation isn't correct! (for posted messages or messages that don't have
16 * a PM version.
17 *
18 */
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 "oslibmsg.h"
26#include <winconst.h>
27#include <win32api.h>
28#include <win32wnd.h>
29#include "oslibutil.h"
30#include "timer.h"
31#include <thread.h>
32#include <wprocess.h>
33#include "pmwindow.h"
34#include "oslibwin.h"
35#include <win\hook.h>
36
37#define DBG_LOCALLOG DBG_oslibmsg
38#include "dbglocal.h"
39
40typedef BOOL (EXPENTRY FNTRANS)(MSG *, QMSG *);
41typedef FNTRANS *PFNTRANS;
42
43typedef struct
44{
45 ULONG msgOS2;
46 ULONG msgWin32;
47// PFNTRANS toOS2;
48// PFNTRANS toWIN32;
49} MSGTRANSTAB, *PMSGTRANSTAB;
50
51//NOTE: Must be ordered by win32 message id!!
52MSGTRANSTAB MsgTransTab[] = {
53 WM_NULL, WINWM_NULL,
54 WM_CREATE, WINWM_CREATE,
55 WM_DESTROY, WINWM_DESTROY,
56 WM_MOVE, WINWM_MOVE, //TODO: Sent directly
57 WM_SIZE, WINWM_SIZE, //TODO: Sent directly
58 WM_ACTIVATE, WINWM_ACTIVATE,
59 WM_SETFOCUS, WINWM_SETFOCUS,
60 WM_SETFOCUS, WINWM_KILLFOCUS,
61 WM_ENABLE, WINWM_ENABLE,
62 WM_PAINT, WINWM_PAINT,
63 WM_CLOSE, WINWM_CLOSE,
64 WM_QUIT, WINWM_QUIT,
65 WM_SHOW, WINWM_SHOWWINDOW,
66
67 WM_HITTEST, WINWM_NCHITTEST,
68
69 //TODO: Needs better translation!
70 WM_CHAR, WINWM_KEYDOWN,
71 WM_CHAR, WINWM_KEYUP,
72 WM_CHAR, WINWM_CHAR,
73 WM_CHAR, WINWM_DEADCHAR,
74 WM_CHAR, WINWM_SYSKEYDOWN,
75 WM_CHAR, WINWM_SYSKEYUP,
76 WM_CHAR, WINWM_SYSCHAR,
77 WM_CHAR, WINWM_SYSDEADCHAR,
78 WM_CHAR, WINWM_KEYLAST,
79
80 WM_COMMAND, WINWM_COMMAND,
81 WM_SYSCOMMAND, WINWM_SYSCOMMAND,
82 //
83 WM_TIMER, WINWM_TIMER,
84 WM_INITMENU, WINWM_INITMENU,
85 //
86 WM_MOUSEMOVE, WINWM_MOUSEMOVE,
87 WM_BUTTON1DOWN, WINWM_LBUTTONDOWN,
88 WM_BUTTON1UP, WINWM_LBUTTONUP,
89 WM_BUTTON1DBLCLK, WINWM_LBUTTONDBLCLK,
90 WM_BUTTON2DOWN, WINWM_RBUTTONDOWN,
91 WM_BUTTON2UP, WINWM_RBUTTONUP,
92 WM_BUTTON2DBLCLK, WINWM_RBUTTONDBLCLK,
93 WM_BUTTON3DOWN, WINWM_MBUTTONDOWN,
94 WM_BUTTON3UP, WINWM_MBUTTONUP,
95 WM_BUTTON3DBLCLK, WINWM_MBUTTONDBLCLK,
96
97 999999999, 999999999,
98};
99#define MAX_MSGTRANSTAB (sizeof(MsgTransTab)/sizeof(MsgTransTab[0]))
100
101LRESULT WIN32API SendMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
102
103//******************************************************************************
104//******************************************************************************
105void WinToOS2MsgTranslate(MSG *winMsg, QMSG *os2Msg, BOOL isUnicode)
106{
107// memcpy(os2Msg, winMsg, sizeof(MSG));
108// os2Msg->hwnd = Win32Window::Win32ToOS2Handle(winMsg->hwnd);
109// os2Msg->reserved = 0;
110}
111//******************************************************************************
112//TODO: NOT COMPLETE nor 100% CORRECT!!!
113//If both the minimum & maximum message are unknown, the result can be wrong (max > min)!
114//******************************************************************************
115ULONG TranslateWinMsg(ULONG msg, BOOL fMinFilter)
116{
117 if(msg == 0)
118 return 0;
119
120 if(msg >= WINWM_USER)
121 return WIN32APP_POSTMSG;
122
123 for(int i=0;i<MAX_MSGTRANSTAB;i++)
124 {
125 if(fMinFilter && MsgTransTab[i].msgWin32 >= msg) {
126 return MsgTransTab[i].msgOS2;
127 }
128 else
129 if(!fMinFilter && MsgTransTab[i].msgWin32 >= msg) {
130 if(MsgTransTab[i].msgWin32 == msg)
131 return MsgTransTab[i].msgOS2;
132 else return MsgTransTab[i-1].msgOS2;
133 }
134 }
135
136 return 0;
137}
138//******************************************************************************
139//******************************************************************************
140void OSLibWinPostQuitMessage(ULONG nExitCode)
141{
142 APIRET rc;
143
144 rc = WinPostQueueMsg(NULLHANDLE, WM_QUIT, MPFROMLONG(nExitCode), 0);
145 dprintf(("WinPostQueueMsg %d returned %d", nExitCode, rc));
146}
147//******************************************************************************
148//******************************************************************************
149LONG OSLibWinDispatchMsg(MSG *msg, BOOL isUnicode)
150{
151 THDB *thdb;
152 QMSG os2msg;
153 LONG rc;
154
155 thdb = GetThreadTHDB();
156 if(thdb == NULL) {
157 DebugInt3();
158 return FALSE;
159 }
160
161 //TODO: What to do if app changed msg? (translate)
162 // WinToOS2MsgTranslate(msg, &qmsg, isUnicode);
163
164 if(!memcmp(msg, &thdb->winmsg, sizeof(MSG)) || msg->hwnd == 0) {
165 memcpy(&os2msg, &thdb->os2msg, sizeof(QMSG));
166 thdb->os2msg.time = -1;
167 thdb->winmsg.time = -1;
168 if(msg->hwnd) {
169 thdb->nrOfMsgs = 1;
170 thdb->msgstate++; //odd -> next call to our PM window handler should dispatch the translated msg
171 memcpy(&thdb->msg, msg, sizeof(MSG));
172 }
173 if(os2msg.hwnd || os2msg.msg == WM_QUIT) {
174 memset(&thdb->os2msg, 0, sizeof(thdb->os2msg));
175 memset(&thdb->winmsg, 0, sizeof(thdb->winmsg));
176 return (LONG)WinDispatchMsg(thdb->hab, &os2msg);
177 }
178 //SvL: Don't dispatch messages sent by PostThreadMessage (correct??)
179 // Or WM_TIMER msgs with no window handle or timer proc
180 return 0;
181
182 }
183 else {//is this allowed?
184// dprintf(("WARNING: OSLibWinDispatchMsg: called with own message!"));
185 return SendMessageA(msg->hwnd, msg->message, msg->wParam, msg->lParam);
186 }
187}
188//******************************************************************************
189//******************************************************************************
190BOOL OSLibWinGetMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax,
191 BOOL isUnicode)
192{
193 BOOL rc, eaten;
194 THDB *thdb;
195 QMSG os2msg;
196 HWND hwndOS2 = 0;
197
198 if(hwnd) {
199 hwndOS2 = Win32BaseWindow::Win32ToOS2Handle(hwnd);
200 if(hwndOS2 == NULL) {
201 memset(pMsg, 0, sizeof(MSG));
202 dprintf(("GetMsg: window %x NOT FOUND!", hwnd));
203 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
204 return TRUE;
205 }
206 }
207
208 thdb = GetThreadTHDB();
209 if(thdb == NULL) {
210 DebugInt3();
211 return TRUE;
212 }
213
214 if(thdb->fTranslated && (!hwnd || hwnd == thdb->msgWCHAR.hwnd)) {
215 if(uMsgFilterMin) {
216 if(thdb->msgWCHAR.message < uMsgFilterMin)
217 goto continuegetmsg;
218 }
219 if(uMsgFilterMax) {
220 if(thdb->msgWCHAR.message > uMsgFilterMax)
221 goto continuegetmsg;
222 }
223 thdb->fTranslated = FALSE;
224 memcpy(pMsg, &thdb->msgWCHAR, sizeof(MSG));
225 thdb->os2msg.msg = 0;
226 thdb->os2msg.hwnd = 0;
227 return (pMsg->message != WINWM_QUIT);
228 }
229
230continuegetmsg:
231 if(hwnd) {
232 do {
233 WinWaitMsg(thdb->hab, TranslateWinMsg(uMsgFilterMin, TRUE), TranslateWinMsg(uMsgFilterMax, FALSE));
234 rc = OSLibWinPeekMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, PM_REMOVE_W, isUnicode);
235 }
236 while(rc == FALSE);
237
238 return (pMsg->message != WINWM_QUIT);
239 }
240 else
241 {
242 do {
243 eaten = FALSE;
244 rc = WinGetMsg(thdb->hab, &os2msg, TranslateWinMsg(uMsgFilterMin, TRUE), TranslateWinMsg(uMsgFilterMax, FALSE), 0);
245 if (os2msg.msg == WM_TIMER)
246 eaten = TIMER_HandleTimer(&os2msg);
247 } while (eaten);
248 }
249
250 OS2ToWinMsgTranslate((PVOID)thdb, &os2msg, pMsg, isUnicode, MSG_REMOVE);
251 memcpy(&thdb->os2msg, &os2msg, sizeof(QMSG));
252 memcpy(&thdb->winmsg, pMsg, sizeof(MSG));
253
254 if(pMsg->message <= WINWM_KEYLAST && pMsg->message >= WINWM_KEYDOWN)
255 {
256 if(ProcessKbdHook(pMsg, TRUE))
257 goto continuegetmsg;
258 }
259 return rc;
260}
261//******************************************************************************
262//PeekMessage retrieves only messages associated with the window identified by the
263//hwnd parameter or any of its children as specified by the IsChild function, and within
264//the range of message values given by the uMsgFilterMin and uMsgFilterMax
265//parameters. If hwnd is NULL, PeekMessage retrieves messages for any window that
266//belongs to the current thread making the call. (PeekMessage does not retrieve
267//messages for windows that belong to other threads.) If hwnd is -1, PeekMessage only
268//returns messages with a hwnd value of NULL, as posted by the PostAppMessage
269//function. If uMsgFilterMin and uMsgFilterMax are both zero, PeekMessage returns all
270//available messages (no range filtering is performed).
271//TODO: Not working as specified right now!
272//******************************************************************************
273BOOL OSLibWinPeekMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax,
274 DWORD fRemove, BOOL isUnicode)
275{
276 BOOL rc, eaten;
277 THDB *thdb;
278 QMSG os2msg;
279 HWND hwndOS2 = 0;
280
281 if(hwnd && hwnd != -1) {
282 hwndOS2 = Win32BaseWindow::Win32ToOS2Handle(hwnd);
283 if(hwndOS2 == NULL) {
284 dprintf(("PeekMsg: window %x NOT FOUND!", hwnd));
285 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
286 return FALSE;
287 }
288 }
289
290 thdb = GetThreadTHDB();
291 if(thdb == NULL) {
292 DebugInt3();
293 return FALSE;
294 }
295
296 if(thdb->fTranslated && (!hwnd || hwnd == thdb->msgWCHAR.hwnd)) {
297 if(uMsgFilterMin) {
298 if(thdb->msgWCHAR.message < uMsgFilterMin)
299 goto continuepeekmsg;
300 }
301 if(uMsgFilterMax) {
302 if(thdb->msgWCHAR.message > uMsgFilterMax)
303 goto continuepeekmsg;
304 }
305
306 if(fRemove & PM_REMOVE_W) {
307 thdb->fTranslated = FALSE;
308 thdb->os2msg.msg = 0;
309 thdb->os2msg.hwnd = 0;
310 }
311 memcpy(pMsg, &thdb->msgWCHAR, sizeof(MSG));
312 return TRUE;
313 }
314
315continuepeekmsg:
316 do {
317 eaten = FALSE;
318 rc = WinPeekMsg(thdb->hab, &os2msg, hwndOS2, TranslateWinMsg(uMsgFilterMin, TRUE),
319 TranslateWinMsg(uMsgFilterMax, FALSE), (fRemove & PM_REMOVE_W) ? PM_REMOVE : PM_NOREMOVE);
320
321 if (rc && (fRemove & PM_REMOVE_W) && os2msg.msg == WM_TIMER) {
322 eaten = TIMER_HandleTimer(&os2msg);
323 }
324 }
325 while (eaten && rc);
326
327 if(rc == FALSE) {
328 return FALSE;
329 }
330
331 OS2ToWinMsgTranslate((PVOID)thdb, &os2msg, pMsg, isUnicode, (fRemove & PM_REMOVE_W) ? MSG_REMOVE : MSG_NOREMOVE);
332 //TODO: This is not safe! There's no guarantee this message will be dispatched and it might overwrite a previous message
333 if(fRemove & PM_REMOVE_W) {
334 memcpy(&thdb->os2msg, &os2msg, sizeof(QMSG));
335 memcpy(&thdb->winmsg, pMsg, sizeof(MSG));
336 }
337
338 if(pMsg->message <= WINWM_KEYLAST && pMsg->message >= WINWM_KEYDOWN)
339 {
340 if(ProcessKbdHook(pMsg, fRemove))
341 goto continuepeekmsg;
342 }
343
344 return rc;
345}
346//******************************************************************************
347//******************************************************************************
348ULONG OSLibWinQueryMsgTime()
349{
350 return WinQueryMsgTime(GetThreadHAB());
351}
352//******************************************************************************
353//******************************************************************************
354BOOL OSLibWinWaitMessage()
355{
356 return WinWaitMsg(GetThreadHAB(), 0, 0);
357}
358//******************************************************************************
359//TODO: QS_HOTKEY
360//******************************************************************************
361ULONG OSLibWinQueryQueueStatus()
362{
363 ULONG statusOS2, statusWin32 = 0;
364
365 statusOS2 = WinQueryQueueStatus(HWND_DESKTOP);
366
367 if(statusOS2 & QS_KEY)
368 statusWin32 |= QS_KEY_W;
369 if(statusOS2 & QS_MOUSEBUTTON)
370 statusWin32 |= QS_MOUSEBUTTON_W;
371 if(statusOS2 & QS_MOUSEMOVE)
372 statusWin32 |= QS_MOUSEMOVE_W;
373 if(statusOS2 & QS_TIMER)
374 statusWin32 |= QS_TIMER_W;
375 if(statusOS2 & QS_PAINT)
376 statusWin32 |= QS_PAINT_W;
377 if(statusOS2 & QS_POSTMSG)
378 statusWin32 |= QS_POSTMESSAGE_W;
379 if(statusOS2 & QS_SENDMSG)
380 statusWin32 |= QS_SENDMESSAGE_W;
381
382 return statusWin32;
383}
384//******************************************************************************
385//******************************************************************************
386BOOL OSLibWinInSendMessage()
387{
388 return WinInSendMsg(GetThreadHAB());
389}
390//******************************************************************************
391//******************************************************************************
392DWORD OSLibWinGetMessagePos()
393{
394 APIRET rc;
395 POINTL ptl;
396
397 rc = WinQueryMsgPos(GetThreadHAB(), &ptl);
398 if(!rc) {
399 return 0;
400 }
401 //convert to windows coordinates
402 return MAKEULONG(ptl.x,mapScreenY(ptl.y));
403}
404//******************************************************************************
405//******************************************************************************
406LONG OSLibWinGetMessageTime()
407{
408 return (LONG)WinQueryMsgTime(GetThreadHAB());
409}
410//******************************************************************************
411//******************************************************************************
412BOOL OSLibWinReplyMessage(ULONG result)
413{
414 return (BOOL)WinReplyMsg( NULLHANDLE, NULLHANDLE, HMQ_CURRENT, (MRESULT)result);
415}
416//******************************************************************************
417//******************************************************************************
418ULONG OSLibSendMessage(HWND hwnd, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
419{
420 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
421
422 packet->Msg = msg;
423 packet->wParam = wParam;
424 packet->lParam = lParam;
425
426 return (ULONG)WinSendMsg(hwnd, WIN32APP_POSTMSG, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
427}
428//******************************************************************************
429//******************************************************************************
430ULONG OSLibWinBroadcastMsg(ULONG msg, ULONG wParam, ULONG lParam, BOOL fSend)
431{
432 return WinBroadcastMsg(HWND_DESKTOP, msg, (MPARAM)wParam, (MPARAM)lParam,
433 (fSend) ? BMSG_SEND : BMSG_POST);
434}
435//******************************************************************************
436//******************************************************************************
437BOOL OSLibPostMessage(HWND hwnd, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
438{
439 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
440
441 packet->Msg = msg;
442 packet->wParam = wParam;
443 packet->lParam = lParam;
444 return WinPostMsg(hwnd, WIN32APP_POSTMSG, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
445}
446//******************************************************************************
447BOOL _System _O32_PostThreadMessage( DWORD, UINT, WPARAM, LPARAM );
448
449inline BOOL O32_PostThreadMessage(DWORD a, UINT b, WPARAM c, LPARAM d)
450{
451 BOOL yyrc;
452 USHORT sel = RestoreOS2FS();
453
454 yyrc = _O32_PostThreadMessage(a, b, c, d);
455 SetFS(sel);
456
457 return yyrc;
458}
459//******************************************************************************
460BOOL OSLibPostThreadMessage(ULONG threadid, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fUnicode)
461{
462// THDB *thdb = GetTHDBFromThreadId(threadid);
463 POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
464
465// if(thdb == NULL) {
466// dprintf(("OSLibPostThreadMessage: thread %x not found!", threadid));
467// return FALSE;
468// }
469 dprintf(("PostThreadMessageA %x %x %x %x", threadid, msg, wParam, lParam));
470 packet->Msg = msg;
471 packet->wParam = wParam;
472 packet->lParam = lParam;
473 return O32_PostThreadMessage(threadid, WIN32APP_POSTMSG-OPEN32_MSGDIFF, ((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (LPARAM)packet);
474}
475//******************************************************************************
476//******************************************************************************
477
Note: See TracBrowser for help on using the repository browser.