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

Last change on this file since 21341 was 21341, checked in by vladest, 16 years ago

Reworked double free check to make sure the patch will not harm other apps

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