source: trunk/src/user32/pmwindow.cpp@ 10285

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

Use WC_FRAME for the Odin frame window and subclass it; Updates for new keyboard hook

File size: 86.9 KB
Line 
1/* $Id: pmwindow.cpp,v 1.223 2003-10-22 12:43:51 sandervl Exp $ */
2/*
3 * Win32 Window Managment Code for OS/2
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_WIN
13#define INCL_GPI
14#define INCL_DEV /* Device Function definitions */
15#define INCL_GPICONTROL /* GPI control Functions */
16#define INCL_DOSPROCESS
17#define INCL_DOSMODULEMGR
18#define INCL_DOSDEVICES
19#define INCL_DOSDEVIOCTL
20#define INCL_WINTRACKRECT
21#define INCL_BASE
22
23#include <os2wrap.h>
24#include <odinwrap.h>
25#include <stdlib.h>
26#include <string.h>
27#include <win32type.h>
28#include <win32api.h>
29#include <winconst.h>
30#include <winuser32.h>
31#include <wprocess.h>
32#include <dbglog.h>
33#include <win32wbase.h>
34#include <win32wfake.h>
35#include <win32dlg.h>
36#include "win32wdesktop.h"
37#include "pmwindow.h"
38#include "oslibwin.h"
39#include "oslibutil.h"
40#include "oslibgdi.h"
41#include "oslibmsg.h"
42#define INCLUDED_BY_DC
43#include "dc.h"
44#include <thread.h>
45#include <wprocess.h>
46#include "caret.h"
47#include "timer.h"
48#include <codepage.h>
49#include "syscolor.h"
50#include "options.h"
51#include "menu.h"
52#include <pmkbdhk.h>
53#include <pmscan.h>
54#include <winscan.h>
55#include <oslibdnd.h>
56#include <custombuild.h>
57#include <win\dbt.h>
58#include "dragdrop.h"
59#include "menu.h"
60#include "user32api.h"
61
62#define DBG_LOCALLOG DBG_pmwindow
63#include "dbglocal.h"
64
65#define ODIN_SetExceptionHandler(a)
66#define ODIN_UnsetExceptionHandler(a)
67
68
69// Notification that focus change has completed (UNDOCUMENTED)
70#define WM_FOCUSCHANGED 0x000e
71
72//define this to use the new code for WM_CALCVALIDRECT handling
73//#define USE_CALCVALIDRECT
74
75HMQ hmq = 0; /* Message queue handle */
76HAB hab = 0;
77RECTL desktopRectl = {0};
78ULONG ScreenWidth = 0;
79ULONG ScreenHeight = 0;
80ULONG ScreenBitsPerPel = 0;
81BOOL fOS2Look = FALSE;
82BOOL fForceMonoCursor = FALSE;
83BOOL fDragDropActive = FALSE;
84BOOL fDragDropDisabled = FALSE;
85
86const char WIN32_CDCLASS[] = "Win32CDWindowClass";
87 char WIN32_STDCLASS[255] = "Win32WindowClass";
88
89#define PMMENU_MINBUTTON 0
90#define PMMENU_MAXBUTTON 1
91#define PMMENU_RESTOREBUTTON 2
92#define PMMENU_CLOSEBUTTON 3
93#define PMMENU_MINBUTTONDOWN 4
94#define PMMENU_MAXBUTTONDOWN 5
95#define PMMENU_RESTOREBUTTONDOWN 6
96#define PMMENU_CLOSEBUTTONDOWN 7
97
98HBITMAP hbmFrameMenu[8] = {0};
99
100//Win32 bitmap handles of the OS/2 min, max and restore buttons
101HBITMAP hBmpMinButton = 0;
102HBITMAP hBmpMaxButton = 0;
103HBITMAP hBmpRestoreButton = 0;
104HBITMAP hBmpCloseButton = 0;
105HBITMAP hBmpMinButtonDown = 0;
106HBITMAP hBmpMaxButtonDown = 0;
107HBITMAP hBmpRestoreButtonDown = 0;
108HBITMAP hBmpCloseButtonDown = 0;
109
110 PFNWP pfnFrameWndProc = NULL;
111static HWND hwndFocusChange = 0;
112 HWND hwndCD = 0;
113
114// this holds the font height that the display driver returns using DevQueryCaps
115// 13 would be small fonts, 16 medium fonts and 20 large fonts
116LONG CapsCharHeight = 0;
117
118// Note:
119// For a "lonekey"-press of AltGr, we only receive WM_KEYUP
120// messages. If the key is pressed longer and starts to repeat,
121// WM_KEYDOWN messages come in properly.
122static BOOL fKeyAltGrDown = FALSE;
123static BOOL fEnableCDPolling = FALSE;
124
125static char *PMDragExtractFiles(PDRAGINFO pDragInfo, ULONG *pcItems, ULONG *pulBytes);
126static BOOL PMDragValidate(PDRAGINFO pDragInfo);
127static void QueryPMMenuBitmaps();
128
129MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
130MRESULT EXPENTRY Win32CDWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
131MRESULT EXPENTRY Win32FrameWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
132void FrameReplaceMenuItem(HWND hwndMenu, ULONG nIndex, ULONG idOld, ULONG idNew,
133 HBITMAP hbmNew);
134void FrameSetFocus(HWND hwnd);
135
136VOID APIENTRY DspInitSystemDriverName(PSZ pszDriverName, ULONG lenDriverName);
137
138#ifdef DEBUG
139static char *DbgGetStringSWPFlags(ULONG flags);
140static char *DbgPrintQFCFlags(ULONG flags);
141#endif
142
143//******************************************************************************
144// Initialize PM; create hab, message queue and register special Win32 window classes
145//
146// This is called from the initterm, so we call it only once for each process.
147// We make sure PM is up and running for our purposes and init the existing
148// thread 0.
149//******************************************************************************
150BOOL InitPM()
151{
152 hab = WinInitialize(0);
153 dprintf(("Winitialize returned %x", hab));
154 hmq = WinCreateMsgQueue(hab, 0);
155
156 if(!hab || !hmq)
157 {
158 UINT error;
159 //CB: only fail on real error
160 error = WinGetLastError(hab) & 0xFFFF; //error code
161 if (!hab || (error != PMERR_MSG_QUEUE_ALREADY_EXISTS))
162 {
163 dprintf(("WinInitialize or WinCreateMsgQueue failed %x %x", hab, hmq));
164 dprintf((" Error = %x",error));
165 if(error == PMERR_NOT_IN_A_PM_SESSION) return TRUE;
166
167 return(FALSE);
168 }
169 else
170 {
171 if(!hab) {
172 hab = WinQueryAnchorBlock(HWND_DESKTOP);
173 dprintf(("WinQueryAnchorBlock returned %x", hab));
174 }
175 if(!hmq) {
176 PTIB ptib;
177 PPIB ppib;
178
179 DosGetInfoBlocks(&ptib, &ppib);
180
181 hmq = WinQueueFromID(hab, ppib->pib_ulpid, ptib->tib_ptib2->tib2_ultid);
182 }
183 }
184 }
185
186 // store our HAB and HMQ in the TEB - we need it quite often
187 // and they don't map 1:1 to Windows entities
188 SetThreadHAB(hab);
189 dprintf(("InitPM: hmq = %x", hmq));
190 SetThreadMessageQueue(hmq);
191
192 BOOL rc = WinSetCp(hmq, GetDisplayCodepage());
193 dprintf(("InitPM: WinSetCP was %sOK", rc ? "" : "not "));
194
195 //CD polling window class
196 if(!WinRegisterClass( /* Register window class */
197 hab, /* Anchor block handle */
198 (PSZ)WIN32_CDCLASS, /* Window class name */
199 (PFNWP)Win32CDWindowProc, /* Address of window procedure */
200 0,
201 0))
202 {
203 dprintf(("WinRegisterClass Win32BaseWindow failed"));
204 return(FALSE);
205 }
206
207 //Standard Odin window class
208 if(!WinRegisterClass( /* Register window class */
209 hab, /* Anchor block handle */
210 (PSZ)WIN32_STDCLASS, /* Window class name */
211 (PFNWP)Win32WindowProc, /* Address of window procedure */
212 0,
213 NROF_WIN32WNDBYTES))
214 {
215 dprintf(("WinRegisterClass Win32BaseWindow failed"));
216 return(FALSE);
217 }
218
219 //We no longer register our own frame window class as there is code in PM
220 //that makes assumptions about frame window class names.
221 //Instead we subclass the frame window right after creating it.
222 CLASSINFO FrameClassInfo;
223 if(!WinQueryClassInfo (hab, WC_FRAME, &FrameClassInfo)) {
224 dprintf (("WinQueryClassInfo WC_FRAME failed"));
225 return (FALSE);
226 }
227 pfnFrameWndProc = FrameClassInfo.pfnWindowProc;
228
229 dprintf(("WC_FRAME style %x", FrameClassInfo.flClassStyle));
230
231 // get the screen dimensions and store them
232 WinQueryWindowRect(HWND_DESKTOP, &desktopRectl);
233 ScreenWidth = desktopRectl.xRight;
234 ScreenHeight = desktopRectl.yTop;
235
236 HDC hdc; /* Device-context handle */
237 /* context data structure */
238 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL,
239 NULL, NULL, NULL};
240
241 /* create memory device context - it's temporary to query some information */
242 hdc = DevOpenDC(hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
243
244 // check if we have the OS/2 Look and Feel enabled
245 fOS2Look = PROFILE_GetOdinIniBool(ODINSYSTEM_SECTION, "OS2Look", TRUE);
246 if(fOS2Look)
247 {
248 SYSCOLOR_Init(FALSE); //use OS/2 colors
249 QueryPMMenuBitmaps();
250 }
251
252 // find out which colordepth we're running
253 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, (PLONG)&ScreenBitsPerPel);
254
255 // query the font height to find out whether we have small or large fonts
256 DevQueryCaps(hdc, CAPS_GRAPHICS_CHAR_HEIGHT, 1, (PLONG)&CapsCharHeight);
257
258 DevCloseDC(hdc);
259
260 dprintf(("InitPM: Desktop (%d,%d) bpp %d", ScreenWidth, ScreenHeight, ScreenBitsPerPel));
261 return TRUE;
262} /* End of main */
263//******************************************************************************
264HBITMAP OPEN32API _O32_CreateBitmapFromPMHandle(HBITMAP hPMBitmap);
265
266inline HBITMAP O32_CreateBitmapFromPMHandle(HBITMAP hPMBitmap)
267{
268 HBITMAP yyrc;
269 USHORT sel = RestoreOS2FS();
270
271 yyrc = _O32_CreateBitmapFromPMHandle(hPMBitmap);
272 SetFS(sel);
273
274 return yyrc;
275}
276//******************************************************************************
277static void QueryPMMenuBitmaps()
278{
279 CHAR szDisplay[30];
280 HMODULE hModDisplay;
281
282 if(hbmFrameMenu[0] == 0)
283 {
284 CHAR szDisplay[30];
285 HMODULE hModDisplay;
286 HDC hdc; /* Device-context handle */
287 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL,
288 NULL, NULL, NULL};
289
290 /* create memory device context */
291 hdc = DevOpenDC(hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
292
293 DspInitSystemDriverName(szDisplay, sizeof(szDisplay));
294 DosQueryModuleHandle(szDisplay, &hModDisplay);
295
296 hbmFrameMenu[PMMENU_MINBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MINBUTTON, 0, 0);
297 hbmFrameMenu[PMMENU_MINBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MINBUTTONDEP, 0, 0);
298 hbmFrameMenu[PMMENU_MAXBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MAXBUTTON, 0, 0);
299 hbmFrameMenu[PMMENU_MAXBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_MAXBUTTONDEP, 0, 0);
300 hbmFrameMenu[PMMENU_RESTOREBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_RESTOREBUTTON, 0, 0);
301 hbmFrameMenu[PMMENU_RESTOREBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_RESTOREBUTTONDEP, 0, 0);
302 hbmFrameMenu[PMMENU_CLOSEBUTTON] = GpiLoadBitmap(hdc, hModDisplay, SBMP_CLOSE, 0, 0);
303 hbmFrameMenu[PMMENU_CLOSEBUTTONDOWN] = GpiLoadBitmap(hdc, hModDisplay, SBMP_CLOSEDEP, 0, 0);
304
305 //Create win32 bitmap handles of the OS/2 min, max and restore buttons
306 hBmpMinButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MINBUTTON]);
307 hBmpMinButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MINBUTTONDOWN]);
308 hBmpMaxButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MAXBUTTON]);
309 hBmpMaxButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_MAXBUTTONDOWN]);
310 hBmpRestoreButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_RESTOREBUTTON]);
311 hBmpRestoreButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_RESTOREBUTTONDOWN]);
312 hBmpCloseButton = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_CLOSEBUTTON]);
313 hBmpCloseButtonDown = O32_CreateBitmapFromPMHandle(hbmFrameMenu[PMMENU_CLOSEBUTTONDOWN]);
314 DevCloseDC(hdc);
315 }
316}
317//******************************************************************************
318//******************************************************************************
319void WIN32API SetWindowAppearance(int fLooks)
320{
321 if(fLooks == OS2_APPEARANCE || fLooks == OS2_APPEARANCE_SYSMENU)
322 {
323 SYSCOLOR_Init(FALSE); //use OS/2 colors
324 QueryPMMenuBitmaps();
325 }
326 fOS2Look = fLooks;
327 MENU_Init();
328}
329//******************************************************************************
330//******************************************************************************
331void WIN32API CustForceMonoCursor()
332{
333 fForceMonoCursor = TRUE;
334}
335//******************************************************************************
336//******************************************************************************
337void WIN32API DisableDragDrop(BOOL fDisabled)
338{
339 fDragDropDisabled = fDisabled;
340}
341//******************************************************************************
342// Turn on CD Polling (window with 2 second timer to check CD disk presence)
343//
344// NOTE: This can cause PM hangs when executing a program for a very long time
345// (block in IOCtl)
346//******************************************************************************
347void WIN32API CustEnableCDPolling()
348{
349 fEnableCDPolling = TRUE;
350}
351//******************************************************************************
352//CD notification window class
353//******************************************************************************
354MRESULT EXPENTRY Win32CDWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
355{
356#pragma pack(1)
357 typedef struct
358 {
359 BYTE ucCommandInfo;
360 WORD usDriveUnit;
361 } ParameterBlock;
362#pragma pack()
363
364 MRESULT rc = 0;
365 static ULONG drives[26] = {0};
366 static int drivestatus[26] = {0};
367
368 switch( msg )
369 {
370 //OS/2 msgs
371 case WM_CREATE:
372 {
373 char drive[4];
374
375 //skip floppy drives
376 drive[0] = 'C';
377 drive[1] = ':';
378 drive[2] = '\0';
379
380 for(int i=2;i<26;i++) {
381 drives[i] = GetDriveTypeA(drive);
382 if(drives[i] == DRIVE_CDROM_W)
383 {
384 DWORD parsize = sizeof(ParameterBlock);
385 DWORD datasize = 2;
386 WORD status = 0;
387 DWORD rc;
388 ParameterBlock parm;
389
390 parm.ucCommandInfo = 0;
391 parm.usDriveUnit = i;
392 rc = DosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
393 &status, sizeof(status), &datasize);
394 if(rc != NO_ERROR) {
395 dprintf(("DosDevIOCtl failed with rc %d", rc));
396 drives[i] = 0;
397 continue;
398 }
399 //if no disk present, return FALSE
400 if(status & 4) {
401 drivestatus[i] = status & 4;
402 }
403 }
404 drive[0]++;
405 }
406 WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 32*60);
407//// WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 32*3);
408//// WinStartTimer(hab, hwnd, TIMERID_DRIVEPOLL, 5000);
409 rc = (MRESULT)FALSE;
410 break;
411 }
412 case WM_TIMER:
413 {
414 for(int i=0;i<26;i++)
415 {
416 //for now only cdrom/dvd drives
417 if(drives[i] == DRIVE_CDROM_W)
418 {
419 DWORD parsize = sizeof(ParameterBlock);
420 DWORD datasize = 2;
421 WORD status = 0;
422 DWORD rc;
423 ParameterBlock parm;
424
425 parm.ucCommandInfo = 0;
426 parm.usDriveUnit = i;
427 rc = DosDevIOCtl(-1, IOCTL_DISK, DSK_GETLOCKSTATUS, &parm, sizeof(parm), &parsize,
428 &status, sizeof(status), &datasize);
429 if(rc != NO_ERROR) {
430 dprintf(("DosDevIOCtl failed with rc %d", rc));
431 return FALSE;
432 }
433 //Send WM_DEVICECHANGE message when CD status changes
434 if((status & 4) != drivestatus[i])
435 {
436 PID pidThis, pidTemp;
437 HENUM henum;
438 HWND hwndEnum;
439 DEV_BROADCAST_VOLUME volchange;
440
441 dprintf(("Disk status 0x%x", status));
442
443 volchange.dbcv_size = sizeof(volchange);
444 volchange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
445 volchange.dbcv_reserved = 0;
446 volchange.dbcv_unitmask = (1 << i);
447 volchange.dbcv_flags = DBTF_MEDIA;
448
449 WinQueryWindowProcess(hwnd, &pidThis, NULL);
450
451 //Iterate over all child windows of the desktop
452 henum = WinBeginEnumWindows(HWND_DESKTOP);
453
454 SetWin32TIB();
455 while(hwndEnum = WinGetNextWindow(henum))
456 {
457 WinQueryWindowProcess(hwndEnum, &pidTemp, NULL);
458 if(pidTemp == pidThis)
459 {
460 HWND hwndWin32 = OS2ToWin32Handle(hwndEnum);
461 if(hwndWin32) {
462 SendMessageA(hwndWin32,
463 WM_DEVICECHANGE_W,
464 (status & 4) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
465 (LPARAM)&volchange);
466 }
467 }
468 }
469 RestoreOS2TIB();
470 WinEndEnumWindows(henum);
471
472 drivestatus[i] = (status & 4);
473 }
474 }
475 }
476 break;
477 }
478
479 case WM_DESTROY:
480 dprintf(("WM_DESTROY for CD notification window"));
481 WinStopTimer(hab, hwnd, TIMERID_DRIVEPOLL);
482 break;
483
484 default:
485 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
486 }
487 return (MRESULT)rc;
488}
489//******************************************************************************
490// Win32 window message handler
491// The PM window procedure for our client window class (non frame)
492//******************************************************************************
493MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
494{
495 Win32BaseWindow *win32wnd;
496 TEB *teb;
497 MSG winMsg, *pWinMsg;
498 MRESULT rc = 0;
499 POSTMSG_PACKET *postmsg;
500 OSLIBPOINT point, ClientPoint;
501 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
502
503 ODIN_SetExceptionHandler(&exceptRegRec);
504 // restore our FS selector
505 SetWin32TIB();
506
507#ifdef DEBUG
508 dbg_ThreadPushCall("Win32WindowProc");
509#endif
510
511 // BEGIN NOTE-------------->>>>>> If this is changed, also change Win32FrameWindowProc!! <<<<<<<<<<<-------------------- BEGIN
512 teb = GetThreadTEB();
513 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
514
515//// dprintf(("window %x msg %x", (win32wnd) ? win32wnd->getWindowHandle() : 0, msg));
516
517 // do some sanity checking here:
518 // - we need to have a TEB handle
519 // - unless this is WM_CREATE (the very first message), there has to be
520 // a USER32 window object for this window handle
521 // - thread must not be suspended in WaitMessage
522 if(!teb || (msg != WM_CREATE && win32wnd == NULL) || teb->o.odin.fWaitMessageSuspend) {
523 if(teb && teb->o.odin.fWaitMessageSuspend)
524 dprintf(("OS2: fWaitMessageSuspend window %x msg %x -> run default frame proc", hwnd, msg));
525 else dprintf(("OS2: Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
526 goto RunDefWndProc;
527 }
528//// if(teb->o.odin.fIgnoreMsgs) {
529//// goto RunDefWndProc;
530//// }
531
532 // check if the message state counter in the TEB is odd
533 // This means the message has been sent directly from PM to our message
534 // handler (so it is the first time we know about this PM message).
535 // If this is the case, we have to translate it here to a Win32
536 // message first. The other case is that the message is the result of a
537 // WinDispatchMsg call and therefore has already been translated.
538 if((teb->o.odin.msgstate & 1) == 0)
539 {
540 // message that was sent directly to our window proc handler; translate it here
541 QMSG qmsg;
542
543 qmsg.msg = msg;
544 qmsg.hwnd = hwnd;
545 qmsg.mp1 = mp1;
546 qmsg.mp2 = mp2;
547 qmsg.time = WinQueryMsgTime(teb->o.odin.hab);
548 WinQueryMsgPos(teb->o.odin.hab, &qmsg.ptl);
549 qmsg.reserved = 0;
550
551 if(OS2ToWinMsgTranslate((PVOID)teb, &qmsg, &winMsg, FALSE, MSG_REMOVE) == FALSE)
552 {//message was not translated
553 memset(&winMsg, 0, sizeof(MSG));
554 }
555 pWinMsg = &winMsg;
556 }
557 else {
558 // message has already been translated before (GetMessage/PeekMessage).
559 // Use the translated information. Flip the translation flag.
560 pWinMsg = &teb->o.odin.msg;
561 teb->o.odin.msgstate++;
562 }
563 // END NOTE-------------->>>>>> If this is changed, also change Win32FrameWindowProc!! <<<<<<<<<<<-------------------- END
564
565 if(msg >= WIN32APP_POSTMSG) {
566 //probably win32 app user message
567 dprintf2(("Posted message %x->%x", msg, msg-WIN32APP_POSTMSG));
568 if((ULONG)mp1 == WIN32MSG_MAGICA) {
569 rc = (MRESULT)win32wnd->DispatchMsgA(pWinMsg);
570 }
571 else
572 if((ULONG)mp1 == WIN32MSG_MAGICW) {
573 rc = (MRESULT)win32wnd->DispatchMsgW(pWinMsg);
574 }
575 else {//broadcasted message
576 rc = (MRESULT)win32wnd->DispatchMsgA(pWinMsg);
577 }
578 RELEASE_WNDOBJ(win32wnd);
579 RestoreOS2TIB();
580 ODIN_UnsetExceptionHandler(&exceptRegRec);
581
582#ifdef DEBUG
583 dbg_ThreadPopCall();
584#endif
585 return rc;
586 }
587
588 switch( msg )
589 {
590 //OS/2 msgs
591 case WM_CREATE:
592 {
593 if(teb->o.odin.newWindow == 0)
594 goto createfail;
595
596 //Processing is done in after WinCreateWindow returns
597 dprintf(("OS2: WM_CREATE %x", hwnd));
598 win32wnd = (Win32BaseWindow *)teb->o.odin.newWindow;
599 win32wnd->addRef();
600 teb->o.odin.newWindow = 0;
601 if(win32wnd->MsgCreate(hwnd) == FALSE)
602 {
603 rc = (MRESULT)TRUE; //discontinue window creation
604 break;
605 }
606
607 //Create CD notification window
608 if(hwndCD == 0 && fEnableCDPolling) {
609 hwndCD = WinCreateWindow(HWND_DESKTOP, WIN32_CDCLASS,
610 NULL, 0, 0, 0, 0, 0,
611 HWND_DESKTOP, HWND_TOP, 0, NULL, NULL);
612 }
613
614 createfail:
615 rc = (MRESULT)FALSE;
616 break;
617 }
618
619 case WM_QUIT:
620 dprintf(("OS2: WM_QUIT %x", hwnd));
621 win32wnd->MsgQuit();
622 break;
623
624 case WM_CLOSE:
625 dprintf(("OS2: WM_CLOSE %x", hwnd));
626 win32wnd->MsgClose();
627 break;
628
629 case WM_DESTROY:
630 dprintf(("OS2: WM_DESTROY %x", hwnd));
631 win32wnd->MsgDestroy();
632 WinSetVisibleRegionNotify(hwnd, FALSE);
633 goto RunDefWndProc;
634
635 case WM_ENABLE:
636 dprintf(("OS2: WM_ENABLE %x", hwnd));
637 break;
638
639 case WM_SHOW:
640 dprintf(("OS2: WM_SHOW %x %d", hwnd, mp1));
641 win32wnd->MsgShow((ULONG)mp1);
642 break;
643
644 case WM_ACTIVATE:
645 {
646 ULONG flags = WinQueryWindowULong(hwnd, OFFSET_WIN32FLAGS);
647
648 dprintf(("OS2: WM_ACTIVATE %x %x %x", hwnd, mp1, mp2));
649 WinSetWindowULong(hwnd, OFFSET_WIN32FLAGS, SHORT1FROMMP(mp1) ? (flags | WINDOWFLAG_ACTIVE):(flags & ~WINDOWFLAG_ACTIVE));
650 if(win32wnd->IsWindowCreated())
651 {
652 win32wnd->MsgActivate((LOWORD(pWinMsg->wParam) == WA_ACTIVE_W) ? 1 : 0, HIWORD(pWinMsg->wParam), pWinMsg->lParam, (HWND)mp2);
653 }
654 break;
655 }
656
657 case WM_SIZE:
658 {
659 dprintf(("OS2: WM_SIZE (%d,%d) (%d,%d)", SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), SHORT1FROMMP(mp1), SHORT2FROMMP(mp1)));
660 win32wnd->SetVisibleRegionChanged(TRUE);
661 goto RunDefWndProc;
662 }
663
664
665 case WM_VRNENABLED:
666 {
667 dprintf(("OS2: WM_VRNENABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
668 //Always call handler; even if mp1 is 0. If we don't do this, the
669 //DivX 4 player will never be allowed to draw after putting another window
670 //on top of it.
671
672 win32wnd->callVisibleRgnNotifyProc(TRUE);
673
674 //Workaround for PM/GPI bug when moving/sizing a window with open DCs
675 //
676 //Windows applictions often get a DC and keep it open for the duration
677 //of the application. When the DC's window is moved (full window dragging on)
678 //PM/GPI doesn't seem to update the DC properly/in time.
679 //This can result is visible distortions on the screen.
680 //Debugging showed that querying the visible region of a DC will cure
681 //this problem (GPI probably recalculates the visible region).
682 int nrdcs = 0;
683 HDC hdcWindow[MAX_OPENDCS];
684
685 if(win32wnd->queryOpenDCs(hdcWindow, MAX_OPENDCS, &nrdcs))
686 {
687 RECTL rcl = {0,0,1,1};
688 HRGN hrgnRect;
689
690 for(int i=0;i<nrdcs;i++) {
691 dprintf(("Recalc visible region of DC %x for window %x", hdcWindow[i], win32wnd->getWindowHandle()));
692 hrgnRect = GreCreateRectRegion(hdcWindow[i], &rcl, 1);
693 GreCopyClipRegion(hdcWindow[i], hrgnRect, 0, COPYCRGN_VISRGN);
694 GreDestroyRegion(hdcWindow[i], hrgnRect);
695 }
696 }
697
698 //Workaround END
699
700 if(!win32wnd->isComingToTop() && ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == WS_EX_TOPMOST_W))
701 {
702 HWND hwndrelated;
703 Win32BaseWindow *topwindow;
704
705 win32wnd->setComingToTop(TRUE);
706
707 hwndrelated = WinQueryWindow(hwnd, QW_PREV);
708 dprintf(("WM_VRNENABLED hwndrelated = %x (hwnd=%x)", hwndrelated, hwnd));
709 topwindow = Win32BaseWindow::GetWindowFromOS2Handle(hwndrelated);
710 if(topwindow == NULL || ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == 0)) {
711 //put window at the top of z order
712 WinSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
713 }
714 if(topwindow) RELEASE_WNDOBJ(topwindow);
715
716 win32wnd->setComingToTop(FALSE);
717 break;
718 }
719 goto RunDefWndProc;
720 }
721
722 case WM_VRNDISABLED:
723 {
724 dprintf(("OS2: WM_VRNDISABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
725 //visible region is about to change or WinLockWindowUpdate called
726 //suspend window drawing
727
728 win32wnd->callVisibleRgnNotifyProc(FALSE);
729 goto RunDefWndProc;
730 }
731
732 case WIN32APP_DDRAWFULLSCREEN:
733 //Changing the size of the win32 window in SetCooperativeLevel can
734 //fail if this happens during WM_ADJUSTWINDOWPOS
735 //NOTE: This is not a good solution, but a proper fix is more difficult
736 // with the current window mess
737 dprintf(("WIN32APP_DDRAWFULLSCREEN %x (%d,%d)", win32wnd->getWindowHandle(), mp1, mp2));
738 SetWindowPos(win32wnd->getWindowHandle(), HWND_TOP_W, 0, 0, (DWORD)mp1, (DWORD)mp2, 0);
739 ShowWindow(win32wnd->getWindowHandle(), SW_SHOW_W);
740 break;
741
742 case WIN32APP_CHNGEFRAMECTRLS:
743 {
744 dprintf(("OS2: WIN32APP_CHANGEFRAMECTRLS"));
745 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), (ULONG)mp1, win32wnd->getExStyle(), (ULONG)mp2);
746 break;
747 }
748
749#ifdef DEBUG
750 case WM_SETFOCUS:
751 {
752 HWND hwndFocus = (HWND)mp1;
753 dprintf(("OS2: WM_SETFOCUS %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
754 if(WinQueryFocus(HWND_DESKTOP) == win32wnd->getOS2FrameWindowHandle()) {
755 dprintf(("WARNING: Focus set to frame window"));
756 }
757 break;
758 }
759#endif
760
761 //Handle all focus processed during WM_FOCUSCHANGED; PM doesn't like focus
762 //changes during focus processing (WM_SETFOCUS). This message is sent
763 //after all focus work has been completed.
764 case WM_FOCUSCHANGED:
765 {
766 HWND hwndFocus = (HWND)mp1;
767 HWND hwndFocusWin32 = OS2ToWin32Handle(hwndFocus);
768
769 dprintf(("OS2: WM_FOCUSCHANGED %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
770
771 //PM doesn't allow SetFocus calls during WM_SETFOCUS message processing;
772 //must delay this function call
773
774 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC)
775 {
776 //another (non-win32) application's window
777 //set to NULL (allowed according to win32 SDK) to avoid problems
778 hwndFocus = 0;
779 hwndFocusWin32 = 0;
780 }
781 if((ULONG)mp2 == TRUE) {
782 recreateCaret(hwndFocusWin32);
783 win32wnd->MsgSetFocus(hwndFocusWin32);
784 }
785 else {
786 //If SetFocus(0) was called, then the window has already received
787 //a WM_KILLFOCUS; don't send another one
788 if(!fIgnoreKeystrokes) {
789 win32wnd->MsgKillFocus(OS2ToWin32Handle(hwndFocus));
790 }
791 else dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
792 }
793 break;
794 }
795
796 //**************************************************************************
797 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
798 //**************************************************************************
799
800 case WM_BUTTON1DOWN:
801 case WM_BUTTON1UP:
802 case WM_BUTTON1DBLCLK:
803 case WM_BUTTON2DOWN:
804 case WM_BUTTON2UP:
805 case WM_BUTTON2DBLCLK:
806 case WM_BUTTON3DOWN:
807 case WM_BUTTON3UP:
808 case WM_BUTTON3DBLCLK:
809 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
810 RELEASE_WNDOBJ(win32wnd);
811 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
812 }
813 if(win32wnd)
814 win32wnd->MsgButton(pWinMsg);
815
816 rc = (MRESULT)TRUE;
817 break;
818
819 case WM_BUTTON2MOTIONSTART:
820 case WM_BUTTON2MOTIONEND:
821 case WM_BUTTON2CLICK:
822 case WM_BUTTON1MOTIONSTART:
823 case WM_BUTTON1MOTIONEND:
824 case WM_BUTTON1CLICK:
825 case WM_BUTTON3MOTIONSTART:
826 case WM_BUTTON3MOTIONEND:
827 case WM_BUTTON3CLICK:
828 rc = (MRESULT)TRUE;
829 break;
830
831 case WM_MOUSEMOVE:
832 {
833 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
834 RELEASE_WNDOBJ(win32wnd);
835 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
836 }
837 if(win32wnd)
838 win32wnd->MsgMouseMove(pWinMsg);
839 break;
840 }
841
842 case WM_CONTROL:
843 goto RunDefWndProc;
844
845 case WM_COMMAND:
846 dprintf(("OS2: WM_COMMAND %x %x %x", hwnd, mp1, mp2));
847 win32wnd->DispatchMsgA(pWinMsg);
848 break;
849
850 case WM_SYSCOMMAND:
851 dprintf(("OS2: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
852 win32wnd->DispatchMsgA(pWinMsg);
853 break;
854
855 case WM_RENDERFMT:
856 case WM_RENDERALLFMTS:
857 case WM_DESTROYCLIPBOARD:
858 case WM_DRAWCLIPBOARD:
859 win32wnd->DispatchMsgA(pWinMsg);
860 break;
861
862 case WM_CHAR_SPECIAL:
863 /* NO BREAK! FALLTHRU CASE! */
864
865 case WM_CHAR:
866 dprintf(("OS2: WM_CHAR %x %x %x, %x %x focus wnd %x", win32wnd->getWindowHandle(), mp1, mp2, pWinMsg->wParam, pWinMsg->lParam, WinQueryFocus(HWND_DESKTOP)));
867 win32wnd->MsgChar(pWinMsg);
868 break;
869
870 case WM_TIMER:
871 dprintf(("OS2: WM_TIMER %x %x time %x", win32wnd->getWindowHandle(), pWinMsg->wParam, GetTickCount()));
872 win32wnd->DispatchMsgA(pWinMsg);
873 goto RunDefWndProc;
874
875 case WM_SETWINDOWPARAMS:
876 {
877 WNDPARAMS *wndParams = (WNDPARAMS *)mp1;
878
879 dprintf(("OS2: WM_SETWINDOWPARAMS %x", hwnd));
880 if(wndParams->fsStatus & WPM_TEXT) {
881 win32wnd->MsgSetText(wndParams->pszText, wndParams->cchText);
882 }
883 goto RunDefWndProc;
884 }
885
886 case WM_QUERYWINDOWPARAMS:
887 {
888 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
889 ULONG textlen;
890 PSZ wintext;
891
892 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
893 {
894 if(wndpars->fsStatus & WPM_TEXT)
895 win32wnd->MsgGetText(wndpars->pszText, wndpars->cchText);
896 if(wndpars->fsStatus & WPM_CCHTEXT)
897 wndpars->cchText = win32wnd->MsgGetTextLength();
898
899 wndpars->fsStatus = 0;
900 wndpars->cbCtlData = 0;
901 wndpars->cbPresParams = 0;
902 rc = (MRESULT)TRUE;
903 break;
904 }
905 goto RunDefWndProc;
906 }
907
908 case WM_PAINT:
909 {
910 RECTL rectl;
911 BOOL rc;
912
913 win32wnd->checkForDirtyUpdateRegion();
914
915 rc = WinQueryUpdateRect(hwnd, &rectl);
916 dprintf(("OS2: WM_PAINT %x (%d,%d) (%d,%d) rc=%d", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop, rc));
917
918 if(rc && win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
919 rectl.yBottom != rectl.yTop) && !IsIconic(win32wnd->GetTopParent()))
920 {
921 win32wnd->DispatchMsgA(pWinMsg);
922 if(WinQueryUpdateRect(hwnd, NULL) == TRUE)
923 {//the application didn't validate the update region; Windows
924 //will only send a WM_PAINT once until another part of the
925 //window is invalidated. Unfortunately PM keeps on sending
926 //WM_PAINT messages until we validate the update region.
927
928 win32wnd->saveAndValidateUpdateRegion();
929 }
930 }
931 else goto RunDefWndProc;
932 break;
933 }
934
935 case WM_ERASEBACKGROUND:
936 {
937 dprintf(("OS2: WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
938 rc = (MRESULT)FALSE;
939 break;
940 }
941
942 case WM_CALCVALIDRECTS:
943 dprintf(("OS2: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
944 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
945 break;
946
947 case WM_REALIZEPALETTE:
948 {
949 dprintf(("OS2: WM_REALIZEPALETTE %x", win32wnd->getWindowHandle()));
950 win32wnd->DispatchMsgA(pWinMsg);
951 break;
952 }
953
954 case WM_HSCROLL:
955 case WM_VSCROLL:
956 dprintf(("OS2: %s %x %x %x", (msg == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL", win32wnd->getWindowHandle(), mp1, mp2));
957 win32wnd->DispatchMsgA(pWinMsg);
958 break;
959
960 case DM_DRAGOVER:
961 {
962 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
963 PDRAGITEM pDragItem;
964 USHORT sxDrop = SHORT1FROMMP(mp2);
965 USHORT syDrop = SHORT2FROMMP(mp2);
966
967 dprintf(("OS2: DM_DRAGOVER %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
968
969 if(fDragDropDisabled) {
970 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
971 break;
972 }
973
974 //does this window accept dropped files?
975 if(!DragDropAccept(win32wnd->getWindowHandle())) {
976 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
977 break;
978 }
979
980 if(PMDragValidate(pDragInfo) == FALSE) {
981 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
982 break;
983 }
984 if(win32wnd->isDragDropActive() == FALSE) {
985 ULONG ulBytes, cItems;
986 char *pszFiles;
987
988 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
989 if(pszFiles) {
990 POINT point = {sxDrop, syDrop};
991 if(DragDropDragEnter(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes, DROPEFFECT_COPY_W) == FALSE) {
992 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
993 }
994 else {
995 fDragDropActive = TRUE;
996 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
997 win32wnd->setDragDropActive(TRUE);
998 }
999 free(pszFiles);
1000 }
1001 else {
1002 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1003 }
1004 }
1005 else {
1006 if(DragDropDragOver(win32wnd->getWindowHandle(), DROPEFFECT_COPY_W) == FALSE) {
1007 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1008 }
1009 else rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1010 }
1011 break;
1012 }
1013
1014 case DM_DRAGLEAVE:
1015 {
1016 dprintf(("OS2: DM_DRAGLEAVE %x", win32wnd->getWindowHandle()));
1017
1018 if(fDragDropDisabled) {
1019 break;
1020 }
1021
1022 fDragDropActive = FALSE;
1023
1024 //does this window accept dropped files?
1025 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1026 break;
1027 }
1028
1029 DragDropDragLeave(win32wnd->getWindowHandle());
1030 win32wnd->setDragDropActive(FALSE);
1031 break;
1032 }
1033
1034 case DM_DROP:
1035 {
1036 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
1037 PDRAGITEM pDragItem;
1038 USHORT sxDrop = SHORT1FROMMP(mp2);
1039 USHORT syDrop = SHORT2FROMMP(mp2);
1040 USHORT usIndicator, usOp;
1041
1042 dprintf(("OS2: DM_DROP %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
1043
1044 fDragDropActive = FALSE;
1045 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1046
1047 if(fDragDropDisabled) {
1048 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1049 break;
1050 }
1051
1052 //does this window accept dropped files?
1053 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1054 break;
1055 }
1056
1057 ULONG ulBytes, cItems;
1058 char *pszFiles;
1059
1060 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
1061 if(pszFiles) {
1062 POINT point = {sxDrop, syDrop};
1063 if(DragDropFiles(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes) == FALSE) {
1064 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1065 }
1066 else {
1067 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1068 win32wnd->setDragDropActive(FALSE);
1069 }
1070 free(pszFiles);
1071 }
1072 else {
1073 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1074 }
1075 break;
1076 }
1077
1078 case DM_RENDER:
1079 {
1080 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1081
1082 dprintf(("OS2: DM_RENDER %x", pDragTransfer));
1083
1084 rc = (MRESULT)OSLibRenderFormat(pDragTransfer);
1085 break;
1086 }
1087
1088 case DM_RENDERPREPARE:
1089 {
1090 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1091
1092 dprintf(("OS2: DM_RENDERPREPARE %x", pDragTransfer));
1093 break;
1094 }
1095
1096 case DM_ENDCONVERSATION:
1097 {
1098 dprintf(("OS2: DM_ENDCONVERSATION"));
1099 rc = (MRESULT)OSLibEndConversation();
1100 break;
1101 }
1102
1103 case DM_RENDERFILE:
1104 {
1105 dprintf(("OS2: DM_ENDCONVERSATION"));
1106 rc = FALSE;
1107 break;
1108 }
1109
1110 case WM_DDE_INITIATE:
1111 case WM_DDE_INITIATEACK:
1112 case WM_DDE_REQUEST:
1113 case WM_DDE_ACK:
1114 case WM_DDE_DATA:
1115 case WM_DDE_ADVISE:
1116 case WM_DDE_UNADVISE:
1117 case WM_DDE_POKE:
1118 case WM_DDE_EXECUTE:
1119 case WM_DDE_TERMINATE:
1120 dprintf(("OS2: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
1121 goto RunDefWndProc;
1122
1123 case WM_INITMENU:
1124 case WM_MENUSELECT:
1125 case WM_MENUEND:
1126 case WM_NEXTMENU:
1127 case WM_SYSCOLORCHANGE:
1128 case WM_SYSVALUECHANGED:
1129 case WM_SETSELECTION:
1130 case WM_PPAINT:
1131 case WM_PSETFOCUS:
1132 case WM_PSYSCOLORCHANGE:
1133 case WM_PSIZE:
1134 case WM_PACTIVATE:
1135 case WM_PCONTROL:
1136 case WM_HELP:
1137 case WM_APPTERMINATENOTIFY:
1138 case WM_PRESPARAMCHANGED:
1139 case WM_DRAWITEM:
1140 case WM_MEASUREITEM:
1141 case WM_CONTROLPOINTER:
1142 case WM_QUERYDLGCODE:
1143 case WM_SUBSTITUTESTRING:
1144 case WM_MATCHMNEMONIC:
1145 case WM_SAVEAPPLICATION:
1146 case WM_SEMANTICEVENT:
1147 default:
1148 dprintf2(("OS2: RunDefWndProc hwnd %x msg %x mp1 %x mp2 %x", hwnd, msg, mp1, mp2));
1149 goto RunDefWndProc;
1150 }
1151 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1152 RestoreOS2TIB();
1153 ODIN_UnsetExceptionHandler(&exceptRegRec);
1154
1155#ifdef DEBUG
1156 dbg_ThreadPopCall();
1157#endif
1158 return (MRESULT)rc;
1159
1160RunDefWndProc:
1161// dprintf(("OS2: RunDefWndProc msg %x for %x", msg, hwnd));
1162 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1163
1164 RestoreOS2TIB();
1165 ODIN_UnsetExceptionHandler(&exceptRegRec);
1166
1167#ifdef DEBUG
1168 dbg_ThreadPopCall();
1169#endif
1170 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1171} /* End of Win32WindowProc */
1172//******************************************************************************
1173//******************************************************************************
1174MRESULT EXPENTRY Win32FrameWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1175{
1176 POSTMSG_PACKET *postmsg;
1177 OSLIBPOINT point, ClientPoint;
1178 Win32BaseWindow *win32wnd;
1179 TEB *teb;
1180 MRESULT rc = 0;
1181 MSG winMsg, *pWinMsg;
1182 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
1183
1184#ifdef DEBUG
1185 dbg_ThreadPushCall("Win32FrameWindowProc");
1186#endif
1187
1188 ODIN_SetExceptionHandler(&exceptRegRec);
1189 //Restore our FS selector
1190 SetWin32TIB();
1191
1192 // BEGIN NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- BEGIN
1193 teb = GetThreadTEB();
1194 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
1195
1196 // do some sanity checking here:
1197 // - we need to have a TEB handle
1198 // - unless this is WM_CREATE (the very first message), there has to be
1199 // a USER32 window object for this window handle
1200 // - thread must not be suspended in WaitMessage
1201 if(!teb || (msg != WM_CREATE && win32wnd == NULL) || teb->o.odin.fWaitMessageSuspend) {
1202 if(teb && teb->o.odin.fWaitMessageSuspend)
1203 dprintf(("PMFRAME: fWaitMessageSuspend window %x msg %x -> run default frame proc", hwnd, msg));
1204 else dprintf(("PMFRAME: Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
1205 goto RunDefFrameWndProc;
1206 }
1207//// if(teb->o.odin.fIgnoreMsgs) {
1208//// goto RunDefWndProc;
1209//// }
1210
1211 // check if the message state counter in the TEB is odd
1212 // This means the message has been sent directly from PM to our message
1213 // handler (so it is the first time we know about this PM message).
1214 // If this is the case, we have to translate it here to a Win32
1215 // message first. The other case is that the message is the result of a
1216 // WinDispatchMsg call and therefore has already been translated.
1217 if((teb->o.odin.msgstate & 1) == 0)
1218 {//message that was sent directly to our window proc handler; translate it here
1219 QMSG qmsg;
1220
1221 qmsg.msg = msg;
1222 qmsg.hwnd = hwnd;
1223 qmsg.mp1 = mp1;
1224 qmsg.mp2 = mp2;
1225 qmsg.time = WinQueryMsgTime(teb->o.odin.hab);
1226 WinQueryMsgPos(teb->o.odin.hab, &qmsg.ptl);
1227 qmsg.reserved = 0;
1228
1229 if(OS2ToWinMsgTranslate((PVOID)teb, &qmsg, &winMsg, FALSE, MSG_REMOVE) == FALSE)
1230 {//message was not translated
1231 memset(&winMsg, 0, sizeof(MSG));
1232 }
1233 pWinMsg = &winMsg;
1234 }
1235 else {
1236 // message has already been translated before (GetMessage/PeekMessage).
1237 // Use the translated information. Flip the translation flag.
1238 pWinMsg = &teb->o.odin.msg;
1239 teb->o.odin.msgstate++;
1240 }
1241 // END NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- END
1242
1243 switch( msg )
1244 {
1245 case WM_CREATE:
1246 {
1247 //WM_CREATE handled during client window creation
1248 dprintf(("PMFRAME: WM_CREATE %x", hwnd));
1249 goto RunDefFrameWndProc;
1250 }
1251
1252//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
1253// handler; must postpone it, so do it here
1254 case WIN32APP_POSTPONEDESTROY:
1255 OSLibWinDestroyWindow(hwnd);
1256 break;
1257//hack end
1258
1259#ifdef DEBUG
1260 case WM_CLOSE:
1261 {
1262 dprintf(("PMFRAME: WM_CLOSE %x", hwnd));
1263 goto RunDefFrameWndProc;
1264 }
1265#endif
1266
1267 case WM_PAINT:
1268 {
1269 RECTL rectl;
1270
1271 HPS hps = WinBeginPaint(hwnd, NULL, &rectl);
1272 dprintf(("PMFRAME: WM_PAINT %x (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop));
1273
1274 if(win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
1275 rectl.yBottom != rectl.yTop))
1276 {
1277 PRECT pClient = win32wnd->getClientRectPtr();
1278 PRECT pWindow = win32wnd->getWindowRect();
1279
1280 if(!(pClient->left == 0 && pClient->top == 0 &&
1281 win32wnd->getClientHeight() == win32wnd->getWindowHeight() &&
1282 win32wnd->getClientWidth() == win32wnd->getWindowWidth()))
1283 {
1284 RECT rectUpdate;
1285
1286 mapOS2ToWin32Rect(win32wnd->getWindowHeight(), (PRECTLOS2)&rectl, &rectUpdate);
1287 win32wnd->MsgNCPaint(&rectUpdate);
1288 }
1289 }
1290 WinEndPaint(hps);
1291 break;
1292 }
1293
1294 case WM_ERASEBACKGROUND:
1295 {
1296 dprintf(("PMFRAME:WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
1297 rc = (MRESULT)FALSE;
1298 break;
1299 }
1300
1301 //**************************************************************************
1302 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
1303 //**************************************************************************
1304
1305 case WM_BUTTON1DOWN:
1306 case WM_BUTTON1UP:
1307 case WM_BUTTON1DBLCLK:
1308 case WM_BUTTON2DOWN:
1309 case WM_BUTTON2UP:
1310 case WM_BUTTON2DBLCLK:
1311 case WM_BUTTON3DOWN:
1312 case WM_BUTTON3UP:
1313 case WM_BUTTON3DBLCLK:
1314 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1315 RELEASE_WNDOBJ(win32wnd);
1316 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1317 }
1318 if(win32wnd)
1319 win32wnd->MsgButton(pWinMsg);
1320
1321 rc = (MRESULT)TRUE;
1322 break;
1323
1324 case WM_BUTTON2MOTIONSTART:
1325 case WM_BUTTON2MOTIONEND:
1326 case WM_BUTTON2CLICK:
1327 case WM_BUTTON1MOTIONSTART:
1328 case WM_BUTTON1MOTIONEND:
1329 case WM_BUTTON1CLICK:
1330 case WM_BUTTON3MOTIONSTART:
1331 case WM_BUTTON3MOTIONEND:
1332 case WM_BUTTON3CLICK:
1333 rc = (MRESULT)TRUE;
1334 break;
1335
1336 case WM_MOUSEMOVE:
1337 {
1338 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1339 RELEASE_WNDOBJ(win32wnd);
1340 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1341 }
1342 if(win32wnd)
1343 win32wnd->MsgMouseMove(pWinMsg);
1344 break;
1345 }
1346
1347 case WM_CHAR_SPECIAL_CONSOLE_BREAK:
1348 {
1349 //ignore this message. don't forward it to the default PM frame window handler
1350 //as that one sends it to the client. as a result we end up translating
1351 //it twice
1352 break;
1353 }
1354
1355 case WM_ADJUSTWINDOWPOS:
1356 {
1357 PSWP pswp = (PSWP)mp1;
1358 SWP swpOld;
1359 WINDOWPOS wp,wpOld;
1360 ULONG ulFlags;
1361 ULONG ret = 0;
1362 HWND hParent = NULLHANDLE, hwndAfter;
1363
1364 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1365
1366 ulFlags = pswp->fl;
1367
1368 if(win32wnd->IsParentChanging()) {
1369 rc = 0;
1370 break;
1371 }
1372
1373 //@@PF all commands from minimized window viewer or from Ctrl-Esc
1374 //are 'pure' and should be handled only by DeFrameProc - this is weird
1375 //but without them we will not have results. Pure = plain flag of restore/minimize/maximize
1376 if((pswp->fl == SWP_MINIMIZE) || (pswp->fl & SWP_RESTORE)) {
1377 // note the purity of SWP no other SWP_FLAGS allowed
1378 goto RunDefFrameWndProc;
1379 }
1380
1381 if(pswp->fl & SWP_NOADJUST) {
1382 //ignore weird messages (TODO: why are they sent?)
1383 dprintf(("WARNING: WM_ADJUSTWINDOWPOS with SWP_NOADJUST flag!!"));
1384 break;
1385
1386 }
1387
1388 //PF Pure flags should not cause any subsequent messages to win32 windows
1389 //we should route them to DefFrameWndProc and check highlight.
1390
1391 if ((pswp->fl == SWP_FOCUSACTIVATE) || (pswp->fl == SWP_FOCUSDEACTIVATE))
1392 {
1393 if (fOS2Look)
1394 {
1395 if(pswp->fl == SWP_FOCUSACTIVATE)
1396 {
1397 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1398 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1399 }
1400 else
1401 {
1402 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1403 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1404 }
1405 }
1406 goto RunDefFrameWndProc;
1407 }
1408
1409 //CB: show dialog in front of owner
1410 if (win32wnd->IsModalDialogOwner())
1411 {
1412 dprintf(("win32wnd->IsModalDialogOwner %x", win32wnd->getWindowHandle()));
1413 pswp->fl |= SWP_ZORDER;
1414 pswp->hwndInsertBehind = win32wnd->getOS2HwndModalDialog();
1415 if (pswp->fl & SWP_ACTIVATE)
1416 {
1417 pswp->fl &= ~SWP_ACTIVATE;
1418 WinSetWindowPos(win32wnd->getOS2HwndModalDialog(),0,0,0,0,0,SWP_ACTIVATE);
1419 }
1420 }
1421
1422 if(!win32wnd->CanReceiveSizeMsgs())
1423 break;
1424
1425 WinQueryWindowPos(hwnd, &swpOld);
1426 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
1427 if (win32wnd->isChild()) {
1428 if(win32wnd->getParent()) {
1429 hParent = win32wnd->getParent()->getOS2WindowHandle();
1430 }
1431 else goto RunDefFrameWndProc;
1432 }
1433 }
1434 hwndAfter = pswp->hwndInsertBehind;
1435 if(win32wnd->getParent()) {
1436 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(), hwnd);
1437 }
1438 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1439
1440 wp.hwnd = win32wnd->getWindowHandle();
1441 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1442 {
1443 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1444 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1445 if(wndAfter) {
1446 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1447 RELEASE_WNDOBJ(wndAfter);
1448 }
1449 else wp.hwndInsertAfter = HWND_TOP_W;
1450 }
1451
1452 wpOld = wp;
1453 win32wnd->MsgPosChanging((LPARAM)&wp);
1454
1455 if(win32wnd->getOldStyle() != win32wnd->getStyle())
1456 {
1457 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), win32wnd->getStyle(), win32wnd->getExStyle(), win32wnd->getStyle());
1458 if(fOS2Look) {
1459 DWORD dwOldStyle = win32wnd->getOldStyle();
1460 DWORD dwStyle = win32wnd->getStyle();
1461
1462 win32wnd->setOldStyle(dwStyle);
1463 if((dwOldStyle & WS_MINIMIZE_W) && !(dwStyle & WS_MINIMIZE_W)) {
1464 //SC_RESTORE -> SC_MINIMIZE
1465 dprintf(("%x -> SC_RESTORE -> SC_MINIMIZE", win32wnd->getWindowHandle()));
1466 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_RESTORE, SC_MINIMIZE, hbmFrameMenu[PMMENU_MINBUTTON]);
1467 if(dwStyle & WS_MAXIMIZE_W) {
1468 //SC_MAXIMIZE -> SC_RESTORE
1469 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (1)", win32wnd->getWindowHandle()));
1470 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1471 }
1472 }
1473 else
1474 if((dwOldStyle & WS_MAXIMIZE_W) && !(dwStyle & WS_MAXIMIZE_W)) {
1475 //SC_RESTORE -> SC_MAXIMIZE
1476 dprintf(("%x -> SC_RESTORE -> SC_MAXIMIZE", win32wnd->getWindowHandle()));
1477 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_RESTORE, SC_MAXIMIZE, hbmFrameMenu[PMMENU_MAXBUTTON]);
1478 }
1479 else
1480 if(!(dwOldStyle & WS_MINIMIZE_W) && (dwStyle & WS_MINIMIZE_W)) {
1481 //SC_MINIMIZE -> SC_RESTORE
1482 dprintf(("%x -> SC_MINIMIZE -> SC_RESTORE", win32wnd->getWindowHandle()));
1483 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_MINIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1484 }
1485 else
1486 if(!(dwOldStyle & WS_MAXIMIZE_W) && (dwStyle & WS_MAXIMIZE_W)) {
1487 //SC_MAXIMIZE -> SC_RESTORE
1488 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (2)", win32wnd->getWindowHandle()));
1489 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1490 }
1491 }
1492 }
1493
1494 if ((wp.hwndInsertAfter != wpOld.hwndInsertAfter) ||
1495 (wp.x != wpOld.x) || (wp.y != wpOld.y) || (wp.cx != wpOld.cx) || (wp.cy != wpOld.cy) || (wp.flags != wpOld.flags))
1496 {
1497 ULONG flags = pswp->fl; //make a backup copy; OSLibMapWINDOWPOStoSWP will modify it
1498
1499 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1500 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1501
1502 if(win32wnd->getParent()) {
1503 OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, win32wnd->getParent()->getClientHeight(),
1504 hwnd);
1505 }
1506 else OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1507
1508 dprintf(("%x (%d,%d), (%d,%d)", pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
1509
1510 //OSLibMapWINDOWPOStoSWP can add flags, but we must not let it remove flags!
1511 if(pswp->fl & SWP_SIZE)
1512 flags |= SWP_SIZE;
1513
1514 if(pswp->fl & SWP_MOVE)
1515 flags |= SWP_MOVE;
1516
1517 pswp->fl = flags; //restore flags
1518
1519 pswp->fl |= SWP_NOADJUST;
1520 pswp->hwndInsertBehind = hwndAfter;
1521 pswp->hwnd = hwnd;
1522
1523 ret = 0xf;
1524 }
1525adjustend:
1526 //The next part needs to be done for top-level windows only
1527 if(!((win32wnd->getStyle() & (WS_POPUP_W|WS_CHILD_W)) == WS_CHILD_W))
1528 {
1529 //Setting these flags is necessary to avoid activation/focus problems
1530 if(ulFlags & SWP_DEACTIVATE) {
1531 ret |= AWP_DEACTIVATE;
1532 }
1533 if(ulFlags & SWP_ACTIVATE)
1534 {
1535 if(ulFlags & SWP_ZORDER) {
1536 dprintf(("Set FF_NOACTIVATESWP"));
1537 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
1538 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags | FF_NOACTIVATESWP);
1539 }
1540
1541 if(!(ulFlags & SWP_SHOW))
1542 {
1543 ret |= AWP_ACTIVATE;
1544 }
1545 else
1546 {
1547 FrameSetFocus(hwnd);
1548 }
1549 }
1550 }
1551 else {
1552 if(ulFlags & (SWP_ACTIVATE|SWP_FOCUSACTIVATE))
1553 {
1554 win32wnd->MsgChildActivate(TRUE);
1555 if(fOS2Look) {
1556 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1557 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1558 }
1559 }
1560 else
1561 if(ulFlags & (SWP_DEACTIVATE|SWP_FOCUSDEACTIVATE))
1562 {
1563 win32wnd->MsgChildActivate(FALSE);
1564 if(fOS2Look) {
1565 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1566 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1567 }
1568 }
1569 }
1570#ifdef DEBUG
1571 dprintf(("WM_ADJUSTWINDOWPOS ret %x flags %x", ret, WinQueryWindowUShort(hwnd, QWS_FLAGS)));
1572 if(ret == 0x0f) {
1573 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1574 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1575 }
1576#endif
1577 rc = (MRESULT)ret;
1578 break;
1579 }
1580
1581 case WM_WINDOWPOSCHANGED:
1582 {
1583 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
1584 SWP swpOld = *(pswp + 1);
1585 WINDOWPOS wp;
1586 ULONG flAfp = (ULONG)mp2;
1587 HWND hParent = NULLHANDLE;
1588 RECTL rect;
1589
1590 dprintf(("PMFRAME:WM_WINDOWPOSCHANGED (%x) %x %x (%s) (%d,%d) (%d,%d) z %x", mp2, win32wnd->getWindowHandle(), pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy, Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind)));
1591 if(win32wnd->IsParentChanging()) {
1592 goto PosChangedEnd;
1593 }
1594
1595 // PF: MDI window is not a common OS/2 frame window so we just skipped all
1596 // PM default processing for it that basicly moved this window to 0,0 point
1597 // and changed frame controls. Now do our own processing.
1598
1599 if ((pswp->fl & SWP_MAXIMIZE) && (win32wnd->getExStyle() & WS_EX_MDICHILD_W))
1600 {
1601 SendMessageA(win32wnd->getWindowHandle(), WM_SYSCOMMAND_W, SC_MAXIMIZE_W, 0);
1602 goto PosChangedEnd;
1603 }
1604
1605 //SvL: When a window is made visible, then we don't receive a
1606 // WM_VRNENABLED message (for some weird reason)
1607 if(pswp->fl & SWP_SHOW) {
1608 win32wnd->callVisibleRgnNotifyProc(TRUE);
1609 }
1610 else
1611 if(pswp->fl & SWP_HIDE) {
1612 win32wnd->callVisibleRgnNotifyProc(FALSE);
1613 }
1614
1615 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
1616 {
1617 if(win32wnd->isChild())
1618 {
1619 if(win32wnd->getParent()) {
1620 hParent = win32wnd->getParent()->getOS2WindowHandle();
1621 }
1622 else goto PosChangedEnd; //parent has just been destroyed
1623 }
1624 }
1625
1626
1627 if(win32wnd->getParent()) {
1628 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1629 hwnd);
1630 }
1631 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1632
1633 wp.hwnd = win32wnd->getWindowHandle();
1634 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1635 {
1636 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1637 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1638 if(wndAfter) {
1639 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1640 RELEASE_WNDOBJ(wndAfter);
1641 }
1642 else wp.hwndInsertAfter = HWND_TOP_W;
1643 }
1644
1645 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0)
1646 {
1647 if(pswp->fl & SWP_RESTORE && win32wnd->getStyle() & WS_MINIMIZE_W) {
1648 dprintf(("Restoring minimized window %x", win32wnd->getWindowHandle()));
1649 win32wnd->ShowWindow(SW_RESTORE_W);
1650 }
1651 if(pswp->fl & SWP_SHOW) {
1652 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1653 }
1654 else
1655 if(pswp->fl & SWP_HIDE) {
1656 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1657 }
1658 if(pswp->fl & (SWP_SHOW|SWP_HIDE))
1659 {//TODO: necessary for more options? (activate?)
1660 if(win32wnd->CanReceiveSizeMsgs())
1661 win32wnd->MsgPosChanged((LPARAM)&wp);
1662 }
1663
1664 //MUST call the old frame window proc!
1665 goto RunDefFrameWndProc;
1666 }
1667
1668 if(pswp->fl & SWP_SHOW) {
1669 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1670 }
1671 else
1672 if(pswp->fl & SWP_HIDE) {
1673 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1674 }
1675
1676 if(flAfp & AWP_ACTIVATE)
1677 {
1678 FrameSetFocus(hwnd);
1679 }
1680
1681#ifndef USE_CALCVALIDRECT
1682 if((pswp->fl & (SWP_MOVE | SWP_SIZE)))
1683 {
1684 //CB: todo: use result for WM_CALCVALIDRECTS
1685 //Get old client rectangle (for invalidation of frame window parts later on)
1686 //Use new window height to calculate the client area
1687 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&rect);
1688
1689 //Note: Also updates the new window rectangle
1690 win32wnd->MsgFormatFrame(&wp);
1691
1692 if(win32wnd->isOwnDC()) {
1693 setPageXForm(win32wnd, (pDCData)GpiQueryDCData(win32wnd->getOwnDC()));
1694 }
1695
1696 if(win32wnd->CanReceiveSizeMsgs())
1697 win32wnd->MsgPosChanged((LPARAM)&wp);
1698
1699 if((pswp->fl & SWP_SIZE) && ((pswp->cx != pswpOld->cx) || (pswp->cy != pswpOld->cy)))
1700 {
1701 //redraw the frame (to prevent unnecessary client updates)
1702 BOOL redrawAll = FALSE;
1703
1704 dprintf2(("WM_WINDOWPOSCHANGED: redraw frame"));
1705 if (win32wnd->getWindowClass())
1706 {
1707 DWORD dwStyle = win32wnd->getWindowClass()->getClassLongA(GCL_STYLE_W);
1708
1709 if ((dwStyle & CS_HREDRAW_W) && (pswp->cx != pswpOld->cx))
1710 redrawAll = TRUE;
1711 else
1712 if ((dwStyle & CS_VREDRAW_W) && (pswp->cy != pswpOld->cy))
1713 redrawAll = TRUE;
1714 }
1715 else redrawAll = TRUE;
1716
1717 if(win32wnd->IsMixMaxStateChanging()) {
1718 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1719 redrawAll = TRUE;
1720 }
1721
1722 if (redrawAll)
1723 {
1724 //CB: redraw all children for now
1725 // -> problems with update region if we don't do it
1726 // todo: rewrite whole handling
1727 dprintf(("PMFRAME: WM_WINDOWPOSCHANGED invalidate all"));
1728 WinInvalidateRect(hwnd,NULL,TRUE);
1729 }
1730 else
1731 {
1732 HPS hps = WinGetPS(hwnd);
1733 RECTL frame,client,arcl[4];
1734
1735 WinQueryWindowRect(hwnd,&frame);
1736
1737 //top
1738 arcl[0].xLeft = 0;
1739 arcl[0].xRight = frame.xRight;
1740 arcl[0].yBottom = rect.yTop;
1741 arcl[0].yTop = frame.yTop;
1742 //right
1743 arcl[1].xLeft = rect.xRight;
1744 arcl[1].xRight = frame.xRight;
1745 arcl[1].yBottom = 0;
1746 arcl[1].yTop = frame.yTop;
1747 //left
1748 arcl[2].xLeft = 0;
1749 arcl[2].xRight = rect.xLeft;
1750 arcl[2].yBottom = 0;
1751 arcl[2].yTop = frame.yTop;
1752 //bottom
1753 arcl[3].xLeft = 0;
1754 arcl[3].xRight = frame.xRight;
1755 arcl[3].yBottom = 0;
1756 arcl[3].yTop = rect.yBottom;
1757
1758 HRGN hrgn = GpiCreateRegion(hps,4,(PRECTL)&arcl);
1759
1760 WinInvalidateRegion(hwnd,hrgn,FALSE);
1761 GpiDestroyRegion(hps,hrgn);
1762 WinReleasePS(hps);
1763 }
1764 }
1765 }
1766 else
1767 {
1768#endif //USE_CALCVALIDRECT
1769 if(win32wnd->CanReceiveSizeMsgs())
1770 win32wnd->MsgPosChanged((LPARAM)&wp);
1771#ifndef USE_CALCVALIDRECT
1772 }
1773#endif
1774 //PF This is the final step of PM restoration - should end up
1775 //in default handler.
1776 if (win32wnd->getOldStyle() & WS_MINIMIZE_W && pswp->fl & SWP_RESTORE)
1777 goto RunDefFrameWndProc;
1778
1779 //PF This is the final step of PM minimization - shoukd end up
1780 //in default handler
1781 if (win32wnd->getStyle() & WS_MINIMIZE_W && pswp->fl & SWP_MINIMIZE)
1782 goto RunDefFrameWndProc;
1783
1784PosChangedEnd:
1785 rc = (MRESULT)FALSE;
1786 break;
1787 }
1788
1789 case WM_CALCVALIDRECTS:
1790#ifdef USE_CALCVALIDRECT
1791 {
1792 PRECTL oldRect = (PRECTL)mp1, newRect = oldRect+1;
1793 PSWP pswp = (PSWP)mp2;
1794 SWP swpOld;
1795 WINDOWPOS wp;
1796 RECTL newClientRect, oldClientRect;
1797 ULONG nccalcret;
1798// UINT res = CVR_ALIGNLEFT | CVR_ALIGNTOP;
1799 UINT res = 0;
1800
1801 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1802
1803 //Get old position info
1804 WinQueryWindowPos(hwnd, &swpOld);
1805
1806 if(win32wnd->getParent()) {
1807 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1808 win32wnd->getParent()->getClientRectPtr()->left,
1809 win32wnd->getParent()->getClientRectPtr()->top,
1810 hwnd);
1811 }
1812 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), 0, 0, hwnd);
1813
1814 wp.hwnd = win32wnd->getWindowHandle();
1815 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1816 {
1817 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1818 if(wndAfter) {
1819 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1820 RELEASE_WNDOBJ(wndAfter);
1821 }
1822 else wp.hwndInsertAfter = HWND_TOP_W;
1823 }
1824
1825 //Get old client rectangle
1826 mapWin32ToOS2Rect(oldRect->yTop - oldRect->yBottom, win32wnd->getClientRectPtr(), (PRECTLOS2)&oldClientRect);
1827
1828 //Note: Also updates the new window rectangle
1829 nccalcret = win32wnd->MsgFormatFrame(&wp);
1830
1831 //Get new client rectangle
1832 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&newClientRect);
1833
1834 if(nccalcret == 0) {
1835 res = CVR_ALIGNTOP | CVR_ALIGNLEFT;
1836 }
1837 else {
1838 if(nccalcret & WVR_ALIGNTOP_W) {
1839 res |= CVR_ALIGNTOP;
1840 }
1841 else
1842 if(nccalcret & WVR_ALIGNBOTTOM_W) {
1843 res |= CVR_ALIGNBOTTOM;
1844 }
1845
1846 if(nccalcret & WVR_ALIGNLEFT_W) {
1847 res |= CVR_ALIGNLEFT;
1848 }
1849 else
1850 if(nccalcret & WVR_ALIGNRIGHT_W) {
1851 res |= CVR_ALIGNRIGHT;
1852 }
1853
1854 if(nccalcret & WVR_REDRAW_W) {//WVR_REDRAW_W = (WVR_HREDRAW | WVR_VREDRAW)
1855 res |= CVR_REDRAW;
1856 }
1857 else
1858 if(nccalcret & WVR_VALIDRECTS_W) {
1859 //TODO:
1860 //res = 0;
1861 }
1862 }
1863 if(win32wnd->IsMixMaxStateChanging()) {
1864 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1865 res |= CVR_REDRAW;
1866 }
1867 if(res == (CVR_ALIGNTOP|CVR_ALIGNLEFT)) {
1868 oldRect->xRight -= oldClientRect.xLeft;
1869 oldRect->yBottom += oldClientRect.yBottom;
1870 newRect->xRight -= newClientRect.xLeft;
1871 newRect->yBottom += newClientRect.yBottom;
1872 }
1873 rc = res;
1874 break;
1875 }
1876#else
1877 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1878 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
1879 break;
1880#endif
1881
1882 case WM_CALCFRAMERECT:
1883 dprintf(("PMFRAME:WM_CALCFRAMERECT %x", win32wnd->getWindowHandle()));
1884 rc = (MRESULT)TRUE;
1885 break;
1886
1887 case WM_QUERYCTLTYPE:
1888 // This is a frame window
1889 dprintf(("PMFRAME:WM_QUERYCTLTYPE %x", win32wnd->getWindowHandle()));
1890 rc = (MRESULT)CCT_FRAME;
1891 break;
1892
1893#ifdef DEBUG
1894 case WM_QUERYFOCUSCHAIN:
1895 dprintf2(("PMFRAME:WM_QUERYFOCUSCHAIN %x fsCmd %x (%s) parent %x", win32wnd->getWindowHandle(), SHORT1FROMMP(mp1), DbgPrintQFCFlags(SHORT1FROMMP(mp1)), (mp2) ? OS2ToWin32Handle((DWORD)mp2) : 0));
1896
1897 RestoreOS2TIB();
1898 rc = pfnFrameWndProc(hwnd, msg, mp1, mp2);
1899 SetWin32TIB();
1900 dprintf2(("PMFRAME:WM_QUERYFOCUSCHAIN %x fsCmd %x parent %x returned %x (%x)", win32wnd->getWindowHandle(), SHORT1FROMMP(mp1), (mp2) ? OS2ToWin32Handle((DWORD)mp2) : 0, (rc) ? OS2ToWin32Handle((DWORD)rc) : 0, rc));
1901 break;
1902// goto RunDefFrameWndProc;
1903#endif
1904
1905 case WM_FOCUSCHANGE:
1906 {
1907 HWND hwndFocus = (HWND)mp1;
1908 HWND hwndLoseFocus, hwndGainFocus;
1909 USHORT usSetFocus = SHORT1FROMMP(mp2);
1910 USHORT fsFocusChange = SHORT2FROMMP(mp2);
1911
1912 //Save window that gains focus so we can determine which
1913 //process we lose activation to
1914 hwndFocusChange = (HWND)mp1;
1915
1916 dprintf(("PMFRAME:WM_FOCUSCHANGE %x %x (%x) %x %x", win32wnd->getWindowHandle(), OS2ToWin32Handle(hwndFocus), hwndFocus, usSetFocus, fsFocusChange));
1917 goto RunDefFrameWndProc;
1918 }
1919
1920#ifdef DEBUG
1921 case WM_SETFOCUS:
1922 {
1923 dprintf(("PMFRAME: WM_SETFOCUS %x %x %d -> %x", win32wnd->getWindowHandle(), hwnd, mp2, mp1));
1924 goto RunDefFrameWndProc;
1925 }
1926#endif
1927
1928 case WM_ACTIVATE:
1929 {
1930 HWND hwndTitle;
1931 USHORT flags = WinQueryWindowUShort(hwnd,QWS_FLAGS);
1932
1933 dprintf(("PMFRAME: WM_ACTIVATE %x %x %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle((DWORD)mp2)));
1934 if (win32wnd->IsWindowCreated())
1935 {
1936 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
1937 if(fOS2Look) {
1938 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1939 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, mp1, 0);
1940 }
1941 if(SHORT1FROMMP(mp1) == 0) {
1942 //deactivate
1943 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
1944 }
1945 PID pidThis, pidPartner, pidTemp;
1946 TID tidPartner;
1947 HENUM henum;
1948 HWND hwndEnum;
1949
1950 WinQueryWindowProcess(hwnd, &pidThis, NULL);
1951 WinQueryWindowProcess(hwndFocusChange, &pidPartner, &tidPartner);
1952
1953 if(pidThis != pidPartner) {
1954 //Gain or lose activation to window in other process
1955 //must send WM_ACTIVATEAPP to top-level windows
1956
1957 //Iterate over all child windows of the desktop
1958 henum = WinBeginEnumWindows(HWND_DESKTOP);
1959
1960 while(hwndEnum = WinGetNextWindow(henum))
1961 {
1962 WinQueryWindowProcess(hwndEnum, &pidTemp, NULL);
1963 if(pidTemp == pidThis)
1964 {
1965 SendMessageA(OS2ToWin32Handle(hwndEnum), WM_ACTIVATEAPP_W, (WPARAM)SHORT1FROMMP(mp1), (LPARAM)tidPartner);
1966 }
1967 }
1968 WinEndEnumWindows(henum);
1969 }
1970 if(SHORT1FROMMP(mp1)) {
1971 //activate
1972 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
1973 }
1974
1975 //CB: show owner behind the dialog
1976 if (win32wnd->IsModalDialog())
1977 {
1978 if(win32wnd->getOwner()) {
1979 Win32BaseWindow *topOwner = Win32BaseWindow::GetWindowFromHandle(win32wnd->getOwner()->GetTopParent());
1980
1981 if (topOwner) {
1982 WinSetWindowPos(topOwner->getOS2FrameWindowHandle(),hwnd,0,0,0,0,SWP_ZORDER);
1983 RELEASE_WNDOBJ(topOwner);
1984 }
1985 }
1986 }
1987 }
1988 else
1989 {
1990 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
1991 }
1992 rc = 0;
1993 break;
1994 }
1995
1996 case WM_ENABLE:
1997 dprintf(("PMFRAME: WM_ENABLE %x", hwnd));
1998 win32wnd->MsgEnable(SHORT1FROMMP(mp1));
1999 break;
2000
2001 case WM_SHOW:
2002 dprintf(("PMFRAME: WM_SHOW %x %d", hwnd, mp1));
2003 //show client window
2004 WinShowWindow(win32wnd->getOS2WindowHandle(), (BOOL)mp1);
2005 break;
2006
2007 case WM_QUERYTRACKINFO:
2008 {
2009 PTRACKINFO trackInfo = (PTRACKINFO)mp2;
2010
2011 dprintf(("PMFRAME:WM_QUERYTRACKINFO %x", win32wnd->getWindowHandle()));
2012 trackInfo->cxBorder = 4;
2013 trackInfo->cyBorder = 4;
2014 win32wnd->AdjustTrackInfo((PPOINT)&trackInfo->ptlMinTrackSize,(PPOINT)&trackInfo->ptlMaxTrackSize);
2015 rc = (MRESULT)TRUE;
2016 break;
2017 }
2018
2019 case WM_QUERYBORDERSIZE:
2020 {
2021 PWPOINT size = (PWPOINT)mp1;
2022
2023 dprintf(("PMFRAME:WM_QUERYBORDERSIZE %x", win32wnd->getWindowHandle()));
2024
2025 size->x = 0;
2026 size->y = 0;
2027 rc = (MRESULT)TRUE;
2028 break;
2029 }
2030
2031#ifdef DEBUG
2032 case WM_QUERYFRAMEINFO:
2033 dprintf(("PMFRAME:WM_QUERYFRAMEINFO %x", win32wnd->getWindowHandle()));
2034 goto RunDefFrameWndProc;
2035#endif
2036
2037 case WM_FORMATFRAME:
2038 dprintf(("PMFRAME:WM_FORMATFRAME %x", win32wnd->getWindowHandle()));
2039 break;
2040
2041 case WM_ADJUSTFRAMEPOS:
2042 {
2043 PSWP pswp = (PSWP)mp1;
2044
2045 dprintf(("PMFRAME:WM_ADJUSTFRAMEPOS %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
2046 //hack alert: the PM frame control changes the z-order of a child window
2047 // if it receives focus after a window has been destroyed
2048 // We can't let this happen as this messes up assumptions
2049 // elsewhere (e.g. GetNextDlgGroupItem)
2050 // By returning 0 here, we prevent the default frame handler
2051 // from messing things up. (one example is a group of radio buttons)
2052 //NOTE: We really need to get rid of frame & client windows for each
2053 // win32 window
2054 if(pswp->fl == SWP_FOCUSACTIVATE && win32wnd->isChild()) {
2055 rc = 0;
2056 break;
2057 }
2058 //hack alert: as we return zero as border size (check handler) we need
2059 //to do adjustments here as well or PM will calculate it for us and
2060 //result will be illegal. Btw we do not honour PM border size settings
2061 //and never will. I was unable to figure out why only X coordinate
2062 //is being broken but not Y as well.
2063
2064 if ((pswp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2065 {
2066 RECT rect;
2067 rect.left = rect.top = rect.right = rect.bottom = 0;
2068 win32wnd->AdjustMaximizedRect(&rect);
2069
2070 pswp->x += rect.left;
2071 }
2072 goto RunDefFrameWndProc;
2073 }
2074
2075#ifdef DEBUG
2076 case WM_OWNERPOSCHANGE:
2077 {
2078 PSWP pswp = (PSWP)mp1;
2079
2080 dprintf(("PMFRAME:WM_OWNERPOSCHANGE %x %x %x (%s) (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), pswp->hwnd, pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
2081 goto RunDefFrameWndProc;
2082 }
2083#endif
2084
2085 case WM_MINMAXFRAME:
2086 {
2087 PSWP swp = (PSWP)mp1;
2088
2089 if (!win32wnd->IsWindowCreated()) goto RunDefWndProc;
2090
2091 dprintf(("PMFRAME:WM_MINMAXFRAME %x",hwnd));
2092 if ((swp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2093 {
2094 // MDI frame windows are not common PM windows so we need to
2095 // drop-out WHOLE chain of WM_X commands with SWP_MAXIMIZE flag
2096 // finally last WM_WINDOWPOSCHANGED will take care of maximization
2097
2098 if (win32wnd->getExStyle() & WS_EX_MDICHILD_W) {
2099 rc = 0;
2100 break;
2101 }
2102
2103 RECT rect;
2104 rect.left = rect.top = rect.right = rect.bottom = 0;
2105 win32wnd->AdjustMaximizedRect(&rect);
2106
2107 swp->x += rect.left;
2108 swp->cx += rect.right-rect.left;
2109 swp->y -= rect.bottom;
2110 swp->cy += rect.bottom-rect.top;
2111
2112 win32wnd->ShowWindow(SW_RESTORE_W);
2113 }
2114 else
2115 if ((swp->fl & SWP_MINIMIZE) == SWP_MINIMIZE)
2116 {
2117 win32wnd->setStyle((win32wnd->getStyle() & ~WS_MAXIMIZE_W) | WS_MINIMIZE_W);
2118 }
2119 else
2120 if ((swp->fl & SWP_RESTORE) == SWP_RESTORE)
2121 {
2122 win32wnd->setStyle(win32wnd->getStyle() & ~(WS_MINIMIZE_W | WS_MAXIMIZE_W));
2123 }
2124 goto RunDefWndProc;
2125 }
2126
2127#ifdef DEBUG
2128 case WM_UPDATEFRAME:
2129 dprintf(("PMFRAME:WM_UPDATEFRAME %x", win32wnd->getWindowHandle()));
2130 goto RunDefFrameWndProc;
2131#endif
2132
2133 case WM_TRACKFRAME:
2134 dprintf(("PMFRAME: WM_TRACKFRAME %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2135 if(fOS2Look) {//sent by titlebar control
2136 Frame_SysCommandSizeMove(win32wnd, SC_MOVE_W+HTCAPTION_W);
2137 }
2138 rc = 0;
2139 break;
2140
2141 case WM_SYSCOMMAND:
2142 dprintf(("PMFRAME: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2143 if (fOS2Look == OS2_APPEARANCE_SYSMENU && mp1 == (MPARAM)OSSC_SYSMENU)
2144 goto RunDefFrameWndProc;
2145
2146 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
2147 RELEASE_WNDOBJ(win32wnd);
2148 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
2149 }
2150 if(win32wnd)
2151 win32wnd->DispatchMsgA(pWinMsg);
2152 break;
2153
2154#ifdef DEBUG
2155 case WM_DDE_INITIATE:
2156 case WM_DDE_INITIATEACK:
2157 case WM_DDE_REQUEST:
2158 case WM_DDE_ACK:
2159 case WM_DDE_DATA:
2160 case WM_DDE_ADVISE:
2161 case WM_DDE_UNADVISE:
2162 case WM_DDE_POKE:
2163 case WM_DDE_EXECUTE:
2164 case WM_DDE_TERMINATE:
2165 dprintf(("PMFRAME: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
2166 break;
2167#endif
2168
2169 default:
2170 goto RunDefFrameWndProc;
2171 }
2172 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2173 RestoreOS2TIB();
2174 ODIN_UnsetExceptionHandler(&exceptRegRec);
2175
2176#ifdef DEBUG
2177 dbg_ThreadPopCall();
2178#endif
2179 return (MRESULT)rc;
2180
2181RunDefFrameWndProc:
2182 dprintf2(("RunDefFrameWndProc"));
2183 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2184 RestoreOS2TIB();
2185 ODIN_UnsetExceptionHandler(&exceptRegRec);
2186
2187#ifdef DEBUG
2188 dbg_ThreadPopCall();
2189#endif
2190 return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2191
2192RunDefWndProc:
2193 dprintf2(("RunDefWndProc"));
2194 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2195 RestoreOS2TIB();
2196 ODIN_UnsetExceptionHandler(&exceptRegRec);
2197
2198 //calling WinDefWindowProc here breaks Opera hotlist window (WM_ADJUSTWINDOWPOS)
2199// return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2200
2201#ifdef DEBUG
2202 dbg_ThreadPopCall();
2203#endif
2204 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2205}
2206//******************************************************************************
2207//******************************************************************************
2208MRESULT EXPENTRY Win32FakeWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2209{
2210 PFNWP pfnOldWindowProc;
2211 Win32BaseWindow *win32wnd, *win32wndchild;
2212 TEB *teb;
2213 MRESULT rc = 0;
2214 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
2215
2216 //Restore our FS selector
2217 SetWin32TIB();
2218
2219 win32wnd = Win32FakeWindow::GetWindowFromOS2Handle(hwnd);
2220 if(win32wnd == NULL) {
2221 DebugInt3();
2222 goto RunDefWndProc;
2223 }
2224
2225 pfnOldWindowProc = (PFNWP)win32wnd->getOldPMWindowProc();
2226 if(pfnOldWindowProc == NULL) {
2227 DebugInt3();
2228 goto RunDefWndProc;
2229 }
2230
2231 RestoreOS2TIB();
2232 rc = pfnOldWindowProc(hwnd, msg, mp1, mp2);
2233
2234 ODIN_SetExceptionHandler(&exceptRegRec);
2235 SetWin32TIB();
2236 switch(msg) {
2237 case WM_WINDOWPOSCHANGED:
2238 {
2239 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
2240 SWP swpOld = *(pswp + 1);
2241 WINDOWPOS wp;
2242
2243 if(win32wnd->getParent()) {
2244 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
2245 hwnd);
2246 }
2247 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
2248
2249 win32wnd->SetWindowPos(wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
2250 break;
2251 }
2252
2253 }
2254 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2255 RestoreOS2TIB();
2256 ODIN_UnsetExceptionHandler(&exceptRegRec);
2257 return rc;
2258
2259RunDefWndProc:
2260 RestoreOS2TIB();
2261 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2262}
2263//******************************************************************************
2264// PMWinSubclassFakeWindow
2265//
2266// Subclass a fake window (converted PM window)
2267//
2268// Parameters
2269//
2270// HWND hwndOS2 - PM handle of fake window
2271//
2272// Returns
2273// NULL - Failure
2274// else - Old PM window procedure
2275//
2276//******************************************************************************
2277PVOID PMWinSubclassFakeWindow(HWND hwndOS2)
2278{
2279 return WinSubclassWindow(hwndOS2, Win32FakeWindowProc);
2280}
2281//******************************************************************************
2282//******************************************************************************
2283void FrameSetFocus(HWND hwnd)
2284{
2285 HWND hwndFocusSave = WinQueryWindowULong(hwnd, QWL_HWNDFOCUSSAVE);
2286 if(!WinIsWindow(hab, hwndFocusSave)) {
2287 hwndFocusSave = WinWindowFromID(hwnd, FID_CLIENT);
2288 WinSetWindowULong(hwnd, QWL_HWNDFOCUSSAVE, hwndFocusSave);
2289 }
2290 dprintf(("FrameSetFocus: hwndFocusSave %x %x", OS2ToWin32Handle(hwndFocusSave), hwndFocusSave));
2291 WinSetFocus(HWND_DESKTOP, hwndFocusSave);
2292
2293 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
2294 ulFrameFlags &= ~FF_NOACTIVATESWP;
2295 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags);
2296}
2297//******************************************************************************
2298//******************************************************************************
2299void FrameReplaceMenuItem(HWND hwndMenu, ULONG nIndex, ULONG idOld, ULONG idNew,
2300 HBITMAP hbmNew)
2301{
2302 MENUITEM mi;
2303
2304 if (!hwndMenu)
2305 return;
2306
2307 WinEnableWindowUpdate(hwndMenu, FALSE);
2308
2309 if (WinSendMsg(hwndMenu, MM_QUERYITEM, MPFROM2SHORT(idOld, TRUE), MPFROMP(&mi)))
2310 {
2311 WinSendMsg(hwndMenu, MM_REMOVEITEM, (MPARAM)idOld, 0);
2312 mi.afStyle = MIS_BITMAP | MIS_SYSCOMMAND;
2313 mi.afAttribute = 0;
2314 mi.hwndSubMenu = 0;
2315 mi.id = idNew;
2316 mi.hItem = (ULONG)hbmNew;
2317 WinSendMsg(hwndMenu, MM_INSERTITEM, (MPARAM)&mi, 0);
2318 }
2319 else
2320 dprintf(("WARNING: FrameReplaceMenuItem control %x not found",idOld));
2321
2322 WinEnableWindowUpdate(hwndMenu, TRUE);
2323
2324 WinInvalidateRect(hwndMenu, NULL, TRUE);
2325}
2326//******************************************************************************
2327//******************************************************************************
2328static char *PMDragExtractFiles(PDRAGINFO pDragInfo, ULONG *pcItems, ULONG *pulBytes)
2329{
2330 PDRAGITEM pDragItem;
2331 int i, cItems;
2332 BOOL ret;
2333 char szFileName[CCHMAXPATH];
2334 char szContainerName[CCHMAXPATH];
2335 ULONG ulBytes;
2336 char *pszCurFile = NULL;
2337
2338 /* Get access to the DRAGINFO data structure */
2339 if(!DrgAccessDraginfo(pDragInfo)) {
2340 return NULL;
2341 }
2342
2343 cItems = DrgQueryDragitemCount(pDragInfo);
2344
2345 //compute memory required to hold all filenames
2346 int bufsize = 0;
2347 for (i = 0; i < cItems; i++) {
2348 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2349
2350 bufsize += DrgQueryStrNameLen(pDragItem->hstrContainerName) + DrgQueryStrNameLen(pDragItem->hstrSourceName);
2351 bufsize++; //0 terminator
2352 bufsize++; //+ potential missing backslash
2353 }
2354 bufsize++; //extra 0 terminator
2355 char *pszFiles = (char *)malloc(bufsize);
2356 if(pszFiles == NULL) {
2357 dprintf(("Out of memory!!"));
2358 DebugInt3();
2359 goto failure;
2360 }
2361 memset(pszFiles, 0, bufsize);
2362
2363 pszCurFile = pszFiles;
2364
2365 //copy all filenames
2366 for (i = 0; i < cItems; i++) {
2367 char *pszTemp = pszCurFile;
2368
2369 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2370
2371 ulBytes = DrgQueryStrNameLen(pDragItem->hstrContainerName);
2372 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2373 ulBytes, pszCurFile);
2374 if(pszCurFile[ulBytes-1] != '\\') {
2375 pszCurFile[ulBytes] = '\\';
2376 pszCurFile++;
2377 }
2378 pszCurFile += ulBytes;
2379
2380 ulBytes = DrgQueryStrNameLen(pDragItem->hstrSourceName);
2381 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2382 ulBytes+1, pszCurFile);
2383 pszCurFile += ulBytes + 1; //+ terminator
2384
2385 dprintf(("dropped file %s", pszTemp));
2386 }
2387
2388 /* Release the draginfo data structure */
2389 DrgFreeDraginfo(pDragInfo);
2390
2391 *pulBytes = bufsize;
2392 *pcItems = cItems;
2393
2394 return pszFiles;
2395
2396failure:
2397 /* Release the draginfo data structure */
2398 DrgFreeDraginfo(pDragInfo);
2399 if(pszFiles) {
2400 free(pszFiles);
2401 }
2402 return NULL;
2403}
2404//******************************************************************************
2405//******************************************************************************
2406static BOOL PMDragValidate(PDRAGINFO pDragInfo)
2407{
2408 PDRAGITEM pDragItem;
2409 ULONG ulBytes;
2410 int i, cItems;
2411 BOOL ret;
2412 char szFileName[CCHMAXPATH];
2413 char szContainerName[CCHMAXPATH];
2414 USHORT usOp = DO_MOVE;
2415
2416 /* Get access to the DRAGINFO data structure */
2417 if(!DrgAccessDraginfo(pDragInfo)) {
2418 return FALSE;
2419 }
2420
2421 /* Can we accept this drop? */
2422 switch (pDragInfo->usOperation) {
2423 /* Return DOR_NODROPOP if current operation */
2424 /* is link or unknown */
2425 case DO_LINK:
2426 case DO_COPY:
2427 case DO_UNKNOWN:
2428 goto failure;
2429
2430 /* Our default operation is Move */
2431 case DO_MOVE:
2432 case DO_DEFAULT:
2433 pDragItem = DrgQueryDragitemPtr(pDragInfo, 0);
2434 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2435 sizeof(szContainerName),
2436 szContainerName);
2437 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2438 sizeof(szFileName),
2439 szFileName);
2440 if (!ulBytes) {
2441 goto failure;
2442 }
2443
2444 dprintf(("dropped file %s%s", szContainerName, szFileName));
2445 break;
2446 }
2447
2448 cItems = DrgQueryDragitemCount(pDragInfo);
2449
2450 /* Now, we need to look at each item in turn */
2451 for (i = 0; i < cItems; i++) {
2452 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2453
2454 /* Make sure we can move for a Move request */
2455 if (!((pDragItem->fsSupportedOps & DO_MOVEABLE) &&
2456 (usOp == (USHORT)DO_MOVE)))
2457 {
2458 dprintf(("item %d not accepted", i));
2459 goto failure;
2460 }
2461 }
2462 /* Release the draginfo data structure */
2463 DrgFreeDraginfo(pDragInfo);
2464 return TRUE;
2465
2466failure:
2467 DrgFreeDraginfo(pDragInfo);
2468 return FALSE;
2469}
2470
2471//******************************************************************************
2472// Override std class names we use in Odin (necessary for keyboard hook)
2473//******************************************************************************
2474void WIN32API SetCustomStdClassName(LPSTR pszStdClassName)
2475{
2476 strcpy(WIN32_STDCLASS, pszStdClassName);
2477}
2478//******************************************************************************
2479//******************************************************************************
2480
2481#ifdef DEBUG
2482static char *DbgGetStringSWPFlags(ULONG flags)
2483{
2484 static char szSWPFlags[512];
2485
2486 szSWPFlags[0] = 0;
2487
2488 if(flags & SWP_SIZE) {
2489 strcat(szSWPFlags, "SWP_SIZE ");
2490 }
2491 if(flags & SWP_MOVE) {
2492 strcat(szSWPFlags, "SWP_MOVE ");
2493 }
2494 if(flags & SWP_ZORDER) {
2495 strcat(szSWPFlags, "SWP_ZORDER ");
2496 }
2497 if(flags & SWP_SHOW) {
2498 strcat(szSWPFlags, "SWP_SHOW ");
2499 }
2500 if(flags & SWP_HIDE) {
2501 strcat(szSWPFlags, "SWP_HIDE ");
2502 }
2503 if(flags & SWP_NOREDRAW) {
2504 strcat(szSWPFlags, "SWP_NOREDRAW ");
2505 }
2506 if(flags & SWP_NOADJUST) {
2507 strcat(szSWPFlags, "SWP_NOADJUST ");
2508 }
2509 if(flags & SWP_ACTIVATE) {
2510 strcat(szSWPFlags, "SWP_ACTIVATE ");
2511 }
2512 if(flags & SWP_DEACTIVATE) {
2513 strcat(szSWPFlags, "SWP_DEACTIVATE ");
2514 }
2515 if(flags & SWP_EXTSTATECHANGE) {
2516 strcat(szSWPFlags, "SWP_EXTSTATECHANGE ");
2517 }
2518 if(flags & SWP_MINIMIZE) {
2519 strcat(szSWPFlags, "SWP_MINIMIZE ");
2520 }
2521 if(flags & SWP_MAXIMIZE) {
2522 strcat(szSWPFlags, "SWP_MAXIMIZE ");
2523 }
2524 if(flags & SWP_RESTORE) {
2525 strcat(szSWPFlags, "SWP_RESTORE ");
2526 }
2527 if(flags & SWP_FOCUSACTIVATE) {
2528 strcat(szSWPFlags, "SWP_FOCUSACTIVATE ");
2529 }
2530 if(flags & SWP_FOCUSDEACTIVATE) {
2531 strcat(szSWPFlags, "SWP_FOCUSDEACTIVATE ");
2532 }
2533 if(flags & SWP_NOAUTOCLOSE) {
2534 strcat(szSWPFlags, "SWP_NOAUTOCLOSE ");
2535 }
2536 return szSWPFlags;
2537}
2538static char *DbgPrintQFCFlags(ULONG flags)
2539{
2540 static char szQFCFlags[64];
2541
2542 szQFCFlags[0] = 0;
2543
2544 if(flags & QFC_NEXTINCHAIN) {
2545 strcat(szQFCFlags, "QFC_NEXTINCHAIN");
2546 }
2547 else
2548 if(flags & QFC_ACTIVE) {
2549 strcat(szQFCFlags, "QFC_ACTIVE");
2550 }
2551 else
2552 if(flags & QFC_FRAME) {
2553 strcat(szQFCFlags, "QFC_FRAME");
2554 }
2555 else
2556 if(flags & QFC_SELECTACTIVE) {
2557 strcat(szQFCFlags, "QFC_SELECTACTIVE");
2558 }
2559 else
2560 if(flags & QFC_PARTOFCHAIN) {
2561 strcat(szQFCFlags, "QFC_PARTOFCHAIN");
2562 }
2563
2564 return szQFCFlags;
2565}
2566#endif
Note: See TracBrowser for help on using the repository browser.