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

Last change on this file since 10431 was 10431, checked in by bird, 22 years ago

#682: Test for DEBUG_LOGGING not DEBUG. dprintf may be used in release.

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