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

Last change on this file since 10515 was 10515, checked in by sandervl, 21 years ago

Log current focus&active hwnds before setting focus.

File size: 91.2 KB
Line 
1/* $Id: pmwindow.cpp,v 1.229 2004-03-12 18:19:50 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 <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
708 goto RunDefWndProc;
709 }
710
711
712 case WM_VRNENABLED:
713 {
714 dprintf(("OS2: WM_VRNENABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
715 //Always call handler; even if mp1 is 0. If we don't do this, the
716 //DivX 4 player will never be allowed to draw after putting another window
717 //on top of it.
718
719 win32wnd->callVisibleRgnNotifyProc(TRUE);
720
721 //Workaround for PM/GPI bug when moving/sizing a window with open DCs
722 //
723 //Windows applictions often get a DC and keep it open for the duration
724 //of the application. When the DC's window is moved (full window dragging on)
725 //PM/GPI doesn't seem to update the DC properly/in time.
726 //This can result is visible distortions on the screen.
727 //Debugging showed that querying the visible region of a DC will cure
728 //this problem (GPI probably recalculates the visible region). (#334)
729
730 int nrdcs = 0;
731 HDC hdcWindow[MAX_OPENDCS];
732
733 if(win32wnd->queryOpenDCs(hdcWindow, MAX_OPENDCS, &nrdcs))
734 {
735 RECTL rcl = {0,0,1,1};
736 HRGN hrgnRect;
737
738 for(int i=0;i<nrdcs;i++) {
739 dprintf(("Recalc visible region of DC %x for window %x", hdcWindow[i], win32wnd->getWindowHandle()));
740
741 hrgnRect = GreCreateRectRegion(hdcWindow[i], &rcl, 1);
742 GreCopyClipRegion(hdcWindow[i], hrgnRect, 0, COPYCRGN_VISRGN);
743 GreDestroyRegion(hdcWindow[i], hrgnRect);
744 }
745 }
746 //Workaround END
747
748 if(!win32wnd->isComingToTop() && ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == WS_EX_TOPMOST_W))
749 {
750 HWND hwndrelated;
751 Win32BaseWindow *topwindow;
752
753 win32wnd->setComingToTop(TRUE);
754
755 hwndrelated = WinQueryWindow(hwnd, QW_PREV);
756 dprintf(("WM_VRNENABLED hwndrelated = %x (hwnd=%x)", hwndrelated, hwnd));
757 topwindow = Win32BaseWindow::GetWindowFromOS2Handle(hwndrelated);
758 if(topwindow == NULL || ((win32wnd->getExStyle() & WS_EX_TOPMOST_W) == 0)) {
759 //put window at the top of z order
760 WinSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ZORDER );
761 }
762 if(topwindow) RELEASE_WNDOBJ(topwindow);
763
764 win32wnd->setComingToTop(FALSE);
765 break;
766 }
767 goto RunDefWndProc;
768 }
769
770 case WM_VRNDISABLED:
771 {
772 dprintf(("OS2: WM_VRNDISABLED %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
773 //visible region is about to change or WinLockWindowUpdate called
774 //suspend window drawing
775
776 win32wnd->callVisibleRgnNotifyProc(FALSE);
777 goto RunDefWndProc;
778 }
779
780 case WIN32APP_DDRAWFULLSCREEN:
781 //Changing the size of the win32 window in SetCooperativeLevel can
782 //fail if this happens during WM_ADJUSTWINDOWPOS
783 //NOTE: This is not a good solution, but a proper fix is more difficult
784 // with the current window mess
785 dprintf(("WIN32APP_DDRAWFULLSCREEN %x (%d,%d)", win32wnd->getWindowHandle(), mp1, mp2));
786 SetWindowPos(win32wnd->getWindowHandle(), HWND_TOP_W, 0, 0, (DWORD)mp1, (DWORD)mp2, 0);
787 ShowWindow(win32wnd->getWindowHandle(), SW_SHOW_W);
788 break;
789
790 case WIN32APP_CHNGEFRAMECTRLS:
791 {
792 dprintf(("OS2: WIN32APP_CHANGEFRAMECTRLS"));
793 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), (ULONG)mp1, win32wnd->getExStyle(), (ULONG)mp2);
794 break;
795 }
796
797#ifdef DEBUG
798 case WM_SETFOCUS:
799 {
800 HWND hwndFocus = (HWND)mp1;
801 dprintf(("OS2: WM_SETFOCUS %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
802 if(WinQueryFocus(HWND_DESKTOP) == win32wnd->getOS2FrameWindowHandle()) {
803 dprintf(("WARNING: Focus set to frame window"));
804 }
805 break;
806 }
807#endif
808
809 //Handle all focus processed during WM_FOCUSCHANGED; PM doesn't like focus
810 //changes during focus processing (WM_SETFOCUS). This message is sent
811 //after all focus work has been completed.
812 case WM_FOCUSCHANGED:
813 {
814 HWND hwndFocus = (HWND)mp1;
815 HWND hwndFocusWin32 = OS2ToWin32Handle(hwndFocus);
816
817 dprintf(("OS2: WM_FOCUSCHANGED %x %x (%x) %d cur focus %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle(hwndFocus), mp2, WinQueryFocus(HWND_DESKTOP)));
818
819 //PM doesn't allow SetFocus calls during WM_SETFOCUS message processing;
820 //must delay this function call
821
822 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC)
823 {
824 //another (non-win32) application's window
825 //set to NULL (allowed according to win32 SDK) to avoid problems
826 hwndFocus = 0;
827 hwndFocusWin32 = 0;
828 }
829 if((ULONG)mp2 == TRUE) {
830 recreateCaret(hwndFocusWin32);
831 win32wnd->MsgSetFocus(hwndFocusWin32);
832 }
833 else {
834 //If SetFocus(0) was called, then the window has already received
835 //a WM_KILLFOCUS; don't send another one
836 if(!fIgnoreKeystrokes) {
837 win32wnd->MsgKillFocus(OS2ToWin32Handle(hwndFocus));
838 }
839 else dprintf(("Window has already received a WM_KILLFOCUS (SetFocus(0)); ignore"));
840 }
841 break;
842 }
843
844 //**************************************************************************
845 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
846 //**************************************************************************
847
848 case WM_BUTTON1DOWN:
849 case WM_BUTTON1UP:
850 case WM_BUTTON1DBLCLK:
851 case WM_BUTTON2DOWN:
852 case WM_BUTTON2UP:
853 case WM_BUTTON2DBLCLK:
854 case WM_BUTTON3DOWN:
855 case WM_BUTTON3UP:
856 case WM_BUTTON3DBLCLK:
857 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
858 RELEASE_WNDOBJ(win32wnd);
859 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
860 }
861 if(win32wnd)
862 win32wnd->MsgButton(pWinMsg);
863
864 rc = (MRESULT)TRUE;
865 break;
866
867 case WM_BUTTON2MOTIONSTART:
868 case WM_BUTTON2MOTIONEND:
869 case WM_BUTTON2CLICK:
870 case WM_BUTTON1MOTIONSTART:
871 case WM_BUTTON1MOTIONEND:
872 case WM_BUTTON1CLICK:
873 case WM_BUTTON3MOTIONSTART:
874 case WM_BUTTON3MOTIONEND:
875 case WM_BUTTON3CLICK:
876 rc = (MRESULT)TRUE;
877 break;
878
879 case WM_MOUSEMOVE:
880 {
881 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
882 RELEASE_WNDOBJ(win32wnd);
883 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
884 }
885 if(win32wnd)
886 win32wnd->MsgMouseMove(pWinMsg);
887 break;
888 }
889
890 case WM_CONTROL:
891 goto RunDefWndProc;
892
893 case WM_COMMAND:
894 dprintf(("OS2: WM_COMMAND %x %x %x", hwnd, mp1, mp2));
895 win32wnd->DispatchMsgA(pWinMsg);
896 break;
897
898 case WM_SYSCOMMAND:
899 dprintf(("OS2: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
900 win32wnd->DispatchMsgA(pWinMsg);
901 break;
902
903 case WM_RENDERFMT:
904 case WM_RENDERALLFMTS:
905 case WM_DESTROYCLIPBOARD:
906 case WM_DRAWCLIPBOARD:
907 win32wnd->DispatchMsgA(pWinMsg);
908 break;
909
910 case WM_CHAR_SPECIAL:
911 /* NO BREAK! FALLTHRU CASE! */
912
913 case WM_CHAR:
914 dprintf(("OS2: WM_CHAR %x %x %x, %x %x focus wnd %x", win32wnd->getWindowHandle(), mp1, mp2, pWinMsg->wParam, pWinMsg->lParam, WinQueryFocus(HWND_DESKTOP)));
915 win32wnd->MsgChar(pWinMsg);
916 break;
917
918 case WM_TIMER:
919 dprintf(("OS2: WM_TIMER %x %x time %x", win32wnd->getWindowHandle(), pWinMsg->wParam, GetTickCount()));
920 win32wnd->DispatchMsgA(pWinMsg);
921 goto RunDefWndProc;
922
923 case WM_SETWINDOWPARAMS:
924 {
925 WNDPARAMS *wndParams = (WNDPARAMS *)mp1;
926
927 dprintf(("OS2: WM_SETWINDOWPARAMS %x", hwnd));
928 if(wndParams->fsStatus & WPM_TEXT) {
929 win32wnd->MsgSetText(wndParams->pszText, wndParams->cchText);
930 }
931 goto RunDefWndProc;
932 }
933
934 case WM_QUERYWINDOWPARAMS:
935 {
936 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
937 ULONG textlen;
938 PSZ wintext;
939
940 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
941 {
942 if(wndpars->fsStatus & WPM_TEXT)
943 win32wnd->MsgGetText(wndpars->pszText, wndpars->cchText);
944 if(wndpars->fsStatus & WPM_CCHTEXT)
945 wndpars->cchText = win32wnd->MsgGetTextLength();
946
947 wndpars->fsStatus = 0;
948 wndpars->cbCtlData = 0;
949 wndpars->cbPresParams = 0;
950 rc = (MRESULT)TRUE;
951 break;
952 }
953 goto RunDefWndProc;
954 }
955
956 case WM_PAINT:
957 {
958 RECTL rectl;
959 BOOL rc;
960
961 win32wnd->checkForDirtyUpdateRegion();
962
963 rc = WinQueryUpdateRect(hwnd, &rectl);
964 dprintf(("OS2: WM_PAINT %x (%d,%d) (%d,%d) rc=%d", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop, rc));
965
966 if(rc && win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
967 rectl.yBottom != rectl.yTop) && !IsIconic(win32wnd->GetTopParent()))
968 {
969 win32wnd->DispatchMsgA(pWinMsg);
970 if(WinQueryUpdateRect(hwnd, NULL) == TRUE)
971 {//the application didn't validate the update region; Windows
972 //will only send a WM_PAINT once until another part of the
973 //window is invalidated. Unfortunately PM keeps on sending
974 //WM_PAINT messages until we validate the update region.
975
976 win32wnd->saveAndValidateUpdateRegion();
977 }
978 }
979 else goto RunDefWndProc;
980 break;
981 }
982
983 case WM_ERASEBACKGROUND:
984 {
985 dprintf(("OS2: WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
986 rc = (MRESULT)FALSE;
987 break;
988 }
989
990 case WM_CALCVALIDRECTS:
991 dprintf(("OS2: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
992 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
993 break;
994
995 case WM_REALIZEPALETTE:
996 {
997 dprintf(("OS2: WM_REALIZEPALETTE %x", win32wnd->getWindowHandle()));
998 win32wnd->DispatchMsgA(pWinMsg);
999 break;
1000 }
1001
1002 case WM_HSCROLL:
1003 case WM_VSCROLL:
1004 dprintf(("OS2: %s %x %x %x", (msg == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL", win32wnd->getWindowHandle(), mp1, mp2));
1005 win32wnd->DispatchMsgA(pWinMsg);
1006 break;
1007
1008 case DM_DRAGOVER:
1009 {
1010 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
1011 PDRAGITEM pDragItem;
1012 USHORT sxDrop = SHORT1FROMMP(mp2);
1013 USHORT syDrop = SHORT2FROMMP(mp2);
1014
1015 dprintf(("OS2: DM_DRAGOVER %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
1016
1017 if(fDragDropDisabled) {
1018 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1019 break;
1020 }
1021
1022 //does this window accept dropped files?
1023 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1024 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1025 break;
1026 }
1027
1028 if(PMDragValidate(pDragInfo) == FALSE) {
1029 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1030 break;
1031 }
1032 if(win32wnd->isDragDropActive() == FALSE) {
1033 ULONG ulBytes, cItems;
1034 char *pszFiles;
1035
1036 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
1037 if(pszFiles) {
1038 POINT point = {sxDrop, syDrop};
1039 if(DragDropDragEnter(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes, DROPEFFECT_COPY_W) == FALSE) {
1040 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1041 }
1042 else {
1043 fDragDropActive = TRUE;
1044 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1045 win32wnd->setDragDropActive(TRUE);
1046 }
1047 free(pszFiles);
1048 }
1049 else {
1050 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1051 }
1052 }
1053 else {
1054 if(DragDropDragOver(win32wnd->getWindowHandle(), DROPEFFECT_COPY_W) == FALSE) {
1055 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1056 }
1057 else rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1058 }
1059 break;
1060 }
1061
1062 case DM_DRAGLEAVE:
1063 {
1064 dprintf(("OS2: DM_DRAGLEAVE %x", win32wnd->getWindowHandle()));
1065
1066 if(fDragDropDisabled) {
1067 break;
1068 }
1069
1070 fDragDropActive = FALSE;
1071
1072 //does this window accept dropped files?
1073 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1074 break;
1075 }
1076
1077 DragDropDragLeave(win32wnd->getWindowHandle());
1078 win32wnd->setDragDropActive(FALSE);
1079 break;
1080 }
1081
1082 case DM_DROP:
1083 {
1084 PDRAGINFO pDragInfo = (PDRAGINFO)mp1;
1085 PDRAGITEM pDragItem;
1086 USHORT sxDrop = SHORT1FROMMP(mp2);
1087 USHORT syDrop = SHORT2FROMMP(mp2);
1088 USHORT usIndicator, usOp;
1089
1090 dprintf(("OS2: DM_DROP %x (%d,%d)", win32wnd->getWindowHandle(), sxDrop, syDrop));
1091
1092 fDragDropActive = FALSE;
1093 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1094
1095 if(fDragDropDisabled) {
1096 rc = (MRFROM2SHORT (DOR_NODROP, 0));
1097 break;
1098 }
1099
1100 //does this window accept dropped files?
1101 if(!DragDropAccept(win32wnd->getWindowHandle())) {
1102 break;
1103 }
1104
1105 ULONG ulBytes, cItems;
1106 char *pszFiles;
1107
1108 pszFiles = PMDragExtractFiles(pDragInfo, &cItems, &ulBytes);
1109 if(pszFiles) {
1110 POINT point = {sxDrop, syDrop};
1111 if(DragDropFiles(win32wnd->getWindowHandle(), point, cItems, pszFiles, ulBytes) == FALSE) {
1112 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1113 }
1114 else {
1115 rc = (MRFROM2SHORT(DOR_DROP, DO_MOVE));
1116 win32wnd->setDragDropActive(FALSE);
1117 }
1118 free(pszFiles);
1119 }
1120 else {
1121 rc = (MRFROM2SHORT (DOR_NEVERDROP, 0));
1122 }
1123 break;
1124 }
1125
1126 case DM_RENDER:
1127 {
1128 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1129
1130 dprintf(("OS2: DM_RENDER %x", pDragTransfer));
1131
1132 rc = (MRESULT)OSLibRenderFormat(pDragTransfer);
1133 break;
1134 }
1135
1136 case DM_RENDERPREPARE:
1137 {
1138 PDRAGTRANSFER pDragTransfer = (PDRAGTRANSFER)mp1;
1139
1140 dprintf(("OS2: DM_RENDERPREPARE %x", pDragTransfer));
1141 break;
1142 }
1143
1144 case DM_ENDCONVERSATION:
1145 {
1146 dprintf(("OS2: DM_ENDCONVERSATION"));
1147 rc = (MRESULT)OSLibEndConversation();
1148 break;
1149 }
1150
1151 case DM_RENDERFILE:
1152 {
1153 dprintf(("OS2: DM_ENDCONVERSATION"));
1154 rc = FALSE;
1155 break;
1156 }
1157
1158 case WM_DDE_INITIATE:
1159 case WM_DDE_INITIATEACK:
1160 case WM_DDE_REQUEST:
1161 case WM_DDE_ACK:
1162 case WM_DDE_DATA:
1163 case WM_DDE_ADVISE:
1164 case WM_DDE_UNADVISE:
1165 case WM_DDE_POKE:
1166 case WM_DDE_EXECUTE:
1167 case WM_DDE_TERMINATE:
1168 dprintf(("OS2: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
1169 goto RunDefWndProc;
1170
1171 case WM_INITMENU:
1172 case WM_MENUSELECT:
1173 case WM_MENUEND:
1174 case WM_NEXTMENU:
1175 case WM_SYSCOLORCHANGE:
1176 case WM_SYSVALUECHANGED:
1177 case WM_SETSELECTION:
1178 case WM_PPAINT:
1179 case WM_PSETFOCUS:
1180 case WM_PSYSCOLORCHANGE:
1181 case WM_PSIZE:
1182 case WM_PACTIVATE:
1183 case WM_PCONTROL:
1184 case WM_HELP:
1185 case WM_APPTERMINATENOTIFY:
1186 case WM_PRESPARAMCHANGED:
1187 case WM_DRAWITEM:
1188 case WM_MEASUREITEM:
1189 case WM_CONTROLPOINTER:
1190 case WM_QUERYDLGCODE:
1191 case WM_SUBSTITUTESTRING:
1192 case WM_MATCHMNEMONIC:
1193 case WM_SAVEAPPLICATION:
1194 case WM_SEMANTICEVENT:
1195 default:
1196 dprintf2(("OS2: RunDefWndProc hwnd %x msg %x mp1 %x mp2 %x", hwnd, msg, mp1, mp2));
1197 goto RunDefWndProc;
1198 }
1199 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1200 RestoreOS2TIB();
1201 ODIN_UnsetExceptionHandler(&exceptRegRec);
1202
1203#ifdef DEBUG
1204 dbg_ThreadPopCall();
1205#endif
1206 return (MRESULT)rc;
1207
1208RunDefWndProc:
1209// dprintf(("OS2: RunDefWndProc msg %x for %x", msg, hwnd));
1210 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
1211
1212 RestoreOS2TIB();
1213 ODIN_UnsetExceptionHandler(&exceptRegRec);
1214
1215#ifdef DEBUG
1216 dbg_ThreadPopCall();
1217#endif
1218 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
1219} /* End of Win32WindowProc */
1220//******************************************************************************
1221//******************************************************************************
1222MRESULT EXPENTRY Win32FrameWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1223{
1224 POSTMSG_PACKET *postmsg;
1225 OSLIBPOINT point, ClientPoint;
1226 Win32BaseWindow *win32wnd;
1227 TEB *teb;
1228 MRESULT rc = 0;
1229 MSG winMsg, *pWinMsg;
1230 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
1231
1232#ifdef DEBUG
1233 dbg_ThreadPushCall("Win32FrameWindowProc");
1234#endif
1235
1236 ODIN_SetExceptionHandler(&exceptRegRec);
1237 //Restore our FS selector
1238 SetWin32TIB();
1239
1240 // BEGIN NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- BEGIN
1241 teb = GetThreadTEB();
1242 win32wnd = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
1243
1244 // do some sanity checking here:
1245 // - we need to have a TEB handle
1246 // - unless this is WM_CREATE (the very first message), there has to be
1247 // a USER32 window object for this window handle
1248 // - thread must not be suspended in WaitMessage
1249 if(!teb || (msg != WM_CREATE && win32wnd == NULL) || teb->o.odin.fWaitMessageSuspend) {
1250 if(teb && teb->o.odin.fWaitMessageSuspend)
1251 dprintf(("PMFRAME: fWaitMessageSuspend window %x msg %x -> run default frame proc", hwnd, msg));
1252 else dprintf(("PMFRAME: Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
1253 goto RunDefFrameWndProc;
1254 }
1255//// if(teb->o.odin.fIgnoreMsgs) {
1256//// goto RunDefWndProc;
1257//// }
1258
1259 // check if the message state counter in the TEB is odd
1260 // This means the message has been sent directly from PM to our message
1261 // handler (so it is the first time we know about this PM message).
1262 // If this is the case, we have to translate it here to a Win32
1263 // message first. The other case is that the message is the result of a
1264 // WinDispatchMsg call and therefore has already been translated.
1265 if((teb->o.odin.msgstate & 1) == 0)
1266 {//message that was sent directly to our window proc handler; translate it here
1267 QMSG qmsg;
1268
1269 qmsg.msg = msg;
1270 qmsg.hwnd = hwnd;
1271 qmsg.mp1 = mp1;
1272 qmsg.mp2 = mp2;
1273 qmsg.time = WinQueryMsgTime(teb->o.odin.hab);
1274 WinQueryMsgPos(teb->o.odin.hab, &qmsg.ptl);
1275 qmsg.reserved = 0;
1276
1277 if(OS2ToWinMsgTranslate((PVOID)teb, &qmsg, &winMsg, FALSE, MSG_REMOVE) == FALSE)
1278 {//message was not translated
1279 memset(&winMsg, 0, sizeof(MSG));
1280 }
1281 pWinMsg = &winMsg;
1282 }
1283 else {
1284 // message has already been translated before (GetMessage/PeekMessage).
1285 // Use the translated information. Flip the translation flag.
1286 pWinMsg = &teb->o.odin.msg;
1287 teb->o.odin.msgstate++;
1288 }
1289 // END NOTE-------------->>>>>> If this is changed, also change Win32WindowProc!! <<<<<<<<<<<-------------------- END
1290
1291 switch( msg )
1292 {
1293 case WM_CREATE:
1294 {
1295 //WM_CREATE handled during client window creation
1296 dprintf(("PMFRAME: WM_CREATE %x", hwnd));
1297 goto RunDefFrameWndProc;
1298 }
1299
1300//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
1301// handler; must postpone it, so do it here
1302 case WIN32APP_POSTPONEDESTROY:
1303 OSLibWinDestroyWindow(hwnd);
1304 break;
1305//hack end
1306
1307#ifdef DEBUG
1308 case WM_CLOSE:
1309 {
1310 dprintf(("PMFRAME: WM_CLOSE %x", hwnd));
1311 goto RunDefFrameWndProc;
1312 }
1313#endif
1314
1315 case WM_PAINT:
1316 {
1317 RECTL rectl;
1318 HRGN hrgn;
1319
1320 hrgn = CreateRectRgn(0, 0, 0, 0);
1321 GetUpdateRgnFrame(win32wnd->getWindowHandle(), hrgn);
1322
1323 HPS hps = WinBeginPaint(hwnd, NULL, &rectl);
1324 dprintf(("PMFRAME: WM_PAINT %x (%d,%d) (%d,%d)", win32wnd->getWindowHandle(), rectl.xLeft, rectl.yBottom, rectl.xRight, rectl.yTop));
1325
1326 if(win32wnd->IsWindowCreated() && (rectl.xLeft != rectl.xRight &&
1327 rectl.yBottom != rectl.yTop))
1328 {
1329 PRECT pClient = win32wnd->getClientRectPtr();
1330 PRECT pWindow = win32wnd->getWindowRect();
1331
1332 if(!(pClient->left == 0 && pClient->top == 0 &&
1333 win32wnd->getClientHeight() == win32wnd->getWindowHeight() &&
1334 win32wnd->getClientWidth() == win32wnd->getWindowWidth()))
1335 {
1336 RECT rectUpdate;
1337
1338 mapOS2ToWin32Rect(win32wnd->getWindowHeight(), (PRECTLOS2)&rectl, &rectUpdate);
1339 win32wnd->MsgNCPaint(&rectUpdate, hrgn);
1340 }
1341 }
1342 WinEndPaint(hps);
1343
1344 DeleteObject(hrgn);
1345 break;
1346 }
1347
1348 case WM_ERASEBACKGROUND:
1349 {
1350 dprintf(("PMFRAME:WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
1351 rc = (MRESULT)FALSE;
1352 break;
1353 }
1354
1355 //**************************************************************************
1356 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
1357 //**************************************************************************
1358
1359 case WM_BUTTON1DOWN:
1360 case WM_BUTTON1UP:
1361 case WM_BUTTON1DBLCLK:
1362 case WM_BUTTON2DOWN:
1363 case WM_BUTTON2UP:
1364 case WM_BUTTON2DBLCLK:
1365 case WM_BUTTON3DOWN:
1366 case WM_BUTTON3UP:
1367 case WM_BUTTON3DBLCLK:
1368 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1369 RELEASE_WNDOBJ(win32wnd);
1370 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1371 }
1372 if(win32wnd)
1373 win32wnd->MsgButton(pWinMsg);
1374
1375 rc = (MRESULT)TRUE;
1376 break;
1377
1378 case WM_BUTTON2MOTIONSTART:
1379 case WM_BUTTON2MOTIONEND:
1380 case WM_BUTTON2CLICK:
1381 case WM_BUTTON1MOTIONSTART:
1382 case WM_BUTTON1MOTIONEND:
1383 case WM_BUTTON1CLICK:
1384 case WM_BUTTON3MOTIONSTART:
1385 case WM_BUTTON3MOTIONEND:
1386 case WM_BUTTON3CLICK:
1387 rc = (MRESULT)TRUE;
1388 break;
1389
1390 case WM_MOUSEMOVE:
1391 {
1392 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
1393 RELEASE_WNDOBJ(win32wnd);
1394 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
1395 }
1396 if(win32wnd)
1397 win32wnd->MsgMouseMove(pWinMsg);
1398 break;
1399 }
1400
1401 case WM_CHAR_SPECIAL_CONSOLE_BREAK:
1402 {
1403 //ignore this message. don't forward it to the default PM frame window handler
1404 //as that one sends it to the client. as a result we end up translating
1405 //it twice
1406 break;
1407 }
1408
1409 case WM_ADJUSTWINDOWPOS:
1410 {
1411 PSWP pswp = (PSWP)mp1;
1412 SWP swpOld;
1413 WINDOWPOS wp,wpOld;
1414 ULONG ulFlags;
1415 ULONG ret = 0;
1416 HWND hParent = NULLHANDLE, hwndAfter;
1417
1418 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));
1419
1420 ulFlags = pswp->fl;
1421
1422 if(win32wnd->IsParentChanging()) {
1423 rc = 0;
1424 break;
1425 }
1426
1427 //@@PF all commands from minimized window viewer or from Ctrl-Esc
1428 //are 'pure' and should be handled only by DeFrameProc - this is weird
1429 //but without them we will not have results. Pure = plain flag of restore/minimize/maximize
1430 if((pswp->fl == SWP_MINIMIZE) || (pswp->fl & SWP_RESTORE)) {
1431 // note the purity of SWP no other SWP_FLAGS allowed
1432 goto RunDefFrameWndProc;
1433 }
1434
1435 if(pswp->fl & SWP_NOADJUST) {
1436 //ignore weird messages (TODO: why are they sent?)
1437 dprintf(("WARNING: WM_ADJUSTWINDOWPOS with SWP_NOADJUST flag!!"));
1438 break;
1439
1440 }
1441
1442 //PF Pure flags should not cause any subsequent messages to win32 windows
1443 //we should route them to DefFrameWndProc and check highlight.
1444
1445 if ((pswp->fl == SWP_FOCUSACTIVATE) || (pswp->fl == SWP_FOCUSDEACTIVATE))
1446 {
1447 if (fOS2Look)
1448 {
1449 if(pswp->fl == SWP_FOCUSACTIVATE)
1450 {
1451 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1452 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1453 }
1454 else
1455 {
1456 dprintf2(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1457 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1458 }
1459 }
1460 goto RunDefFrameWndProc;
1461 }
1462
1463 //CB: show dialog in front of owner
1464 if (win32wnd->IsModalDialogOwner())
1465 {
1466 dprintf(("win32wnd->IsModalDialogOwner %x", win32wnd->getWindowHandle()));
1467 pswp->fl |= SWP_ZORDER;
1468 pswp->hwndInsertBehind = win32wnd->getOS2HwndModalDialog();
1469 if (pswp->fl & SWP_ACTIVATE)
1470 {
1471 pswp->fl &= ~SWP_ACTIVATE;
1472 WinSetWindowPos(win32wnd->getOS2HwndModalDialog(),0,0,0,0,0,SWP_ACTIVATE);
1473 }
1474 }
1475
1476 if(!win32wnd->CanReceiveSizeMsgs())
1477 break;
1478
1479 WinQueryWindowPos(hwnd, &swpOld);
1480 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
1481 if (win32wnd->isChild()) {
1482 if(win32wnd->getParent()) {
1483 hParent = win32wnd->getParent()->getOS2WindowHandle();
1484 }
1485 else goto RunDefFrameWndProc;
1486 }
1487 }
1488 hwndAfter = pswp->hwndInsertBehind;
1489 if(win32wnd->getParent()) {
1490 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(), hwnd);
1491 }
1492 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1493
1494 wp.hwnd = win32wnd->getWindowHandle();
1495 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1496 {
1497 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1498 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1499 if(wndAfter) {
1500 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1501 RELEASE_WNDOBJ(wndAfter);
1502 }
1503 else wp.hwndInsertAfter = HWND_TOP_W;
1504 }
1505
1506 wpOld = wp;
1507 win32wnd->MsgPosChanging((LPARAM)&wp);
1508
1509 if(win32wnd->getOldStyle() != win32wnd->getStyle())
1510 {
1511 OSLibSetWindowStyle(win32wnd->getOS2FrameWindowHandle(), win32wnd->getOS2WindowHandle(), win32wnd->getStyle(), win32wnd->getExStyle(), win32wnd->getStyle());
1512 if(fOS2Look) {
1513 DWORD dwOldStyle = win32wnd->getOldStyle();
1514 DWORD dwStyle = win32wnd->getStyle();
1515
1516 win32wnd->setOldStyle(dwStyle);
1517 if((dwOldStyle & WS_MINIMIZE_W) && !(dwStyle & WS_MINIMIZE_W)) {
1518 //SC_RESTORE -> SC_MINIMIZE
1519 dprintf(("%x -> SC_RESTORE -> SC_MINIMIZE", win32wnd->getWindowHandle()));
1520 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_RESTORE, SC_MINIMIZE, hbmFrameMenu[PMMENU_MINBUTTON]);
1521 if(dwStyle & WS_MAXIMIZE_W) {
1522 //SC_MAXIMIZE -> SC_RESTORE
1523 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (1)", win32wnd->getWindowHandle()));
1524 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1525 }
1526 }
1527 else
1528 if((dwOldStyle & WS_MAXIMIZE_W) && !(dwStyle & WS_MAXIMIZE_W)) {
1529 //SC_RESTORE -> SC_MAXIMIZE
1530 dprintf(("%x -> SC_RESTORE -> SC_MAXIMIZE", win32wnd->getWindowHandle()));
1531 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_RESTORE, SC_MAXIMIZE, hbmFrameMenu[PMMENU_MAXBUTTON]);
1532 }
1533 else
1534 if(!(dwOldStyle & WS_MINIMIZE_W) && (dwStyle & WS_MINIMIZE_W)) {
1535 //SC_MINIMIZE -> SC_RESTORE
1536 dprintf(("%x -> SC_MINIMIZE -> SC_RESTORE", win32wnd->getWindowHandle()));
1537 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), 0, SC_MINIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1538 }
1539 else
1540 if(!(dwOldStyle & WS_MAXIMIZE_W) && (dwStyle & WS_MAXIMIZE_W)) {
1541 //SC_MAXIMIZE -> SC_RESTORE
1542 dprintf(("%x -> SC_MAXIMIZE -> SC_RESTORE (2)", win32wnd->getWindowHandle()));
1543 FrameReplaceMenuItem(WinWindowFromID(hwnd, FID_MINMAX), MIT_END, SC_MAXIMIZE, SC_RESTORE, hbmFrameMenu[PMMENU_RESTOREBUTTON]);
1544 }
1545 }
1546 }
1547
1548 if ((wp.hwndInsertAfter != wpOld.hwndInsertAfter) ||
1549 (wp.x != wpOld.x) || (wp.y != wpOld.y) || (wp.cx != wpOld.cx) || (wp.cy != wpOld.cy) || (wp.flags != wpOld.flags))
1550 {
1551 ULONG flags = pswp->fl; //make a backup copy; OSLibMapWINDOWPOStoSWP will modify it
1552
1553 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1554 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1555
1556 if(win32wnd->getParent()) {
1557 OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, win32wnd->getParent()->getClientHeight(),
1558 hwnd);
1559 }
1560 else OSLibMapWINDOWPOStoSWP(&wp, pswp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1561
1562 dprintf(("%x (%d,%d), (%d,%d)", pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
1563
1564 //OSLibMapWINDOWPOStoSWP can add flags, but we must not let it remove flags!
1565 if(pswp->fl & SWP_SIZE)
1566 flags |= SWP_SIZE;
1567
1568 if(pswp->fl & SWP_MOVE)
1569 flags |= SWP_MOVE;
1570
1571 pswp->fl = flags; //restore flags
1572
1573 pswp->fl |= SWP_NOADJUST;
1574 pswp->hwndInsertBehind = hwndAfter;
1575 pswp->hwnd = hwnd;
1576
1577 ret = 0xf;
1578 }
1579adjustend:
1580 //The next part needs to be done for top-level windows only
1581 if(!((win32wnd->getStyle() & (WS_POPUP_W|WS_CHILD_W)) == WS_CHILD_W))
1582 {
1583 //Setting these flags is necessary to avoid activation/focus problems
1584 if(ulFlags & SWP_DEACTIVATE) {
1585 ret |= AWP_DEACTIVATE;
1586 }
1587 if(ulFlags & SWP_ACTIVATE)
1588 {
1589 if(ulFlags & SWP_ZORDER) {
1590 dprintf(("Set FF_NOACTIVATESWP"));
1591 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
1592 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags | FF_NOACTIVATESWP);
1593 }
1594
1595 if(!(ulFlags & SWP_SHOW))
1596 {
1597 ret |= AWP_ACTIVATE;
1598 }
1599 else
1600 {
1601 FrameSetFocus(hwnd);
1602 }
1603 }
1604 }
1605 else {
1606 if(ulFlags & (SWP_ACTIVATE|SWP_FOCUSACTIVATE))
1607 {
1608 win32wnd->MsgChildActivate(TRUE);
1609 if(fOS2Look) {
1610 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1611 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, (MPARAM)1, 0);
1612 }
1613 }
1614 else
1615 if(ulFlags & (SWP_DEACTIVATE|SWP_FOCUSDEACTIVATE))
1616 {
1617 win32wnd->MsgChildActivate(FALSE);
1618 if(fOS2Look) {
1619 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1620 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, 0, 0);
1621 }
1622 }
1623 }
1624#ifdef DEBUG
1625 dprintf(("WM_ADJUSTWINDOWPOS ret %x flags %x", ret, WinQueryWindowUShort(hwnd, QWS_FLAGS)));
1626 if(ret == 0x0f) {
1627 dprintf(("PMFRAME:WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
1628 dprintf(("%x (%s) (%d,%d), (%d,%d)", pswp->fl, DbgGetStringSWPFlags(pswp->fl), pswp->x, pswp->y, pswp->cx, pswp->cy));
1629 }
1630#endif
1631 rc = (MRESULT)ret;
1632 break;
1633 }
1634
1635 case WM_WINDOWPOSCHANGED:
1636 {
1637 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
1638 SWP swpOld = *(pswp + 1);
1639 WINDOWPOS wp;
1640 ULONG flAfp = (ULONG)mp2;
1641 HWND hParent = NULLHANDLE;
1642 RECTL rect;
1643
1644 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)));
1645 if(win32wnd->IsParentChanging()) {
1646 goto PosChangedEnd;
1647 }
1648
1649 // PF: MDI window is not a common OS/2 frame window so we just skipped all
1650 // PM default processing for it that basicly moved this window to 0,0 point
1651 // and changed frame controls. Now do our own processing.
1652
1653 if ((pswp->fl & SWP_MAXIMIZE) && (win32wnd->getExStyle() & WS_EX_MDICHILD_W))
1654 {
1655 SendMessageA(win32wnd->getWindowHandle(), WM_SYSCOMMAND_W, SC_MAXIMIZE_W, 0);
1656 goto PosChangedEnd;
1657 }
1658
1659 //SvL: When a window is made visible, then we don't receive a
1660 // WM_VRNENABLED message (for some weird reason)
1661 if(pswp->fl & SWP_SHOW) {
1662 win32wnd->callVisibleRgnNotifyProc(TRUE);
1663 }
1664 else
1665 if(pswp->fl & SWP_HIDE) {
1666 win32wnd->callVisibleRgnNotifyProc(FALSE);
1667 }
1668
1669 if(pswp->fl & (SWP_MOVE | SWP_SIZE))
1670 {
1671 if(win32wnd->isChild())
1672 {
1673 if(win32wnd->getParent()) {
1674 hParent = win32wnd->getParent()->getOS2WindowHandle();
1675 }
1676 else goto PosChangedEnd; //parent has just been destroyed
1677 }
1678 }
1679
1680
1681 if(win32wnd->getParent()) {
1682 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1683 hwnd);
1684 }
1685 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
1686
1687 wp.hwnd = win32wnd->getWindowHandle();
1688 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1689 {
1690 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1691 dprintf2(("SWP_ZORDER: %x %x", pswp->hwndInsertBehind, (wndAfter) ? wndAfter->getWindowHandle() : 0));
1692 if(wndAfter) {
1693 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1694 RELEASE_WNDOBJ(wndAfter);
1695 }
1696 else wp.hwndInsertAfter = HWND_TOP_W;
1697 }
1698
1699 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0)
1700 {
1701 if(pswp->fl & SWP_RESTORE && win32wnd->getStyle() & WS_MINIMIZE_W) {
1702 dprintf(("Restoring minimized window %x", win32wnd->getWindowHandle()));
1703 win32wnd->ShowWindow(SW_RESTORE_W);
1704 }
1705 if(pswp->fl & SWP_SHOW) {
1706 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1707 }
1708 else
1709 if(pswp->fl & SWP_HIDE) {
1710 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1711 }
1712 if(pswp->fl & (SWP_SHOW|SWP_HIDE))
1713 {//TODO: necessary for more options? (activate?)
1714 if(win32wnd->CanReceiveSizeMsgs())
1715 win32wnd->MsgPosChanged((LPARAM)&wp);
1716 }
1717
1718 //MUST call the old frame window proc!
1719 goto RunDefFrameWndProc;
1720 }
1721
1722 if(pswp->fl & SWP_SHOW) {
1723 WinShowWindow(win32wnd->getOS2WindowHandle(), 1);
1724 }
1725 else
1726 if(pswp->fl & SWP_HIDE) {
1727 WinShowWindow(win32wnd->getOS2WindowHandle(), 0);
1728 }
1729
1730 if(flAfp & AWP_ACTIVATE)
1731 {
1732 FrameSetFocus(hwnd);
1733 }
1734
1735#ifndef USE_CALCVALIDRECT
1736 if((pswp->fl & (SWP_MOVE | SWP_SIZE)))
1737 {
1738 //CB: todo: use result for WM_CALCVALIDRECTS
1739 //Get old client rectangle (for invalidation of frame window parts later on)
1740 //Use new window height to calculate the client area
1741 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&rect);
1742
1743 //Note: Also updates the new window rectangle
1744 win32wnd->MsgFormatFrame(&wp);
1745
1746 if(win32wnd->isOwnDC()) {
1747 setPageXForm(win32wnd, (pDCData)GpiQueryDCData(win32wnd->getOwnDC()));
1748 }
1749
1750 if(win32wnd->CanReceiveSizeMsgs())
1751 win32wnd->MsgPosChanged((LPARAM)&wp);
1752
1753 if((pswp->fl & SWP_SIZE) && ((pswp->cx != pswpOld->cx) || (pswp->cy != pswpOld->cy)))
1754 {
1755 //redraw the frame (to prevent unnecessary client updates)
1756 BOOL redrawAll = FALSE;
1757
1758 dprintf2(("WM_WINDOWPOSCHANGED: redraw frame"));
1759 if (win32wnd->getWindowClass())
1760 {
1761 DWORD dwStyle = win32wnd->getWindowClass()->getClassLongA(GCL_STYLE_W);
1762
1763 if ((dwStyle & CS_HREDRAW_W) && (pswp->cx != pswpOld->cx))
1764 redrawAll = TRUE;
1765 else
1766 if ((dwStyle & CS_VREDRAW_W) && (pswp->cy != pswpOld->cy))
1767 redrawAll = TRUE;
1768 }
1769 else redrawAll = TRUE;
1770
1771 if(win32wnd->IsMixMaxStateChanging()) {
1772 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1773 redrawAll = TRUE;
1774 }
1775
1776 if (redrawAll)
1777 {
1778 //CB: redraw all children for now
1779 // -> problems with update region if we don't do it
1780 // todo: rewrite whole handling
1781 dprintf(("PMFRAME: WM_WINDOWPOSCHANGED invalidate all"));
1782 WinInvalidateRect(hwnd,NULL,TRUE);
1783 }
1784 else
1785 {
1786 HPS hps = WinGetPS(hwnd);
1787 RECTL frame,client,arcl[4];
1788
1789 WinQueryWindowRect(hwnd,&frame);
1790
1791 //top
1792 arcl[0].xLeft = 0;
1793 arcl[0].xRight = frame.xRight;
1794 arcl[0].yBottom = rect.yTop;
1795 arcl[0].yTop = frame.yTop;
1796 //right
1797 arcl[1].xLeft = rect.xRight;
1798 arcl[1].xRight = frame.xRight;
1799 arcl[1].yBottom = 0;
1800 arcl[1].yTop = frame.yTop;
1801 //left
1802 arcl[2].xLeft = 0;
1803 arcl[2].xRight = rect.xLeft;
1804 arcl[2].yBottom = 0;
1805 arcl[2].yTop = frame.yTop;
1806 //bottom
1807 arcl[3].xLeft = 0;
1808 arcl[3].xRight = frame.xRight;
1809 arcl[3].yBottom = 0;
1810 arcl[3].yTop = rect.yBottom;
1811
1812 HRGN hrgn = GpiCreateRegion(hps,4,(PRECTL)&arcl);
1813
1814 WinInvalidateRegion(hwnd,hrgn,FALSE);
1815 GpiDestroyRegion(hps,hrgn);
1816 WinReleasePS(hps);
1817 }
1818 }
1819 }
1820 else
1821 {
1822#endif //USE_CALCVALIDRECT
1823 if(win32wnd->CanReceiveSizeMsgs())
1824 win32wnd->MsgPosChanged((LPARAM)&wp);
1825#ifndef USE_CALCVALIDRECT
1826 }
1827#endif
1828 //PF This is the final step of PM restoration - should end up
1829 //in default handler.
1830 if (win32wnd->getOldStyle() & WS_MINIMIZE_W && pswp->fl & SWP_RESTORE)
1831 goto RunDefFrameWndProc;
1832
1833 //PF This is the final step of PM minimization - shoukd end up
1834 //in default handler
1835 if (win32wnd->getStyle() & WS_MINIMIZE_W && pswp->fl & SWP_MINIMIZE)
1836 goto RunDefFrameWndProc;
1837
1838PosChangedEnd:
1839 rc = (MRESULT)FALSE;
1840 break;
1841 }
1842
1843 case WM_CALCVALIDRECTS:
1844#ifdef USE_CALCVALIDRECT
1845 {
1846 PRECTL oldRect = (PRECTL)mp1, newRect = oldRect+1;
1847 PSWP pswp = (PSWP)mp2;
1848 SWP swpOld;
1849 WINDOWPOS wp;
1850 RECTL newClientRect, oldClientRect;
1851 ULONG nccalcret;
1852// UINT res = CVR_ALIGNLEFT | CVR_ALIGNTOP;
1853 UINT res = 0;
1854
1855 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1856
1857 //Get old position info
1858 WinQueryWindowPos(hwnd, &swpOld);
1859
1860 if(win32wnd->getParent()) {
1861 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
1862 win32wnd->getParent()->getClientRectPtr()->left,
1863 win32wnd->getParent()->getClientRectPtr()->top,
1864 hwnd);
1865 }
1866 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), 0, 0, hwnd);
1867
1868 wp.hwnd = win32wnd->getWindowHandle();
1869 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
1870 {
1871 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
1872 if(wndAfter) {
1873 wp.hwndInsertAfter = wndAfter->getWindowHandle();
1874 RELEASE_WNDOBJ(wndAfter);
1875 }
1876 else wp.hwndInsertAfter = HWND_TOP_W;
1877 }
1878
1879 //Get old client rectangle
1880 mapWin32ToOS2Rect(oldRect->yTop - oldRect->yBottom, win32wnd->getClientRectPtr(), (PRECTLOS2)&oldClientRect);
1881
1882 //Note: Also updates the new window rectangle
1883 nccalcret = win32wnd->MsgFormatFrame(&wp);
1884
1885 //Get new client rectangle
1886 mapWin32ToOS2Rect(pswp->cy, win32wnd->getClientRectPtr(), (PRECTLOS2)&newClientRect);
1887
1888 if(nccalcret == 0) {
1889 res = CVR_ALIGNTOP | CVR_ALIGNLEFT;
1890 }
1891 else {
1892 if(nccalcret & WVR_ALIGNTOP_W) {
1893 res |= CVR_ALIGNTOP;
1894 }
1895 else
1896 if(nccalcret & WVR_ALIGNBOTTOM_W) {
1897 res |= CVR_ALIGNBOTTOM;
1898 }
1899
1900 if(nccalcret & WVR_ALIGNLEFT_W) {
1901 res |= CVR_ALIGNLEFT;
1902 }
1903 else
1904 if(nccalcret & WVR_ALIGNRIGHT_W) {
1905 res |= CVR_ALIGNRIGHT;
1906 }
1907
1908 if(nccalcret & WVR_REDRAW_W) {//WVR_REDRAW_W = (WVR_HREDRAW | WVR_VREDRAW)
1909 res |= CVR_REDRAW;
1910 }
1911 else
1912 if(nccalcret & WVR_VALIDRECTS_W) {
1913 //TODO:
1914 //res = 0;
1915 }
1916 }
1917 if(win32wnd->IsMixMaxStateChanging()) {
1918 dprintf(("WM_CALCVALIDRECT: window changed min/max/restore state, invalidate entire window"));
1919 res |= CVR_REDRAW;
1920 }
1921 if(res == (CVR_ALIGNTOP|CVR_ALIGNLEFT)) {
1922 oldRect->xRight -= oldClientRect.xLeft;
1923 oldRect->yBottom += oldClientRect.yBottom;
1924 newRect->xRight -= newClientRect.xLeft;
1925 newRect->yBottom += newClientRect.yBottom;
1926 }
1927 rc = res;
1928 break;
1929 }
1930#else
1931 dprintf(("PMWINDOW: WM_CALCVALIDRECTS %x", win32wnd->getWindowHandle()));
1932 rc = (MRESULT)(CVR_ALIGNLEFT | CVR_ALIGNTOP);
1933 break;
1934#endif
1935
1936 case WM_CALCFRAMERECT:
1937 dprintf(("PMFRAME:WM_CALCFRAMERECT %x", win32wnd->getWindowHandle()));
1938 rc = (MRESULT)TRUE;
1939 break;
1940
1941 case WM_QUERYCTLTYPE:
1942 // This is a frame window
1943 dprintf(("PMFRAME:WM_QUERYCTLTYPE %x", win32wnd->getWindowHandle()));
1944 rc = (MRESULT)CCT_FRAME;
1945 break;
1946
1947#ifdef DEBUG
1948 case WM_QUERYFOCUSCHAIN:
1949 dprintf2(("PMFRAME:WM_QUERYFOCUSCHAIN %x fsCmd %x (%s) parent %x", win32wnd->getWindowHandle(), SHORT1FROMMP(mp1), DbgPrintQFCFlags(SHORT1FROMMP(mp1)), (mp2) ? OS2ToWin32Handle((DWORD)mp2) : 0));
1950
1951 RestoreOS2TIB();
1952 rc = pfnFrameWndProc(hwnd, msg, mp1, mp2);
1953 SetWin32TIB();
1954 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));
1955 break;
1956// goto RunDefFrameWndProc;
1957#endif
1958
1959 case WM_FOCUSCHANGE:
1960 {
1961 HWND hwndFocus = (HWND)mp1;
1962 HWND hwndLoseFocus, hwndGainFocus;
1963 USHORT usSetFocus = SHORT1FROMMP(mp2);
1964 USHORT fsFocusChange = SHORT2FROMMP(mp2);
1965
1966 //Save window that gains focus so we can determine which
1967 //process we lose activation to
1968 hwndFocusChange = (HWND)mp1;
1969
1970 dprintf(("PMFRAME:WM_FOCUSCHANGE %x %x (%x) %x %x", win32wnd->getWindowHandle(), OS2ToWin32Handle(hwndFocus), hwndFocus, usSetFocus, fsFocusChange));
1971 goto RunDefFrameWndProc;
1972 }
1973
1974#ifdef DEBUG
1975 case WM_SETFOCUS:
1976 {
1977 dprintf(("PMFRAME: WM_SETFOCUS %x %x %d -> %x", win32wnd->getWindowHandle(), hwnd, mp2, mp1));
1978 goto RunDefFrameWndProc;
1979 }
1980#endif
1981
1982 case WM_ACTIVATE:
1983 {
1984 HWND hwndTitle;
1985 USHORT flags = WinQueryWindowUShort(hwnd,QWS_FLAGS);
1986
1987 dprintf(("PMFRAME: WM_ACTIVATE %x %x %x", win32wnd->getWindowHandle(), mp1, OS2ToWin32Handle((DWORD)mp2)));
1988 if (win32wnd->IsWindowCreated())
1989 {
1990 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
1991 if(fOS2Look) {
1992 dprintf(("TBM_QUERYHILITE returned %d", WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_QUERYHILITE, 0, 0)));
1993 WinSendDlgItemMsg(hwnd, FID_TITLEBAR, TBM_SETHILITE, mp1, 0);
1994 }
1995 if(SHORT1FROMMP(mp1) == 0) {
1996 //deactivate
1997 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
1998 }
1999 PID pidThis, pidPartner, pidTemp;
2000 TID tidPartner;
2001 HENUM henum;
2002 HWND hwndEnum;
2003
2004 WinQueryWindowProcess(hwnd, &pidThis, NULL);
2005 WinQueryWindowProcess(hwndFocusChange, &pidPartner, &tidPartner);
2006
2007 if(pidThis != pidPartner) {
2008 //Gain or lose activation to window in other process
2009 //must send WM_ACTIVATEAPP to top-level windows
2010
2011 //Iterate over all child windows of the desktop
2012 henum = WinBeginEnumWindows(HWND_DESKTOP);
2013
2014 while(hwndEnum = WinGetNextWindow(henum))
2015 {
2016 WinQueryWindowProcess(hwndEnum, &pidTemp, NULL);
2017 if(pidTemp == pidThis)
2018 {
2019 SendMessageA(OS2ToWin32Handle(hwndEnum), WM_ACTIVATEAPP_W, (WPARAM)SHORT1FROMMP(mp1), (LPARAM)tidPartner);
2020 }
2021 }
2022 WinEndEnumWindows(henum);
2023 }
2024 if(SHORT1FROMMP(mp1)) {
2025 //activate
2026 WinSendDlgItemMsg(hwnd, FID_CLIENT, WM_ACTIVATE, mp1, mp2);
2027 }
2028
2029 //CB: show owner behind the dialog
2030 if (win32wnd->IsModalDialog())
2031 {
2032 if(win32wnd->getOwner()) {
2033 Win32BaseWindow *topOwner = Win32BaseWindow::GetWindowFromHandle(win32wnd->getOwner()->GetTopParent());
2034
2035 if (topOwner) {
2036 WinSetWindowPos(topOwner->getOS2FrameWindowHandle(),hwnd,0,0,0,0,SWP_ZORDER);
2037 RELEASE_WNDOBJ(topOwner);
2038 }
2039 }
2040 }
2041 }
2042 else
2043 {
2044 WinSetWindowUShort(hwnd,QWS_FLAGS,mp1 ? (flags | FF_ACTIVE):(flags & ~FF_ACTIVE));
2045 }
2046 rc = 0;
2047 break;
2048 }
2049
2050 case WM_ENABLE:
2051 dprintf(("PMFRAME: WM_ENABLE %x", hwnd));
2052 win32wnd->MsgEnable(SHORT1FROMMP(mp1));
2053 break;
2054
2055 case WM_SHOW:
2056 dprintf(("PMFRAME: WM_SHOW %x %d", hwnd, mp1));
2057 //show client window
2058 WinShowWindow(win32wnd->getOS2WindowHandle(), (BOOL)mp1);
2059 break;
2060
2061 case WM_QUERYTRACKINFO:
2062 {
2063 PTRACKINFO trackInfo = (PTRACKINFO)mp2;
2064
2065 dprintf(("PMFRAME:WM_QUERYTRACKINFO %x", win32wnd->getWindowHandle()));
2066 trackInfo->cxBorder = 4;
2067 trackInfo->cyBorder = 4;
2068 win32wnd->AdjustTrackInfo((PPOINT)&trackInfo->ptlMinTrackSize,(PPOINT)&trackInfo->ptlMaxTrackSize);
2069 rc = (MRESULT)TRUE;
2070 break;
2071 }
2072
2073 case WM_QUERYBORDERSIZE:
2074 {
2075 PWPOINT size = (PWPOINT)mp1;
2076
2077 dprintf(("PMFRAME:WM_QUERYBORDERSIZE %x", win32wnd->getWindowHandle()));
2078
2079 size->x = 0;
2080 size->y = 0;
2081 rc = (MRESULT)TRUE;
2082 break;
2083 }
2084
2085#ifdef DEBUG
2086 case WM_QUERYFRAMEINFO:
2087 dprintf(("PMFRAME:WM_QUERYFRAMEINFO %x", win32wnd->getWindowHandle()));
2088 goto RunDefFrameWndProc;
2089#endif
2090
2091 case WM_FORMATFRAME:
2092 dprintf(("PMFRAME:WM_FORMATFRAME %x", win32wnd->getWindowHandle()));
2093 break;
2094
2095 case WM_ADJUSTFRAMEPOS:
2096 {
2097 PSWP pswp = (PSWP)mp1;
2098
2099 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));
2100 //hack alert: the PM frame control changes the z-order of a child window
2101 // if it receives focus after a window has been destroyed
2102 // We can't let this happen as this messes up assumptions
2103 // elsewhere (e.g. GetNextDlgGroupItem)
2104 // By returning 0 here, we prevent the default frame handler
2105 // from messing things up. (one example is a group of radio buttons)
2106 //NOTE: We really need to get rid of frame & client windows for each
2107 // win32 window
2108 if(pswp->fl == SWP_FOCUSACTIVATE && win32wnd->isChild()) {
2109 rc = 0;
2110 break;
2111 }
2112 //hack alert: as we return zero as border size (check handler) we need
2113 //to do adjustments here as well or PM will calculate it for us and
2114 //result will be illegal. Btw we do not honour PM border size settings
2115 //and never will. I was unable to figure out why only X coordinate
2116 //is being broken but not Y as well.
2117
2118 if ((pswp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2119 {
2120 RECT rect;
2121 rect.left = rect.top = rect.right = rect.bottom = 0;
2122 win32wnd->AdjustMaximizedRect(&rect);
2123
2124 pswp->x += rect.left;
2125 }
2126 goto RunDefFrameWndProc;
2127 }
2128
2129#ifdef DEBUG
2130 case WM_OWNERPOSCHANGE:
2131 {
2132 PSWP pswp = (PSWP)mp1;
2133
2134 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));
2135 RestoreOS2TIB();
2136 rc = pfnFrameWndProc(hwnd, msg, mp1, mp2);
2137 SetWin32TIB();
2138 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));
2139 break;
2140 }
2141#endif
2142
2143 case WM_MINMAXFRAME:
2144 {
2145 PSWP swp = (PSWP)mp1;
2146
2147 if (!win32wnd->IsWindowCreated()) goto RunDefWndProc;
2148
2149 dprintf(("PMFRAME:WM_MINMAXFRAME %x",hwnd));
2150 if ((swp->fl & SWP_MAXIMIZE) == SWP_MAXIMIZE)
2151 {
2152 // MDI frame windows are not common PM windows so we need to
2153 // drop-out WHOLE chain of WM_X commands with SWP_MAXIMIZE flag
2154 // finally last WM_WINDOWPOSCHANGED will take care of maximization
2155
2156 if (win32wnd->getExStyle() & WS_EX_MDICHILD_W) {
2157 rc = 0;
2158 break;
2159 }
2160
2161 RECT rect;
2162 rect.left = rect.top = rect.right = rect.bottom = 0;
2163 win32wnd->AdjustMaximizedRect(&rect);
2164
2165 swp->x += rect.left;
2166 swp->cx += rect.right-rect.left;
2167 swp->y -= rect.bottom;
2168 swp->cy += rect.bottom-rect.top;
2169
2170 win32wnd->ShowWindow(SW_RESTORE_W);
2171 }
2172 else
2173 if ((swp->fl & SWP_MINIMIZE) == SWP_MINIMIZE)
2174 {
2175 win32wnd->setStyle((win32wnd->getStyle() & ~WS_MAXIMIZE_W) | WS_MINIMIZE_W);
2176 }
2177 else
2178 if ((swp->fl & SWP_RESTORE) == SWP_RESTORE)
2179 {
2180 win32wnd->setStyle(win32wnd->getStyle() & ~(WS_MINIMIZE_W | WS_MAXIMIZE_W));
2181 }
2182 goto RunDefWndProc;
2183 }
2184
2185#ifdef DEBUG
2186 case WM_UPDATEFRAME:
2187 dprintf(("PMFRAME:WM_UPDATEFRAME %x", win32wnd->getWindowHandle()));
2188 goto RunDefFrameWndProc;
2189#endif
2190
2191 case WM_TRACKFRAME:
2192 dprintf(("PMFRAME: WM_TRACKFRAME %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2193 if(fOS2Look) {//sent by titlebar control
2194 Frame_SysCommandSizeMove(win32wnd, SC_MOVE_W+HTCAPTION_W);
2195 }
2196 rc = 0;
2197 break;
2198
2199 case WM_SYSCOMMAND:
2200 dprintf(("PMFRAME: WM_SYSCOMMAND %x %x %x", win32wnd->getWindowHandle(), mp1, mp2));
2201 if (fOS2Look == OS2_APPEARANCE_SYSMENU && mp1 == (MPARAM)OSSC_SYSMENU)
2202 goto RunDefFrameWndProc;
2203
2204 if(win32wnd->getWindowHandle() != pWinMsg->hwnd) {
2205 RELEASE_WNDOBJ(win32wnd);
2206 win32wnd = Win32BaseWindow::GetWindowFromHandle(pWinMsg->hwnd);
2207 }
2208 if(win32wnd)
2209 win32wnd->DispatchMsgA(pWinMsg);
2210 break;
2211
2212#ifdef DEBUG
2213 case WM_DDE_INITIATE:
2214 case WM_DDE_INITIATEACK:
2215 case WM_DDE_REQUEST:
2216 case WM_DDE_ACK:
2217 case WM_DDE_DATA:
2218 case WM_DDE_ADVISE:
2219 case WM_DDE_UNADVISE:
2220 case WM_DDE_POKE:
2221 case WM_DDE_EXECUTE:
2222 case WM_DDE_TERMINATE:
2223 dprintf(("PMFRAME: WM_DDE %x %x", msg, win32wnd->getWindowHandle()));
2224 break;
2225#endif
2226
2227 default:
2228 goto RunDefFrameWndProc;
2229 }
2230 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2231 RestoreOS2TIB();
2232 ODIN_UnsetExceptionHandler(&exceptRegRec);
2233
2234#ifdef DEBUG
2235 dbg_ThreadPopCall();
2236#endif
2237 return (MRESULT)rc;
2238
2239RunDefFrameWndProc:
2240 dprintf2(("RunDefFrameWndProc"));
2241 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2242 RestoreOS2TIB();
2243 ODIN_UnsetExceptionHandler(&exceptRegRec);
2244
2245#ifdef DEBUG
2246 dbg_ThreadPopCall();
2247#endif
2248 return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2249
2250RunDefWndProc:
2251 dprintf2(("RunDefWndProc"));
2252 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2253 RestoreOS2TIB();
2254 ODIN_UnsetExceptionHandler(&exceptRegRec);
2255
2256 //calling WinDefWindowProc here breaks Opera hotlist window (WM_ADJUSTWINDOWPOS)
2257// return pfnFrameWndProc(hwnd, msg, mp1, mp2);
2258
2259#ifdef DEBUG
2260 dbg_ThreadPopCall();
2261#endif
2262 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2263}
2264//******************************************************************************
2265//******************************************************************************
2266MRESULT EXPENTRY Win32FakeWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
2267{
2268 PFNWP pfnOldWindowProc;
2269 Win32BaseWindow *win32wnd, *win32wndchild;
2270 TEB *teb;
2271 MRESULT rc = 0;
2272 EXCEPTIONREGISTRATIONRECORD exceptRegRec = {0,0};
2273
2274 //Restore our FS selector
2275 SetWin32TIB();
2276
2277 win32wnd = Win32FakeWindow::GetWindowFromOS2Handle(hwnd);
2278 if(win32wnd == NULL) {
2279 DebugInt3();
2280 goto RunDefWndProc;
2281 }
2282
2283 pfnOldWindowProc = (PFNWP)win32wnd->getOldPMWindowProc();
2284 if(pfnOldWindowProc == NULL) {
2285 DebugInt3();
2286 goto RunDefWndProc;
2287 }
2288
2289 RestoreOS2TIB();
2290 rc = pfnOldWindowProc(hwnd, msg, mp1, mp2);
2291
2292 ODIN_SetExceptionHandler(&exceptRegRec);
2293 SetWin32TIB();
2294 switch(msg) {
2295 case WM_WINDOWPOSCHANGED:
2296 {
2297 PSWP pswp = (PSWP)mp1,pswpOld = pswp+1;
2298 SWP swpOld = *(pswp + 1);
2299 WINDOWPOS wp;
2300
2301 if(win32wnd->getParent()) {
2302 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, win32wnd->getParent()->getClientHeight(),
2303 hwnd);
2304 }
2305 else OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, OSLibQueryScreenHeight(), hwnd);
2306
2307 win32wnd->SetWindowPos(wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
2308 break;
2309 }
2310
2311 }
2312 if(win32wnd) RELEASE_WNDOBJ(win32wnd);
2313 RestoreOS2TIB();
2314 ODIN_UnsetExceptionHandler(&exceptRegRec);
2315 return rc;
2316
2317RunDefWndProc:
2318 RestoreOS2TIB();
2319 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
2320}
2321//******************************************************************************
2322// PMWinSubclassFakeWindow
2323//
2324// Subclass a fake window (converted PM window)
2325//
2326// Parameters
2327//
2328// HWND hwndOS2 - PM handle of fake window
2329//
2330// Returns
2331// NULL - Failure
2332// else - Old PM window procedure
2333//
2334//******************************************************************************
2335PVOID PMWinSubclassFakeWindow(HWND hwndOS2)
2336{
2337 return WinSubclassWindow(hwndOS2, Win32FakeWindowProc);
2338}
2339//******************************************************************************
2340//******************************************************************************
2341void FrameSetFocus(HWND hwnd)
2342{
2343 HWND hwndFocusSave = WinQueryWindowULong(hwnd, QWL_HWNDFOCUSSAVE);
2344 if(!WinIsWindow(hab, hwndFocusSave)) {
2345 hwndFocusSave = WinWindowFromID(hwnd, FID_CLIENT);
2346 WinSetWindowULong(hwnd, QWL_HWNDFOCUSSAVE, hwndFocusSave);
2347 }
2348 dprintf(("FrameSetFocus: hwndFocusSave %x %x", OS2ToWin32Handle(hwndFocusSave), hwndFocusSave));
2349 dprintf(("FrameSetFocus: cur focus=%x (%x) cur active=%x (%x)\n",
2350 WinQueryFocus(HWND_DESKTOP), OS2ToWin32Handle(WinQueryFocus(HWND_DESKTOP)),
2351 WinQueryActiveWindow(HWND_DESKTOP), OS2ToWin32Handle(WinQueryActiveWindow(HWND_DESKTOP))));
2352 WinSetFocus(HWND_DESKTOP, hwndFocusSave);
2353
2354 ULONG ulFrameFlags = WinQueryWindowUShort(hwnd, QWS_FLAGS);
2355 ulFrameFlags &= ~FF_NOACTIVATESWP;
2356 WinSetWindowUShort(hwnd, QWS_FLAGS, ulFrameFlags);
2357}
2358//******************************************************************************
2359//******************************************************************************
2360void FrameReplaceMenuItem(HWND hwndMenu, ULONG nIndex, ULONG idOld, ULONG idNew,
2361 HBITMAP hbmNew)
2362{
2363 MENUITEM mi;
2364
2365 if (!hwndMenu)
2366 return;
2367
2368 WinEnableWindowUpdate(hwndMenu, FALSE);
2369
2370 if (WinSendMsg(hwndMenu, MM_QUERYITEM, MPFROM2SHORT(idOld, TRUE), MPFROMP(&mi)))
2371 {
2372 WinSendMsg(hwndMenu, MM_REMOVEITEM, (MPARAM)idOld, 0);
2373 mi.afStyle = MIS_BITMAP | MIS_SYSCOMMAND;
2374 mi.afAttribute = 0;
2375 mi.hwndSubMenu = 0;
2376 mi.id = idNew;
2377 mi.hItem = (ULONG)hbmNew;
2378 WinSendMsg(hwndMenu, MM_INSERTITEM, (MPARAM)&mi, 0);
2379 }
2380 else
2381 dprintf(("WARNING: FrameReplaceMenuItem control %x not found",idOld));
2382
2383 WinEnableWindowUpdate(hwndMenu, TRUE);
2384
2385 WinInvalidateRect(hwndMenu, NULL, TRUE);
2386}
2387//******************************************************************************
2388//******************************************************************************
2389void RecalcVisibleRegion(Win32BaseWindow *win32wnd)
2390{
2391 //Workaround for PM/GPI bug when moving/sizing a window with open DCs
2392 //
2393 //Windows applictions often get a DC and keep it open for the duration
2394 //of the application. When the DC's window is moved (full window dragging on)
2395 //PM/GPI doesn't seem to update the DC properly/in time.
2396 //This can result is visible distortions on the screen.
2397
2398 //We need to reset our DC (transformation & y-inversion) (#945)
2399 //Debugging showed that querying the visible region of a DC will cure
2400 //this problem (GPI probably recalculates the visible region). (#334)
2401
2402 int nrdcs = 0;
2403 HDC hdcWindow[MAX_OPENDCS];
2404
2405 if(win32wnd->queryOpenDCs(hdcWindow, MAX_OPENDCS, &nrdcs))
2406 {
2407 for(int i=0;i<nrdcs;i++)
2408 {
2409 dprintf(("Recalc visible region of DC %x for window %x", hdcWindow[i], win32wnd->getWindowHandle()));
2410
2411 pDCData pHps = (pDCData)GpiQueryDCData (hdcWindow[i]);
2412
2413 if(pHps) setPageXForm (win32wnd, pHps);
2414 else DebugInt3();
2415 }
2416 }
2417 //Workaround END
2418}
2419//******************************************************************************
2420//******************************************************************************
2421static char *PMDragExtractFiles(PDRAGINFO pDragInfo, ULONG *pcItems, ULONG *pulBytes)
2422{
2423 PDRAGITEM pDragItem;
2424 int i, cItems;
2425 BOOL ret;
2426 char szFileName[CCHMAXPATH];
2427 char szContainerName[CCHMAXPATH];
2428 ULONG ulBytes;
2429 char *pszCurFile = NULL;
2430
2431 /* Get access to the DRAGINFO data structure */
2432 if(!DrgAccessDraginfo(pDragInfo)) {
2433 return NULL;
2434 }
2435
2436 cItems = DrgQueryDragitemCount(pDragInfo);
2437
2438 //compute memory required to hold all filenames
2439 int bufsize = 0;
2440 for (i = 0; i < cItems; i++) {
2441 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2442
2443 bufsize += DrgQueryStrNameLen(pDragItem->hstrContainerName) + DrgQueryStrNameLen(pDragItem->hstrSourceName);
2444 bufsize++; //0 terminator
2445 bufsize++; //+ potential missing backslash
2446 }
2447 bufsize++; //extra 0 terminator
2448 char *pszFiles = (char *)malloc(bufsize);
2449 if(pszFiles == NULL) {
2450 dprintf(("Out of memory!!"));
2451 DebugInt3();
2452 goto failure;
2453 }
2454 memset(pszFiles, 0, bufsize);
2455
2456 pszCurFile = pszFiles;
2457
2458 //copy all filenames
2459 for (i = 0; i < cItems; i++) {
2460 char *pszTemp = pszCurFile;
2461
2462 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2463
2464 ulBytes = DrgQueryStrNameLen(pDragItem->hstrContainerName);
2465 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2466 ulBytes, pszCurFile);
2467 if(pszCurFile[ulBytes-1] != '\\') {
2468 pszCurFile[ulBytes] = '\\';
2469 pszCurFile++;
2470 }
2471 pszCurFile += ulBytes;
2472
2473 ulBytes = DrgQueryStrNameLen(pDragItem->hstrSourceName);
2474 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2475 ulBytes+1, pszCurFile);
2476 pszCurFile += ulBytes + 1; //+ terminator
2477
2478 dprintf(("dropped file %s", pszTemp));
2479 }
2480
2481 /* Release the draginfo data structure */
2482 DrgFreeDraginfo(pDragInfo);
2483
2484 *pulBytes = bufsize;
2485 *pcItems = cItems;
2486
2487 return pszFiles;
2488
2489failure:
2490 /* Release the draginfo data structure */
2491 DrgFreeDraginfo(pDragInfo);
2492 if(pszFiles) {
2493 free(pszFiles);
2494 }
2495 return NULL;
2496}
2497//******************************************************************************
2498//******************************************************************************
2499static BOOL PMDragValidate(PDRAGINFO pDragInfo)
2500{
2501 PDRAGITEM pDragItem;
2502 ULONG ulBytes;
2503 int i, cItems;
2504 BOOL ret;
2505 char szFileName[CCHMAXPATH];
2506 char szContainerName[CCHMAXPATH];
2507 USHORT usOp = DO_MOVE;
2508
2509 /* Get access to the DRAGINFO data structure */
2510 if(!DrgAccessDraginfo(pDragInfo)) {
2511 return FALSE;
2512 }
2513
2514 /* Can we accept this drop? */
2515 switch (pDragInfo->usOperation) {
2516 /* Return DOR_NODROPOP if current operation */
2517 /* is link or unknown */
2518 case DO_LINK:
2519 case DO_COPY:
2520 case DO_UNKNOWN:
2521 goto failure;
2522
2523 /* Our default operation is Move */
2524 case DO_MOVE:
2525 case DO_DEFAULT:
2526 pDragItem = DrgQueryDragitemPtr(pDragInfo, 0);
2527 ulBytes = DrgQueryStrName(pDragItem->hstrContainerName,
2528 sizeof(szContainerName),
2529 szContainerName);
2530 ulBytes = DrgQueryStrName(pDragItem->hstrSourceName,
2531 sizeof(szFileName),
2532 szFileName);
2533 if (!ulBytes) {
2534 goto failure;
2535 }
2536
2537 dprintf(("dropped file %s%s", szContainerName, szFileName));
2538 break;
2539 }
2540
2541 cItems = DrgQueryDragitemCount(pDragInfo);
2542
2543 /* Now, we need to look at each item in turn */
2544 for (i = 0; i < cItems; i++) {
2545 pDragItem = DrgQueryDragitemPtr(pDragInfo, i);
2546
2547 /* Make sure we can move for a Move request */
2548 if (!((pDragItem->fsSupportedOps & DO_MOVEABLE) &&
2549 (usOp == (USHORT)DO_MOVE)))
2550 {
2551 dprintf(("item %d not accepted", i));
2552 goto failure;
2553 }
2554 }
2555 /* Release the draginfo data structure */
2556 DrgFreeDraginfo(pDragInfo);
2557 return TRUE;
2558
2559failure:
2560 DrgFreeDraginfo(pDragInfo);
2561 return FALSE;
2562}
2563
2564//******************************************************************************
2565// Override std class names we use in Odin (necessary for keyboard hook)
2566//******************************************************************************
2567void WIN32API SetCustomStdClassName(LPSTR pszStdClassName)
2568{
2569 strcpy(WIN32_STDCLASS, pszStdClassName);
2570}
2571//******************************************************************************
2572//******************************************************************************
2573char *WIN32API QueryCustomStdClassName()
2574{
2575 return WIN32_STDCLASS;
2576}
2577//******************************************************************************
2578//******************************************************************************
2579
2580#ifdef DEBUG_LOGGING
2581static char *DbgGetStringSWPFlags(ULONG flags)
2582{
2583 static char szSWPFlags[512];
2584
2585 szSWPFlags[0] = 0;
2586
2587 if(flags & SWP_SIZE) {
2588 strcat(szSWPFlags, "SWP_SIZE ");
2589 }
2590 if(flags & SWP_MOVE) {
2591 strcat(szSWPFlags, "SWP_MOVE ");
2592 }
2593 if(flags & SWP_ZORDER) {
2594 strcat(szSWPFlags, "SWP_ZORDER ");
2595 }
2596 if(flags & SWP_SHOW) {
2597 strcat(szSWPFlags, "SWP_SHOW ");
2598 }
2599 if(flags & SWP_HIDE) {
2600 strcat(szSWPFlags, "SWP_HIDE ");
2601 }
2602 if(flags & SWP_NOREDRAW) {
2603 strcat(szSWPFlags, "SWP_NOREDRAW ");
2604 }
2605 if(flags & SWP_NOADJUST) {
2606 strcat(szSWPFlags, "SWP_NOADJUST ");
2607 }
2608 if(flags & SWP_ACTIVATE) {
2609 strcat(szSWPFlags, "SWP_ACTIVATE ");
2610 }
2611 if(flags & SWP_DEACTIVATE) {
2612 strcat(szSWPFlags, "SWP_DEACTIVATE ");
2613 }
2614 if(flags & SWP_EXTSTATECHANGE) {
2615 strcat(szSWPFlags, "SWP_EXTSTATECHANGE ");
2616 }
2617 if(flags & SWP_MINIMIZE) {
2618 strcat(szSWPFlags, "SWP_MINIMIZE ");
2619 }
2620 if(flags & SWP_MAXIMIZE) {
2621 strcat(szSWPFlags, "SWP_MAXIMIZE ");
2622 }
2623 if(flags & SWP_RESTORE) {
2624 strcat(szSWPFlags, "SWP_RESTORE ");
2625 }
2626 if(flags & SWP_FOCUSACTIVATE) {
2627 strcat(szSWPFlags, "SWP_FOCUSACTIVATE ");
2628 }
2629 if(flags & SWP_FOCUSDEACTIVATE) {
2630 strcat(szSWPFlags, "SWP_FOCUSDEACTIVATE ");
2631 }
2632 if(flags & SWP_NOAUTOCLOSE) {
2633 strcat(szSWPFlags, "SWP_NOAUTOCLOSE ");
2634 }
2635 return szSWPFlags;
2636}
2637static char *DbgPrintQFCFlags(ULONG flags)
2638{
2639 static char szQFCFlags[64];
2640
2641 szQFCFlags[0] = 0;
2642
2643 if(flags & QFC_NEXTINCHAIN) {
2644 strcat(szQFCFlags, "QFC_NEXTINCHAIN");
2645 }
2646 else
2647 if(flags & QFC_ACTIVE) {
2648 strcat(szQFCFlags, "QFC_ACTIVE");
2649 }
2650 else
2651 if(flags & QFC_FRAME) {
2652 strcat(szQFCFlags, "QFC_FRAME");
2653 }
2654 else
2655 if(flags & QFC_SELECTACTIVE) {
2656 strcat(szQFCFlags, "QFC_SELECTACTIVE");
2657 }
2658 else
2659 if(flags & QFC_PARTOFCHAIN) {
2660 strcat(szQFCFlags, "QFC_PARTOFCHAIN");
2661 }
2662
2663 return szQFCFlags;
2664}
2665#endif
2666
Note: See TracBrowser for help on using the repository browser.