source: trunk/src/user32/win32wbase.cpp@ 22134

Last change on this file since 22134 was 22134, checked in by dmik, 8 years ago

user32: Do not touch user data of foreign OS/2 windows.

This is plain wrong as these windows' classes are not created by Odin so
it must not make assumptions about window data usage. It fixes Firefox malfunction
when using Flash, see https://github.com/bitwiseworks/mozilla-os2/issues/229.

File size: 152.1 KB
Line 
1/* $Id: win32wbase.cpp,v 1.390 2004-05-24 09:02:00 sandervl Exp $ */
2/*
3 * Win32 Window Base Class for OS/2
4 *
5 * Copyright 1998-2002 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 * Copyright 1999-2000 Christoph Bratschi (cbratschi@datacomm.ch)
8 *
9 * Parts based on Wine Windows code (windows\win.c)
10 * Corel version: corel20000212
11 *
12 * Copyright 1993, 1994, 1996 Alexandre Julliard
13 * 1995 Alex Korobka
14 *
15 * TODO: Not thread/process safe
16 *
17 * NOTE: To access a window object, you must call GetWindowFromOS2Handle or
18 * GetWindowFromHandle. Both these methods increase the reference count
19 * of the object. When you're done with the object, you MUST call
20 * the release method!
21 * This mechanism prevents premature destruction of objects when there
22 * are still clients using it.
23 *
24 * NOTE: Client rectangle always relative to frame window
25 * Window rectangle in parent coordinates (relative to parent's client window)
26 * (screen coord. if no parent)
27 *
28 * NOTE: Status of window:
29 * Before a window has processed WM_NCCREATE:
30 * - GetTopWindow can't return that window handle
31 * - GetWindow(parent, GW_CHILD) can't return that window handle
32 * - IsChild works
33 * TODO: Does this affect more functions?? (other GetWindow ops)
34 * (verified in NT4, SP6)
35 *
36 * Project Odin Software License can be found in LICENSE.TXT
37 *
38 */
39#include <os2win.h>
40#include <win.h>
41#include <stdlib.h>
42#include <string.h>
43#include <stdarg.h>
44#include <assert.h>
45#include <misc.h>
46#include <heapstring.h>
47#include <winuser32.h>
48#include <custombuild.h>
49#include "win32wbase.h"
50#include "win32wfake.h"
51#include "wndmsg.h"
52#include "oslibwin.h"
53#include "oslibmsg.h"
54#include "oslibutil.h"
55#include "oslibgdi.h"
56#include "oslibres.h"
57#include "oslibdos.h"
58#include "syscolor.h"
59#include "win32wndhandle.h"
60#include "dc.h"
61#include "win32wdesktop.h"
62#include "pmwindow.h"
63#include "controls.h"
64#include <wprocess.h>
65#include <win/hook.h>
66#include "menu.h"
67#define INCL_TIMERWIN32
68#include "timer.h"
69#include "user32api.h"
70#include "callwrap.h"
71
72#define DBG_LOCALLOG DBG_win32wbase
73#include "dbglocal.h"
74
75/* bits in the dwKeyData */
76#define KEYDATA_ALT 0x2000
77#define KEYDATA_PREVSTATE 0x4000
78
79void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle);
80
81static BOOL fDestroyAll = FALSE;
82//For quick lookup of current process id
83static ULONG currentProcessId = -1;
84static int iF10Key = 0;
85static int iMenuSysKey = 0;
86
87//******************************************************************************
88//******************************************************************************
89Win32BaseWindow::Win32BaseWindow()
90 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
91{
92 Init();
93}
94//******************************************************************************
95//******************************************************************************
96Win32BaseWindow::Win32BaseWindow(CREATESTRUCTA *lpCreateStructA, ATOM classAtom, BOOL isUnicode)
97 : GenericObject(&windows, &critsect), ChildWindow(&critsect)
98{
99 Init();
100 this->isUnicode = isUnicode;
101 // call member function
102 CreateWindowExA(lpCreateStructA, classAtom);
103}
104//******************************************************************************
105//******************************************************************************
106void Win32BaseWindow::Init()
107{
108 isUnicode = FALSE;
109 fFirstShow = TRUE;
110 fIsDialog = FALSE;
111 fIsModalDialogOwner = FALSE;
112 OS2HwndModalDialog = 0;
113 fParentChange = FALSE;
114 fDestroyWindowCalled = FALSE;
115 fChildDestructionInProgress = FALSE;
116 fTaskList = FALSE;
117 fParentDC = FALSE;
118 fComingToTop = FALSE;
119 fMinMaxChange = FALSE;
120 fPMUpdateRegionChanged = FALSE;
121 fEraseBkgndFlag = TRUE;
122 fIsDragDropActive= FALSE;
123 fDirtyUpdateRegion = FALSE;
124 fWindowLocked = FALSE;
125
126 state = STATE_INIT;
127 windowNameA = NULL;
128 windowNameW = NULL;
129 windowNameLengthA = 0;
130 windowNameLengthW = 0;
131
132 userWindowBytes = NULL;;
133 nrUserWindowBytes= 0;
134
135 OS2Hwnd = 0;
136 OS2HwndFrame = 0;
137 hSysMenu = 0;
138 Win32Hwnd = 0;
139
140 // allocate a Win32 HWND, return it in Win32Hwnd and associate object
141 // pointer with it
142 if(HwAllocateWindowHandle(&Win32Hwnd, (ULONG)this) == FALSE)
143 {
144 dprintf(("Win32BaseWindow::Init HwAllocateWindowHandle failed!!"));
145 DebugInt3();
146 }
147 Win32HwndOrg = Win32Hwnd;
148
149 posx = posy = 0;
150 width = height = 0;
151
152 dwExStyle = 0;
153 dwStyle = 0;
154 dwOldStyle = 0;
155 win32wndproc = 0;
156 hInstance = 0;
157 dwIDMenu = 0; //0xFFFFFFFF; //default -1
158 userData = 0;
159 contextHelpId = 0;
160 hotkey = 0;
161
162 hwndLinkAfter = HWND_BOTTOM;
163 flags = 0;
164 lastHitTestVal = HTCLIENT;
165 owner = NULL;
166 windowClass = 0;
167
168 hIcon = 0;
169 hIconSm = 0;
170
171 horzScrollInfo = NULL;
172 vertScrollInfo = NULL;
173
174 propertyList = NULL;
175
176 cbExtra = 0;
177 pExtra = NULL;
178
179 ownDC = 0;
180 hWindowRegion = 0;
181 hClipRegion = 0;
182 hVisRegion = 0;
183 hUpdateRegion = 0;
184
185 hTaskList = 0;
186
187 if(currentProcessId == -1)
188 {
189 currentProcessId = GetCurrentProcessId();
190 }
191 dwThreadId = GetCurrentThreadId();
192 dwProcessId = currentProcessId;
193
194 memset(&windowpos, 0, sizeof(windowpos));
195 //min and max position are initially -1 (verified in NT4, SP6)
196 windowpos.ptMinPosition.x = -1;
197 windowpos.ptMinPosition.y = -1;
198 windowpos.ptMaxPosition.x = -1;
199 windowpos.ptMaxPosition.y = -1;
200
201 lpVisRgnNotifyProc = NULL;
202 dwVisRgnNotifyParam = NULL;
203
204 pfnOldPMWndProc = NULL;
205
206 memset(hdcWindow, 0, sizeof(hdcWindow));
207 nrOpenDCs = 0;
208}
209//******************************************************************************
210//todo get rid of resources (menu, icon etc)
211//******************************************************************************
212Win32BaseWindow::~Win32BaseWindow()
213{
214 if(getRefCount() < 0) {
215 DebugInt3();
216 }
217
218 if(hTaskList) {
219 OSLibWinRemoveFromTasklist(hTaskList);
220 }
221
222 if (!isFakeWindow()) {
223 OSLibWinSetVisibleRegionNotify(OS2Hwnd, FALSE);
224 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, 0);
225 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, 0);
226 }
227
228 if(fDestroyAll) {
229 dprintf(("Destroying window %x %s", getWindowHandle(), windowNameA));
230 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
231 }
232 else
233 if(getParent() && getParent()->getFirstChild() == this && getNextChild() == NULL)
234 {
235 //if we're the last child that's being destroyed and our
236 //parent window was also destroyed, then we
237 if(getParent()->IsWindowDestroyed())
238 {
239 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
240 RELEASE_WNDOBJ(wndparent);
241 setParent(NULL); //or else we'll crash in the dtor of the ChildWindow class
242 }
243 }
244 else
245 {
246 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
247 if(wndparent && !fDestroyAll) {
248 RELEASE_WNDOBJ(wndparent);
249 }
250 }
251 if(owner && !fDestroyAll) {
252 RELEASE_WNDOBJ(owner);
253 }
254
255 // Decrement class window counter
256 // NOTE: Must be done before ReleaseDC call for ownDC!
257 if(windowClass) {
258 RELEASE_CLASSOBJ(windowClass);
259 }
260
261 if(ownDC)
262 ReleaseDC(Win32HwndOrg, ownDC);
263
264 if(Win32Hwnd)
265 HwFreeWindowHandle(Win32Hwnd);
266
267 if(userWindowBytes)
268 free(userWindowBytes);
269
270 if(windowNameA) {
271 free(windowNameA);
272 windowNameA = NULL;
273 }
274 if(windowNameW) {
275 free(windowNameW);
276 windowNameW = NULL;
277 }
278 if(vertScrollInfo) {
279 free(vertScrollInfo);
280 vertScrollInfo = NULL;
281 }
282 if(horzScrollInfo) {
283 free(horzScrollInfo);
284 horzScrollInfo = NULL;
285 }
286 if(propertyList) {
287 removeWindowProps();
288 }
289 if(hUpdateRegion) {
290 DeleteObject(hUpdateRegion);
291 hUpdateRegion = NULL;
292 }
293}
294//******************************************************************************
295//******************************************************************************
296void Win32BaseWindow::DestroyAll()
297{
298 fDestroyAll = TRUE;
299 GenericObject::DestroyAll(windows);
300}
301//******************************************************************************
302//******************************************************************************
303BOOL Win32BaseWindow::isChild()
304{
305 return ((dwStyle & WS_CHILD) != 0);
306}
307//******************************************************************************
308//******************************************************************************
309BOOL Win32BaseWindow::IsWindowUnicode()
310{
311 dprintf2(("IsWindowUnicode %x %d", getWindowHandle(),
312 WINPROC_GetProcType((HWINDOWPROC)getWindowProc()) == WIN_PROC_32W));
313 return (WINPROC_GetProcType((HWINDOWPROC)getWindowProc()) == WIN_PROC_32W);
314}
315//******************************************************************************
316//******************************************************************************
317BOOL Win32BaseWindow::CreateWindowExA(CREATESTRUCTA *cs, ATOM classAtom)
318{
319 char buffer[256];
320
321#ifdef DEBUG
322 PrintWindowStyle(cs->style, cs->dwExStyle);
323#endif
324
325 //If window has no owner/parent window, then it will be added to the tasklist
326 //(depending on visibility state)
327 if (!cs->hwndParent) fTaskList = TRUE;
328
329 sw = SW_SHOW;
330 SetLastError(0);
331
332 /* Find the parent window */
333 if (cs->hwndParent)
334 {
335 Win32BaseWindow *window = GetWindowFromHandle(cs->hwndParent);
336 if(!window) {
337 dprintf(("Bad parent %04x\n", cs->hwndParent ));
338 SetLastError(ERROR_INVALID_PARAMETER);
339 return FALSE;
340 }
341 /* Make sure parent is valid */
342 if (!window->IsWindow() )
343 {
344 RELEASE_WNDOBJ(window);
345 dprintf(("Bad parent %04x\n", cs->hwndParent ));
346 SetLastError(ERROR_INVALID_PARAMETER);
347 return FALSE;
348 }
349 if (window->getExStyle() & WS_EX_TOPMOST)
350 cs->dwExStyle |= WS_EX_TOPMOST;
351
352 RELEASE_WNDOBJ(window);
353 /* Windows does this for overlapped windows
354 * (I don't know about other styles.) */
355 if (cs->hwndParent == GetDesktopWindow() && (!(cs->style & WS_CHILD) || (cs->style & WS_POPUP)))
356 {
357 cs->hwndParent = 0;
358 }
359 }
360 else
361 if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
362 dprintf(("No parent for child window" ));
363 SetLastError(ERROR_INVALID_PARAMETER);
364 return FALSE; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
365 }
366
367 /* Find the window class */
368 windowClass = Win32WndClass::FindClass(cs->hInstance, (LPSTR)classAtom);
369 if (!windowClass)
370 {
371 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
372 dprintf(("Bad class '%s'", buffer ));
373 SetLastError(ERROR_INVALID_PARAMETER);
374 return 0;
375 }
376
377#ifdef DEBUG
378 if(HIWORD(cs->lpszClass))
379 {
380 if(isUnicode) dprintf(("Window class %ls", cs->lpszClass));
381 else dprintf(("Window class %s", cs->lpszClass));
382 }
383 else dprintf(("Window class %x", cs->lpszClass));
384#endif
385
386 /* Fix the lpszClass field: from existing programs, it seems ok to call a CreateWindowXXX
387 * with an atom as the class name, put some programs expect to have a *REAL* string in
388 * lpszClass when the CREATESTRUCT is sent with WM_CREATE
389 */
390 if (!HIWORD(cs->lpszClass) ) {
391 if (isUnicode) {
392 GlobalGetAtomNameW( classAtom, (LPWSTR)buffer, sizeof(buffer) );
393 }
394 else {
395 GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) );
396 }
397 cs->lpszClass = buffer;
398 }
399 /* Fix the coordinates */
400 fXDefault = FALSE;
401 fCXDefault = FALSE;
402 FixCoordinates(cs, &sw);
403
404 /* Correct the window style - stage 1
405 *
406 * These are patches that appear to affect both the style loaded into the
407 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
408 *
409 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
410 * why does the user get to set it?
411 */
412
413 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
414 * tested for WS_POPUP
415 */
416 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
417 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
418 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
419 cs->dwExStyle |= WS_EX_WINDOWEDGE;
420 else
421 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
422
423 //Allocate window words
424 nrUserWindowBytes = windowClass->getExtraWndBytes();
425 if(nrUserWindowBytes) {
426 userWindowBytes = (char *)_smalloc(nrUserWindowBytes);
427 memset(userWindowBytes, 0, nrUserWindowBytes);
428 }
429
430 // check if it's the standard child window case
431 if ((cs->style & WS_CHILD) && cs->hwndParent)
432 {
433 SetParent(cs->hwndParent);
434 owner = NULL;
435 //SvL: Shell positioning shouldn't be done for child windows! (breaks Notes)
436 fXDefault = fCXDefault = FALSE;
437 }
438 else
439 {
440 // either no child window or a popup window
441
442 SetParent(0);
443 if (!cs->hwndParent || (cs->hwndParent == windowDesktop->getWindowHandle())) {
444 owner = NULL;
445 }
446 else
447 {
448 // we're a popup window
449
450 Win32BaseWindow *wndparent = GetWindowFromHandle(cs->hwndParent);
451 if(wndparent) {
452 owner = GetWindowFromHandle(wndparent->GetTopParent());
453 RELEASE_WNDOBJ(wndparent);
454 }
455 else owner = NULL;
456
457 if(owner == NULL)
458 {
459 dprintf(("HwGetWindowHandleData couldn't find owner window %x!!!", cs->hwndParent));
460 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
461 return FALSE;
462 }
463 }
464 }
465
466 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc,
467 windowClass->getWindowProc((isUnicode) ? WNDPROC_UNICODE : WNDPROC_ASCII),
468 WINPROC_GetProcType((HWINDOWPROC)windowClass->getWindowProc((isUnicode) ? WNDPROC_UNICODE : WNDPROC_ASCII)),
469 WIN_PROC_WINDOW);
470 hInstance = cs->hInstance;
471 dwStyle = cs->style & ~WS_VISIBLE;
472 dwOldStyle = dwStyle;
473 dwExStyle = cs->dwExStyle;
474
475 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
476
477 /* Correct the window style phase 2 */
478 if (!(cs->style & WS_CHILD))
479 {
480 dwStyle |= WS_CLIPSIBLINGS;
481 if (!(cs->style & WS_POPUP))
482 {
483 dwStyle |= WS_CAPTION;
484 flags |= WIN_NEED_SIZE;
485 }
486 }
487
488 //WinZip 8.0 crashes when a dialog created after opening a zipfile receives
489 //the WM_SIZE message (before WM_INITDIALOG)
490 //Opera doesn't like this either.
491 if(IsDialog()) {
492 flags |= WIN_NEED_SIZE;
493 }
494
495 //copy pointer of CREATESTRUCT for usage in MsgCreate method
496 tmpcs = cs;
497
498 //Store our window object pointer in thread local memory, so PMWINDOW.CPP can retrieve it
499 TEB *teb = GetThreadTEB();
500 if(teb == NULL) {
501 dprintf(("Window creation failed - teb == NULL")); //this is VERY bad
502 ExitProcess(666);
503 return FALSE;
504 }
505 teb->o.odin.newWindow = (ULONG)this;
506
507 DWORD dwOSWinStyle, dwOSFrameStyle;
508 OSLibWinConvertStyle(dwStyle,dwExStyle,&dwOSWinStyle, &dwOSFrameStyle);
509
510 // create PM windows - frame and client window
511 HWND hwndOS2Frame = (getParent()) ? getParent()->getOS2WindowHandle() : OSLIB_HWND_DESKTOP;
512 OS2Hwnd = OSLibWinCreateWindow(hwndOS2Frame,
513 dwOSWinStyle,
514 dwOSFrameStyle,
515 (char *)windowNameA,
516 (owner) ? owner->getOS2WindowHandle() : 0,
517 (hwndLinkAfter == HWND_BOTTOM) ? TRUE : FALSE,
518 0,
519 fTaskList,
520 fXDefault | fCXDefault,
521 windowClass->getStyle(),
522 &OS2HwndFrame);
523 if(OS2Hwnd == 0) {
524 dprintf(("Window creation failed!! OS LastError %0x", OSLibWinGetLastError()));
525 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
526 return FALSE;
527 }
528 OSLibWinSetVisibleRegionNotify(OS2Hwnd, TRUE);
529 state = STATE_CREATED;
530 SetLastError(0);
531 return TRUE;
532}
533//******************************************************************************
534//******************************************************************************
535BOOL Win32BaseWindow::MsgCreate(HWND hwndOS2)
536{
537 CREATESTRUCTA *cs = tmpcs; //pointer to CREATESTRUCT used in CreateWindowExA method
538 POINT maxSize, maxPos, minTrack, maxTrack;
539 HWND hwnd = getWindowHandle();
540 LRESULT (* CALLBACK localSend32)(HWND, UINT, WPARAM, LPARAM);
541
542 OS2Hwnd = hwndOS2;
543
544 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, getWindowHandle()) == FALSE) {
545 dprintf(("WM_CREATE: WinSetWindowULong %X failed!!", OS2Hwnd));
546 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
547 return FALSE;
548 }
549 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, WIN32PM_MAGIC) == FALSE) {
550 dprintf(("WM_CREATE: WinSetWindowULong2 %X failed!!", OS2Hwnd));
551 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
552 return FALSE;
553 }
554 if(OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32FLAGS, 0) == FALSE) {
555 dprintf(("WM_CREATE: WinSetWindowULong2 %X failed!!", OS2Hwnd));
556 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
557 return FALSE;
558 }
559
560 if (HOOK_IsHooked( WH_CBT ))
561 {
562 CBT_CREATEWNDA cbtc;
563 LRESULT ret;
564
565 cbtc.lpcs = cs;
566 cbtc.hwndInsertAfter = hwndLinkAfter;
567 ret = (isUnicode) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND, getWindowHandle(), (LPARAM)&cbtc)
568 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND, getWindowHandle(), (LPARAM)&cbtc);
569 if(ret)
570 {
571 dprintf(("CBT-hook returned non-0 !!"));
572 SetLastError(ERROR_CAN_NOT_COMPLETE); //todo: wrong error
573 return FALSE;
574 }
575 //todo: if hook changes parent, we need to do so too!!!!!!!!!!
576 }
577
578 if (cs->style & WS_HSCROLL)
579 {
580 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
581 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
582 horzScrollInfo->MaxVal = 100;
583 horzScrollInfo->flags = ESB_ENABLE_BOTH;
584 }
585
586 if (cs->style & WS_VSCROLL)
587 {
588 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
589 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
590 vertScrollInfo->MaxVal = 100;
591 vertScrollInfo->flags = ESB_ENABLE_BOTH;
592 }
593
594 // initially allocate the window name fields
595 if(HIWORD(cs->lpszName))
596 {
597 if (!isUnicode)
598 {
599 windowNameLengthA = strlen(cs->lpszName);
600 windowNameA = (LPSTR)_smalloc(windowNameLengthA+1);
601 strcpy(windowNameA,cs->lpszName);
602
603 windowNameLengthW = lstrlenAtoW( windowNameA, -1 );
604 windowNameW = (LPWSTR)_smalloc(( windowNameLengthW + 1 ) * sizeof( WCHAR ) );
605 lstrcpyAtoW( windowNameW, windowNameA );
606 }
607 else
608 {
609 // Wide
610 windowNameLengthW = lstrlenW((LPWSTR)cs->lpszName);
611 windowNameW = (LPWSTR)_smalloc((windowNameLengthW+1)*sizeof(WCHAR));
612 strcpyW(windowNameW,(LPWSTR)cs->lpszName);
613
614 // windowNameW[lstrlenW((LPWSTR)cs->lpszName)] = 0; // need ?
615
616 // Ascii
617 windowNameLengthA = lstrlenWtoA( windowNameW, -1 );
618 windowNameA = (LPSTR)_smalloc( windowNameLengthA + 1 );
619 lstrcpyWtoA( windowNameA, windowNameW );
620 }
621
622 dprintf(("windowNameA 0x%lx to 0x%lx windowNameW : 0x%lx to 0x%lx",
623 windowNameA, windowNameA + windowNameLengthA,
624 windowNameW, windowNameW + windowNameLengthW ));
625
626 if(fOS2Look) {
627 OSLibWinSetTitleBarText(OS2HwndFrame, windowNameA);
628 }
629 }
630
631//SvL: This completely messes up MS Word 97 (no button bar, no menu)
632#if 0
633 //adjust CW_USEDEFAULT position
634 if (fXDefault | fCXDefault)
635 {
636 RECT rect;
637
638 //SvL: Returns invalid rectangle (not the expected shell default size)
639 OSLibWinQueryWindowRect(OS2Hwnd,&rect,RELATIVE_TO_SCREEN);
640 if (getParent()) mapWin32Rect(OSLIB_HWND_DESKTOP,getParent()->getOS2WindowHandle(),&rect);
641 if (fXDefault)
642 {
643 cs->x = rect.left;
644 cs->y = rect.top;
645 if (!fCXDefault)
646 {
647 //CB: todo: adjust pos to screen rect
648 }
649 }
650 if (fCXDefault)
651 {
652 cs->cx = rect.right-rect.left;
653 cs->cy = rect.bottom-rect.top;
654 }
655 }
656#endif
657
658 //Set icon from window or class
659 if (hIcon)
660 OSLibWinSetIcon(OS2HwndFrame,hIcon);
661 else
662 if (windowClass->getIcon())
663 OSLibWinSetIcon(OS2HwndFrame,windowClass->getIcon());
664
665 /* Get class or window DC if needed */
666 if(windowClass->getStyle() & CS_OWNDC) {
667 dprintf(("Class with CS_OWNDC style"));
668 ownDC = GetDCEx(getWindowHandle(), NULL, DCX_USESTYLE);
669 }
670 else
671 if (windowClass->getStyle() & CS_PARENTDC) {
672 fParentDC = TRUE;
673 ownDC = 0;
674 }
675 else
676 if (windowClass->getStyle() & CS_CLASSDC) {
677 dprintf(("WARNING: Class with CS_CLASSDC style!"));
678 //not a good solution, but it's a bit difficult to share a single
679 //DC among different windows... DevOpenDC apparently can't be used
680 //for window DCs and WinOpenWindowDC must be associated with a window
681 ownDC = GetDCEx(getWindowHandle(), NULL, DCX_USESTYLE);
682 }
683 /* Set the window menu */
684 if ((dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
685 {
686 if (cs->hMenu) {
687 ::SetMenu(getWindowHandle(), cs->hMenu);
688 }
689 else {
690 if (windowClass->getMenuNameA()) {
691 cs->hMenu = LoadMenuA(windowClass->getInstance(),windowClass->getMenuNameA());
692#if 0 //CB: hack for treeview test cases bug
693if (!cs->hMenu) cs->hMenu = LoadMenuA(windowClass->getInstance(),"MYAPP");
694#endif
695 if (cs->hMenu) ::SetMenu(getWindowHandle(), cs->hMenu );
696 }
697 }
698 }
699 else
700 {
701 setWindowId((DWORD)cs->hMenu);
702 }
703 hSysMenu = (dwStyle & WS_SYSMENU) ? MENU_GetSysMenu(Win32Hwnd,0):0;
704
705 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
706 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
707 {
708 GetMinMaxInfo(&maxSize, &maxPos, &minTrack, &maxTrack);
709 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
710 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
711 if (cs->cx < minTrack.x) cs->cx = minTrack.x;
712 if (cs->cy < minTrack.y) cs->cy = minTrack.y;
713 if (cs->cx < 0) cs->cx = 0;
714 if (cs->cy < 0) cs->cy = 0;
715 }
716
717 //set client & window rectangles from CreateWindowEx CREATESTRUCT
718 rectWindow.left = cs->x;
719 rectWindow.right = cs->x+cs->cx;
720 rectWindow.top = cs->y;
721 rectWindow.bottom = cs->y+cs->cy;
722 rectClient = rectWindow;
723 OffsetRect(&rectClient, -rectClient.left, -rectClient.top);
724
725 /* Send the WM_CREATE message
726 * Perhaps we shouldn't allow width/height changes as well.
727 * See p327 in "Internals".
728 */
729 maxPos.x = rectWindow.left; maxPos.y = rectWindow.top;
730
731 if(fTaskList) {
732 hTaskList = OSLibWinAddToTaskList(OS2HwndFrame, windowNameA, (cs->style & WS_VISIBLE) ? 1 : 0);
733 }
734
735 localSend32 = (isUnicode) ? ::SendMessageW : ::SendMessageA;
736
737 state = STATE_PRE_WMNCCREATE;
738 if(localSend32(getWindowHandle(), WM_NCCREATE,0,(LPARAM)cs))
739 {
740 RECT tmpRect;
741
742 //CB: recheck flags
743 if (cs->style & (WS_POPUP | WS_CHILD))
744 {
745 fXDefault = FALSE;
746 if (fCXDefault)
747 {
748 fCXDefault = FALSE;
749 cs->cx = cs->cy = 0;
750 rectWindow.right = rectWindow.left;
751 rectWindow.bottom = rectWindow.top;
752 }
753 }
754 tmpRect = rectWindow;
755 state = STATE_POST_WMNCCREATE;
756
757 //set the window size and update the client
758 //@@PF Popup children of inactive windows can thus bring inactive window
759 //on top, this is not correct, popup windows can be on top only if their owner
760 //is in foreground, otherwise they are linked after owner.
761 if (((dwStyle & (WS_CHILD|WS_POPUP)) == WS_POPUP) && getOwner() && (getOwner()->getWindowHandle() != GetForegroundWindow()))
762 {
763 hwndLinkAfter = getOwner()->getWindowHandle();
764 }
765 SetWindowPos(hwndLinkAfter, tmpRect.left, tmpRect.top, tmpRect.right-tmpRect.left, tmpRect.bottom-tmpRect.top,SWP_NOACTIVATE | SWP_NOREDRAW | SWP_FRAMECHANGED);
766
767 state = STATE_PRE_WMCREATE;
768 if (cs->style & WS_VISIBLE) dwStyle |= WS_VISIBLE; //program could change position in WM_CREATE
769 if( (localSend32(getWindowHandle(), WM_CREATE, 0, (LPARAM)cs )) != -1 )
770 {
771 state = STATE_POST_WMCREATE;
772
773 if(!(flags & WIN_NEED_SIZE))
774 {
775 SendMessageA(getWindowHandle(), WM_SIZE, SIZE_RESTORED,
776 MAKELONG(rectClient.right-rectClient.left,
777 rectClient.bottom-rectClient.top));
778
779 if(!::IsWindow(hwnd))
780 {
781 dprintf(("Createwindow: WM_SIZE destroyed window"));
782 goto end;
783 }
784 SendMessageA(getWindowHandle(), WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
785 if(!::IsWindow(hwnd))
786 {
787 dprintf(("Createwindow: WM_MOVE destroyed window"));
788 goto end;
789 }
790 }
791
792 if (getStyle() & (WS_MINIMIZE | WS_MAXIMIZE))
793 {
794 RECT newPos;
795 UINT swFlag = (getStyle() & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
796 setStyle(getStyle() & ~(WS_MAXIMIZE | WS_MINIMIZE));
797 MinMaximize(swFlag, &newPos);
798 swFlag = ((getStyle() & WS_CHILD) || GetActiveWindow()) ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
799 : SWP_NOZORDER | SWP_FRAMECHANGED;
800 SetWindowPos(0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag);
801 if(!::IsWindow(hwnd))
802 {
803 dprintf(("Createwindow: min/max destroyed window"));
804 goto end;
805 }
806 }
807
808 if( (getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY) )
809 {
810 /* Notify the parent window only */
811 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
812 {
813 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_CREATE, getWindowId()), (LPARAM)getWindowHandle());
814 }
815 if(!::IsWindow(hwnd))
816 {
817 dprintf(("Createwindow: WM_PARENTNOTIFY destroyed window"));
818 goto end;
819 }
820 }
821
822 if(cs->style & WS_VISIBLE) {
823 dwStyle &= ~WS_VISIBLE;
824 ShowWindow(sw);
825 }
826
827 /* Call WH_SHELL hook */
828 if (!(getStyle() & WS_CHILD) && !owner)
829 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWCREATED, getWindowHandle(), 0);
830
831 //Call custom Odin hook for window creation (for all windows)
832 HOOK_CallOdinHookA(HODIN_WINDOWCREATED, hwnd, 0);
833
834 SetLastError(0);
835 return TRUE;
836 }
837 }
838 dprintf(("Window creation FAILED (NCCREATE cancelled creation)"));
839 SetLastError(ERROR_OUTOFMEMORY); //TODO: Better error
840end:
841 return FALSE;
842}
843//******************************************************************************
844//******************************************************************************
845ULONG Win32BaseWindow::MsgQuit()
846{
847 return SendMessageA(getWindowHandle(), WM_QUIT, 0, 0);
848}
849//******************************************************************************
850//******************************************************************************
851ULONG Win32BaseWindow::MsgClose()
852{
853 return SendMessageA(getWindowHandle(), WM_CLOSE,0,0);
854}
855//******************************************************************************
856//******************************************************************************
857ULONG Win32BaseWindow::MsgDestroy()
858{
859 ULONG rc;
860 Win32BaseWindow *child;
861 HWND hwnd = getWindowHandle();
862
863 state = STATE_DESTROYED;
864
865 if(fDestroyWindowCalled == FALSE)
866 {//this window was destroyed because DestroyWindow was called for its parent
867 //so: send a WM_PARENTNOTIFY now as that hasn't happened yet
868 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
869 {
870 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
871 {
872 /* Notify the parent window only */
873 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
874 }
875//// else DebugInt3();
876 }
877 }
878
879 // there may be no window proc already (reset to null with SetWindowLong by
880 // the application), avoid the debug assertion
881 if (win32wndproc)
882 SendMessageA(getWindowHandle(),WM_DESTROY, 0, 0);
883
884 if(::IsWindow(hwnd) == FALSE) {
885 //object already destroyed, so return immediately
886 return 1;
887 }
888
889 if (win32wndproc)
890 SendMessageA(getWindowHandle(),WM_NCDESTROY, 0, 0);
891
892 TIMER_KillTimerFromWindow(getWindowHandle());
893
894 if(getRefCount() == 0 && getFirstChild() == NULL && state == STATE_CREATED) {
895 delete this;
896 }
897 else {
898 //make sure no message can ever arrive for this window again (PM or from other win32 windows)
899 dprintf(("Mark window %x (%x) as deleted; refcount %d", getWindowHandle(), this, getRefCount()));
900 markDeleted();
901 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32WNDPTR, 0);
902 OSLibWinSetWindowULong(OS2Hwnd, OFFSET_WIN32PM_MAGIC, 0);
903 if(Win32Hwnd) {
904 HwFreeWindowHandle(Win32Hwnd);
905 Win32Hwnd = 0;
906 }
907 // Decrement class window counter
908 // NOTE: Must be done before ReleaseDC call for ownDC!
909 if(windowClass) {
910 RELEASE_CLASSOBJ(windowClass);
911 }
912
913 if(ownDC) {
914 ReleaseDC(Win32Hwnd, ownDC);
915 ownDC = 0;
916 }
917 }
918 return 1;
919}
920//******************************************************************************
921//******************************************************************************
922ULONG Win32BaseWindow::MsgEnable(BOOL fEnable)
923{
924 if(fEnable) {
925 dwStyle &= ~WS_DISABLED;
926 }
927 else dwStyle |= WS_DISABLED;
928
929 return SendMessageA(getWindowHandle(),WM_ENABLE, fEnable, 0);
930}
931//******************************************************************************
932//TODO: SW_PARENTCLOSING/OPENING flag (lParam)
933//******************************************************************************
934ULONG Win32BaseWindow::MsgShow(BOOL fShow)
935{
936 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled) {
937 return 1;
938 }
939
940 if(fShow) {
941 setStyle(getStyle() | WS_VISIBLE);
942 if(getStyle() & WS_MINIMIZE) {
943 return ShowWindow(SW_RESTORE);
944 }
945 }
946 else setStyle(getStyle() & ~WS_VISIBLE);
947
948 //already sent from ShowWindow
949//// return SendMessageA(getWindowHandle(),WM_SHOWWINDOW, fShow, 0);
950 return 0;
951}
952//******************************************************************************
953//******************************************************************************
954ULONG Win32BaseWindow::MsgPosChanging(LPARAM lp)
955{
956 //SvL: Notes crashes when switching views (calls DestroyWindow -> PM sends
957 // a WM_WINDOWPOSCHANGED msg -> crash)
958 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled)
959 return 0;
960
961 return SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, lp);
962}
963//******************************************************************************
964//******************************************************************************
965ULONG Win32BaseWindow::MsgPosChanged(LPARAM lp)
966{
967 //SvL: Notes crashes when switching views (calls DestroyWindow -> PM sends
968 // a WM_WINDOWPOSCHANGED msg -> crash)
969 if(!CanReceiveSizeMsgs() || fDestroyWindowCalled)
970 return 1;
971
972 return SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, lp);
973}
974//******************************************************************************
975//******************************************************************************
976ULONG Win32BaseWindow::MsgScroll(ULONG msg, ULONG scrollCode, ULONG scrollPos)
977{
978 //According to the SDK docs, the scrollbar handle (lParam) is 0 when the standard
979 //window scrollbars send these messages
980 return SendMessageA(getWindowHandle(),msg, MAKELONG(scrollCode, scrollPos), 0);
981}
982//******************************************************************************
983//******************************************************************************
984ULONG Win32BaseWindow::MsgActivate(BOOL fActivate, BOOL fMinimized, HWND hwnd, HWND hwndOS2Win)
985{
986 ULONG rc, procidhwnd = -1, threadidhwnd = 0;
987
988 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
989 if(fDestroyWindowCalled) {
990 return 0;
991 }
992
993 //According to SDK docs, if app returns FALSE & window is being deactivated,
994 //default processing is cancelled
995 //TODO: According to Wine we should proceed anyway if window is sysmodal
996 if(SendMessageA(getWindowHandle(),WM_NCACTIVATE, fActivate, 0) == FALSE && !fActivate)
997 {
998 dprintf(("WARNING: WM_NCACTIVATE return code = FALSE -> cancel processing"));
999 return 0;
1000 }
1001 /* child windows get a WM_CHILDACTIVATE message */
1002 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1003 {
1004 if(fActivate) {//WM_CHILDACTIVE is for activation only
1005 SendMessageA(getWindowHandle(),WM_CHILDACTIVATE, 0, 0L);
1006 }
1007 return 0;
1008 }
1009
1010 return SendMessageA(getWindowHandle(),WM_ACTIVATE, MAKELONG((fActivate) ? WA_ACTIVE : WA_INACTIVE, fMinimized), hwnd);
1011}
1012//******************************************************************************
1013//******************************************************************************
1014ULONG Win32BaseWindow::MsgChildActivate(BOOL fActivate)
1015{
1016 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1017 if(fDestroyWindowCalled) {
1018 return 0;
1019 }
1020
1021 //According to SDK docs, if app returns FALSE & window is being deactivated,
1022 //default processing is cancelled
1023 //TODO: According to Wine we should proceed anyway if window is sysmodal
1024 if(SendMessageA(getWindowHandle(),WM_NCACTIVATE, fActivate, 0) == FALSE && !fActivate)
1025 {
1026 dprintf(("WARNING: WM_NCACTIVATE return code = FALSE -> cancel processing"));
1027 return 0;
1028 }
1029 /* child windows get a WM_CHILDACTIVATE message */
1030 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1031 {
1032 if(fActivate) {//WM_CHILDACTIVE is for activation only
1033 SendMessageA(getWindowHandle(),WM_CHILDACTIVATE, 0, 0L);
1034 }
1035 return 0;
1036 }
1037 DebugInt3();
1038 return 0;
1039}
1040//******************************************************************************
1041//******************************************************************************
1042ULONG Win32BaseWindow::DispatchMsgA(MSG *msg)
1043{
1044 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1045}
1046//******************************************************************************
1047//******************************************************************************
1048ULONG Win32BaseWindow::DispatchMsgW(MSG *msg)
1049{
1050 return SendMessageW(getWindowHandle(), msg->message, msg->wParam, msg->lParam);
1051}
1052//******************************************************************************
1053//******************************************************************************
1054ULONG Win32BaseWindow::MsgSetFocus(HWND hwnd)
1055{
1056 //Notify that focus has changed (necessary for SetFocus(0) handling)
1057 SetFocusChanged();
1058
1059 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1060 if(fDestroyWindowCalled) {
1061 return 0;
1062 }
1063
1064 // if in <= 8bpp mode, then we must send a WM_QUERYNEWPALETTE message here
1065 // this gives the app the chance to realize its palette
1066 if(ScreenBitsPerPel <= 8) {
1067 SendMessageA(getWindowHandle(),WM_QUERYNEWPALETTE, 0, 0);
1068 }
1069 return SendMessageA(getWindowHandle(),WM_SETFOCUS, hwnd, 0);
1070}
1071//******************************************************************************
1072//******************************************************************************
1073ULONG Win32BaseWindow::MsgKillFocus(HWND hwnd)
1074{
1075 //Notify that focus has changed (necessary for SetFocus(0) handling)
1076 SetFocusChanged();
1077
1078 //SvL: Don't send WM_(NC)ACTIVATE messages when the window is being destroyed
1079 if(fDestroyWindowCalled) {
1080 return 0;
1081 }
1082 return SendMessageA(getWindowHandle(),WM_KILLFOCUS, hwnd, 0);
1083}
1084//******************************************************************************
1085//******************************************************************************
1086ULONG Win32BaseWindow::MsgButton(MSG *msg)
1087{
1088 BOOL eatMsg = FALSE;
1089 BOOL fClick = FALSE;
1090
1091 dprintf(("MsgButton %d at (%d,%d) %X %X", msg->message, msg->pt.x, msg->pt.y, msg->wParam, msg->lParam));
1092
1093 switch(msg->message)
1094 {
1095 case WM_LBUTTONDBLCLK:
1096 case WM_RBUTTONDBLCLK:
1097 case WM_MBUTTONDBLCLK:
1098 if (!(windowClass && windowClass->getClassLongA(GCL_STYLE) & CS_DBLCLKS))
1099 {
1100 msg->message = msg->message - (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); //dblclick -> down
1101 return MsgButton(msg);
1102 }
1103 break;
1104 case WM_NCLBUTTONDBLCLK:
1105 case WM_NCRBUTTONDBLCLK:
1106 case WM_NCMBUTTONDBLCLK:
1107 //Docs say CS_DBLCLKS style doesn't matter for non-client double clicks
1108 fClick = TRUE;
1109 break;
1110
1111 case WM_LBUTTONDOWN:
1112 case WM_RBUTTONDOWN:
1113 case WM_MBUTTONDOWN:
1114 if (getParent())
1115 {
1116 dprintf(("notifying parent: %X %X", msg->wParam, msg->lParam));
1117 NotifyParent(msg->message, msg->wParam, /*0*/msg->lParam);
1118 }
1119 // fall through to set fClick
1120 case WM_NCLBUTTONDOWN:
1121 case WM_NCRBUTTONDOWN:
1122 case WM_NCMBUTTONDOWN:
1123 fClick = TRUE;
1124 break;
1125 }
1126
1127 if(fClick)
1128 {
1129 HWND hwndTop;
1130
1131 /* Activate the window if needed */
1132 hwndTop = GetTopParent();
1133
1134 HWND hwndActive = GetActiveWindow();
1135 if (hwndTop && (getWindowHandle() != hwndActive))
1136 {
1137 LONG ret = SendMessageA(getWindowHandle(),WM_MOUSEACTIVATE, hwndTop,
1138 MAKELONG( lastHitTestVal, msg->message) );
1139
1140 //SendMessageA(getWindowHandle(), msg->message, msg->wParam, msg->lParam);
1141 dprintf2(("WM_MOUSEACTIVATE returned %d foreground %x top %x", ret, GetForegroundWindow(), hwndTop));
1142
1143 if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
1144 eatMsg = TRUE;
1145
1146 //SvL: 0 is not documented, but experiments in NT4 show that
1147 // the window will get activated when it returns this.
1148 // (FreeCell is an example)
1149 if(((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT) || (ret == 0))
1150 && (hwndTop != GetForegroundWindow()) )
1151 {
1152 Win32BaseWindow *win32top = Win32BaseWindow::GetWindowFromHandle(hwndTop);
1153
1154 //SvL: Calling OSLibSetActiveWindow(hwndTop); causes focus problems
1155 if (win32top) {
1156 //Must use client window handle (not frame!!)
1157 SetFocus(win32top->getWindowHandle());
1158 RELEASE_WNDOBJ(win32top);
1159 }
1160 }
1161 }
1162 }
1163
1164 SendMessageA(getWindowHandle(),WM_SETCURSOR, getWindowHandle(), MAKELONG(lastHitTestVal, msg->message));
1165
1166 return eatMsg ? 0 : SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1167}
1168//******************************************************************************
1169//******************************************************************************
1170ULONG Win32BaseWindow::MsgPaint(ULONG tmp, ULONG select)
1171{
1172 if (select && IsWindowIconic())
1173 return SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1174 else
1175 return SendMessageA(getWindowHandle(),WM_PAINT, 0, 0);
1176}
1177//******************************************************************************
1178//
1179// Win32BaseWindow::saveAndValidateUpdateRegion
1180//
1181// If an application doesn't validate the update region while processing
1182// WM_PAINT, then we must remember it for the next time. Also validates
1183// the current update region.
1184//
1185// Parameters:
1186// Returns:
1187//
1188// NOTE:
1189// Windows will only send a WM_PAINT once until another part of the
1190// window is invalidated. Unfortunately PM keeps on sending
1191// WM_PAINT messages until we validate the update region.
1192//
1193// This affects UpdateWindow, RedrawWindow, GetUpdateRgn, GetUpdateRect,
1194// BeginPaint and the next WM_PAINT message.
1195//
1196//******************************************************************************
1197void Win32BaseWindow::saveAndValidateUpdateRegion()
1198{
1199 if(hUpdateRegion == NULL) {
1200 hUpdateRegion = ::CreateRectRgn(0, 0, 1, 1);
1201 }
1202
1203 dprintf(("Win32BaseWindow::saveAndValidateUpdateRegion; marked dirty!"));
1204
1205 //save update region
1206 ::GetUpdateRgn(getWindowHandle(), hUpdateRegion, FALSE);
1207
1208 //and validate it so PM won't bother us again
1209 ::ValidateRgn(getWindowHandle(), hUpdateRegion);
1210
1211 //we just pretend the entire window is invalid. easier this way
1212 fDirtyUpdateRegion = TRUE;
1213}
1214//******************************************************************************
1215//
1216// Win32BaseWindow::checkForDirtyUpdateRegion
1217//
1218// If an application doesn't validate the update region while processing
1219// WM_PAINT, then we must remember it for the next time. If the window has
1220// a dirty update region, then invalidate that region.
1221//
1222// Parameters:
1223// Returns:
1224//
1225// NOTE:
1226//
1227//******************************************************************************
1228void Win32BaseWindow::checkForDirtyUpdateRegion()
1229{
1230 if(fDirtyUpdateRegion) {
1231 dprintf(("Win32BaseWindow::checkForDirtyUpdateRegion; marked dirty -> invalidate whole window!"));
1232 fDirtyUpdateRegion = FALSE;
1233 ::InvalidateRgn(getWindowHandle(), hUpdateRegion, TRUE);
1234 }
1235}
1236//******************************************************************************
1237//TODO: Is the clipper region of the window DC equal to the invalidated rectangle?
1238// (or are we simply erasing too much here)
1239//******************************************************************************
1240ULONG Win32BaseWindow::MsgEraseBackGround(HDC hdc)
1241{
1242 ULONG rc;
1243 HDC hdcErase = hdc;
1244
1245 if (hdcErase == 0) {
1246 DebugInt3();
1247 return 0;
1248 }
1249
1250 if(IsWindowIconic())
1251 rc = SendMessageA(getWindowHandle(),WM_ICONERASEBKGND, hdcErase, 0);
1252 else
1253 rc = SendMessageA(getWindowHandle(),WM_ERASEBKGND, hdcErase, 0);
1254
1255 return (rc);
1256}
1257//******************************************************************************
1258//******************************************************************************
1259ULONG Win32BaseWindow::MsgMouseMove(MSG *msg)
1260{
1261 //TODO: hiword should be 0 if window enters menu mode (SDK docs)
1262 //SDK: WM_SETCURSOR is not sent if the mouse is captured
1263 if(GetCapture() == 0) {
1264 SendMessageA(getWindowHandle(),WM_SETCURSOR, Win32Hwnd, MAKELONG(lastHitTestVal, msg->message));
1265 }
1266
1267 //translated message == WM_(NC)MOUSEMOVE
1268 return SendMessageA(getWindowHandle(),msg->message, msg->wParam, msg->lParam);
1269}
1270//******************************************************************************
1271//******************************************************************************
1272ULONG Win32BaseWindow::MsgChar(MSG *msg)
1273{
1274 if (IsWindowUnicode()) {
1275 // Unicode windows expect the character code in UTF-16 while we save it
1276 // in ascii format, so we need to convert before sending to the window
1277 if (msg->message == WINWM_CHAR) {
1278 CHAR charA;
1279 WCHAR charW;
1280
1281 charA = msg->wParam;
1282 MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
1283 msg->wParam= charW;
1284 dprintf(("MsgChar: Convert to Unicode src=%x res=%x", charA, charW));
1285 }
1286 return DispatchMsgW(msg);
1287 }
1288 return DispatchMsgA(msg);
1289}
1290//******************************************************************************
1291//******************************************************************************
1292ULONG Win32BaseWindow::MsgNCPaint(PRECT pUpdateRect, HRGN hrgnUpdate)
1293{
1294 ULONG rc;
1295 RECT client = rectClient;
1296
1297 if ((pUpdateRect->left >= client.left) && (pUpdateRect->left < client.right) &&
1298 (pUpdateRect->right >= client.left) && (pUpdateRect->right < client.right) &&
1299 (pUpdateRect->top >= client.top) && (pUpdateRect->top < client.bottom) &&
1300 (pUpdateRect->bottom >= client.top) && (pUpdateRect->bottom < client.bottom)
1301 && (!(getStyle() & WS_MINIMIZE)))
1302 {
1303 return 0;
1304 }
1305
1306 rc = SendMessageA(getWindowHandle(),WM_NCPAINT, hrgnUpdate, 0);
1307 //Send WM_PAINTICON here if minimized, because client window will
1308 //not receive a (valid) WM_PAINT message
1309 if (getStyle() & WS_MINIMIZE)
1310 {
1311 rc = SendMessageA(getWindowHandle(),WM_PAINTICON, 1, 0);
1312 }
1313
1314 return rc;
1315}
1316//******************************************************************************
1317//Called when either the frame's size or position has changed (lpWndPos != NULL)
1318//or when the frame layout has changed (i.e. scrollbars added/removed) (lpWndPos == NULL)
1319//******************************************************************************
1320ULONG Win32BaseWindow::MsgFormatFrame(WINDOWPOS *lpWndPos)
1321{
1322 RECT oldWindowRect = rectWindow, client = rectClient, newWindowRect;
1323 RECT newClientRect;
1324 WINDOWPOS wndPos;
1325 ULONG rc;
1326
1327 if(lpWndPos)
1328 {
1329 //set new window rectangle
1330 setWindowRect(lpWndPos->x, lpWndPos->y, lpWndPos->x+lpWndPos->cx,
1331 lpWndPos->y+lpWndPos->cy);
1332 newWindowRect = rectWindow;
1333 }
1334 else {
1335 wndPos.hwnd = getWindowHandle();
1336 wndPos.hwndInsertAfter = 0;
1337 newWindowRect= rectWindow;
1338 wndPos.x = newWindowRect.left;
1339 wndPos.y = newWindowRect.top;
1340 wndPos.cx = newWindowRect.right - newWindowRect.left;
1341 wndPos.cy = newWindowRect.bottom - newWindowRect.top;
1342 wndPos.flags = SWP_FRAMECHANGED;
1343 lpWndPos = &wndPos;
1344 }
1345
1346 newClientRect = rectClient;
1347 rc = SendNCCalcSize(TRUE, &newWindowRect, &oldWindowRect, &client, lpWndPos, &newClientRect);
1348 rectClient = newClientRect; //must update rectClient here
1349
1350 dprintf(("MsgFormatFrame: old client rect (%d,%d)(%d,%d), new client (%d,%d)(%d,%d)", client.left, client.top, client.right, client.bottom, rectClient.left, rectClient.top, rectClient.right, rectClient.bottom));
1351 dprintf(("MsgFormatFrame: old window rect (%d,%d)(%d,%d), new window (%d,%d)(%d,%d)", oldWindowRect.left, oldWindowRect.top, oldWindowRect.right, oldWindowRect.bottom, rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
1352
1353 if(!CanReceiveSizeMsgs() || !EqualRect(&client, &rectClient)) {
1354 OSLibWinSetClientPos(getOS2WindowHandle(), rectClient.left, rectClient.top, getClientWidth(), getClientHeight(), getWindowHeight());
1355 }
1356
1357#if 1
1358//this doesn't always work
1359// if(CanReceiveSizeMsgs() && (client.left != rectClient.left || client.top != rectClient.top))
1360 if(CanReceiveSizeMsgs() && ((oldWindowRect.right - oldWindowRect.left < rectClient.left
1361 || oldWindowRect.bottom - oldWindowRect.top < rectClient.top) ||
1362 (EqualRect(&oldWindowRect, &rectWindow) && (client.left != rectClient.left || client.top != rectClient.top))))
1363 {
1364 Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild();
1365
1366 //client rectangle has moved -> inform children
1367 dprintf(("MsgFormatFrame -> client rectangle has changed, move children"));
1368 while(child) {
1369 ::SetWindowPos(child->getWindowHandle(),
1370 HWND_TOP, child->getWindowRect()->left,
1371 child->getWindowRect()->top, 0, 0,
1372 SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
1373 child = (Win32BaseWindow *)child->getNextChild();
1374 }
1375 }
1376#endif
1377 //WS_EX_TOOLWINDOW is incompatible with the OS2Look (titlebar thinner + smaller font)
1378 if(fOS2Look && ((dwStyle & WS_CAPTION) == WS_CAPTION) && !(dwExStyle & WS_EX_TOOLWINDOW))
1379 {
1380 RECT rect = {0};
1381 BOOL fCloseButton;
1382
1383 fCloseButton = !(windowClass && (windowClass->getClassLongA(GCL_STYLE) & CS_NOCLOSE));
1384
1385 int height = getWindowHeight();
1386 RECTLOS2 rectOS2;
1387
1388 AdjustRectOuter(&rect, FALSE);
1389
1390 rect.left = -rect.left;
1391 rect.top = rect.bottom - rect.top;
1392 rect.right = rectWindow.right - rectWindow.left - rect.right;
1393
1394 rectOS2.xLeft = rect.left;
1395 rectOS2.xRight = rect.right;
1396 rectOS2.yBottom = height - rect.top;
1397 rectOS2.yTop = height - rect.bottom;
1398
1399 //@@PF Disable close button as well when needed by application
1400 OSLibChangeCloseButtonState(getOS2FrameWindowHandle(), fCloseButton);
1401 OSLibWinPositionFrameControls(getOS2FrameWindowHandle(), &rectOS2,
1402 dwStyle, dwExStyle, IconForWindow(ICON_SMALL),
1403 fCloseButton, windowClass->getIcon() != NULL);
1404 }
1405 return rc;
1406}
1407//******************************************************************************
1408//******************************************************************************
1409ULONG Win32BaseWindow::MsgSetText(LPSTR lpsz, LONG cch)
1410{
1411 return SendMessageA(getWindowHandle(),WM_SETTEXT, 0, (LPARAM)lpsz);
1412}
1413//******************************************************************************
1414//******************************************************************************
1415ULONG Win32BaseWindow::MsgGetTextLength()
1416{
1417 return SendMessageA(getWindowHandle(),WM_GETTEXTLENGTH, 0, 0);
1418}
1419//******************************************************************************
1420//******************************************************************************
1421void Win32BaseWindow::MsgGetText(char *wndtext, ULONG textlength)
1422{
1423 SendMessageA(getWindowHandle(),WM_GETTEXT, textlength, (LPARAM)wndtext);
1424}
1425//******************************************************************************
1426//******************************************************************************
1427BOOL Win32BaseWindow::isMDIClient()
1428{
1429 return FALSE;
1430}
1431//******************************************************************************
1432//******************************************************************************
1433BOOL Win32BaseWindow::isMDIChild()
1434{
1435 return FALSE;
1436}
1437//******************************************************************************
1438//TODO: Not complete
1439//******************************************************************************
1440BOOL Win32BaseWindow::isFrameWindow()
1441{
1442 if(getParent() == NULL)
1443 return TRUE;
1444
1445 return FALSE;
1446}
1447//******************************************************************************
1448//******************************************************************************
1449BOOL Win32BaseWindow::isDesktopWindow()
1450{
1451 return FALSE;
1452}
1453//******************************************************************************
1454//******************************************************************************
1455BOOL Win32BaseWindow::isFakeWindow()
1456{
1457 return FALSE;
1458}
1459//******************************************************************************
1460//******************************************************************************
1461BOOL Win32BaseWindow::IsWindowIconic()
1462{
1463 return ((getStyle() & WS_MINIMIZE) && windowClass->getIcon());
1464}
1465//******************************************************************************
1466//******************************************************************************
1467SCROLLBAR_INFO *Win32BaseWindow::getScrollInfo(int nBar)
1468{
1469 switch(nBar)
1470 {
1471 case SB_HORZ:
1472 if (!horzScrollInfo)
1473 {
1474 horzScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1475 if (!horzScrollInfo) break;
1476 horzScrollInfo->MinVal = horzScrollInfo->CurVal = horzScrollInfo->Page = 0;
1477 horzScrollInfo->MaxVal = 100;
1478 horzScrollInfo->flags = ESB_ENABLE_BOTH;
1479 }
1480 return horzScrollInfo;
1481
1482 case SB_VERT:
1483 if (!vertScrollInfo)
1484 {
1485 vertScrollInfo = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
1486 if (!vertScrollInfo) break;
1487 vertScrollInfo->MinVal = vertScrollInfo->CurVal = vertScrollInfo->Page = 0;
1488 vertScrollInfo->MaxVal = 100;
1489 vertScrollInfo->flags = ESB_ENABLE_BOTH;
1490 }
1491 return vertScrollInfo;
1492 }
1493
1494 return NULL;
1495}
1496//******************************************************************************
1497//******************************************************************************
1498LRESULT Win32BaseWindow::DefWndControlColor(UINT ctlType, HDC hdc)
1499{
1500 //SvL: Set background color to default button color (not window (white))
1501 if(ctlType == CTLCOLOR_BTN)
1502 {
1503 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1504 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1505 return GetSysColorBrush(COLOR_BTNFACE);
1506 }
1507 //SvL: Set background color to default dialog color if window is dialog
1508 if((ctlType == CTLCOLOR_DLG || ctlType == CTLCOLOR_STATIC) && IsDialog()) {
1509 SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
1510 SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
1511 return GetSysColorBrush(COLOR_BTNFACE);
1512 }
1513 if( ctlType == CTLCOLOR_SCROLLBAR)
1514 {
1515 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
1516 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
1517 SetTextColor( hdc, GetSysColor(COLOR_3DFACE));
1518 SetBkColor( hdc, bk);
1519
1520 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
1521 * we better use 0x55aa bitmap brush to make scrollbar's background
1522 * look different from the window background.
1523 */
1524 if (bk == GetSysColor(COLOR_WINDOW)) {
1525 return GetPattern55AABrush();
1526 }
1527
1528 UnrealizeObject( hb );
1529 return (LRESULT)hb;
1530 }
1531
1532 SetTextColor( hdc, GetSysColor(COLOR_WINDOWTEXT));
1533
1534 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
1535 {
1536 SetBkColor( hdc, GetSysColor(COLOR_WINDOW) );
1537 }
1538 else
1539 {
1540 SetBkColor( hdc, GetSysColor(COLOR_3DFACE) );
1541 return (LRESULT)GetSysColorBrush(COLOR_3DFACE);
1542 }
1543 return (LRESULT)GetSysColorBrush(COLOR_WINDOW);
1544}
1545//******************************************************************************
1546//******************************************************************************
1547LRESULT Win32BaseWindow::DefWndPrint(HDC hdc,ULONG uFlags)
1548{
1549 /*
1550 * Visibility flag.
1551 */
1552 if ( (uFlags & PRF_CHECKVISIBLE) &&
1553 !IsWindowVisible(getWindowHandle()) )
1554 return 0;
1555
1556 /*
1557 * Unimplemented flags.
1558 */
1559 if ( (uFlags & PRF_CHILDREN) ||
1560 (uFlags & PRF_OWNED) ||
1561 (uFlags & PRF_NONCLIENT) )
1562 {
1563 dprintf(("WM_PRINT message with unsupported flags\n"));
1564 }
1565
1566 /*
1567 * Background
1568 */
1569 if ( uFlags & PRF_ERASEBKGND)
1570 SendMessageA(getWindowHandle(),WM_ERASEBKGND, (WPARAM)hdc, 0);
1571
1572 /*
1573 * Client area
1574 */
1575 if ( uFlags & PRF_CLIENT)
1576 SendMessageA(getWindowHandle(),WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
1577
1578
1579 return 0;
1580}
1581//******************************************************************************
1582//******************************************************************************
1583LRESULT Win32BaseWindow::DefWindowProcA(UINT Msg, WPARAM wParam, LPARAM lParam)
1584{
1585
1586 dprintf(("DefWndProc: winmsg: %x for %x Msg %s", Msg, Win32Hwnd, GetMsgText(/*HIWORD(lParam)*/Msg)));
1587
1588 switch(Msg)
1589 {
1590 case WM_CLOSE:
1591 dprintf(("DefWindowProcA: WM_CLOSE %x", getWindowHandle()));
1592 DestroyWindow();
1593 return 0;
1594
1595 case WM_GETTEXTLENGTH:
1596 return windowNameLengthA;
1597
1598 case WM_GETTEXT:
1599 if (!lParam || !wParam)
1600 return 0;
1601 if (!windowNameA)
1602 ((LPSTR)lParam)[0] = 0;
1603 else
1604 lstrcpynA(( LPSTR )lParam, windowNameA, wParam );
1605 return strlen(( LPSTR )lParam );
1606
1607 case WM_SETTEXT:
1608 {
1609 LPCSTR lpsz = (LPCSTR)lParam;
1610
1611 // reallocate if new buffer is larger
1612 if (!lParam)
1613 {
1614 free(windowNameA);
1615 free(windowNameW);
1616 windowNameLengthA = 0;
1617 windowNameLengthW = 0;
1618 windowNameA = NULL;
1619 windowNameW = NULL;
1620 }
1621 else
1622 {
1623 if (windowNameA)
1624 {
1625 free(windowNameA);
1626 windowNameA = NULL;
1627 }
1628
1629 if (windowNameW)
1630 {
1631 free(windowNameW);
1632 windowNameW = NULL;
1633 }
1634
1635 windowNameLengthA = strlen( lpsz );
1636 windowNameA = (LPSTR)_smalloc(windowNameLengthA+1);
1637 strcpy(windowNameA, lpsz);
1638 windowNameLengthW = lstrlenAtoW( lpsz, -1 );
1639 windowNameW = (LPWSTR)_smalloc(( windowNameLengthW + 1 )*sizeof(WCHAR));
1640 lstrcpyAtoW( windowNameW, windowNameA );
1641 }
1642
1643 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, lParam));
1644 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1645 {
1646 HandleNCPaint((HRGN)1);
1647 if(hTaskList) {
1648 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
1649 }
1650 if(fOS2Look) {
1651 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
1652 }
1653 }
1654
1655 return TRUE;
1656 }
1657
1658 case WM_SETREDRAW:
1659 {
1660 if (wParam)
1661 {
1662 setStyle(getStyle() | WS_VISIBLE);
1663 dprintf(("Enable window update for %x", getWindowHandle()));
1664 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, TRUE);
1665 }
1666 else
1667 {
1668 if (getStyle() & WS_VISIBLE)
1669 {
1670 setStyle(getStyle() & ~WS_VISIBLE);
1671 dprintf(("Disable window update for %x", getWindowHandle()));
1672 OSLibWinEnableWindowUpdate(OS2HwndFrame, OS2Hwnd, FALSE);
1673 }
1674 }
1675 return 0;
1676 }
1677
1678 case WM_CTLCOLORMSGBOX:
1679 case WM_CTLCOLOREDIT:
1680 case WM_CTLCOLORLISTBOX:
1681 case WM_CTLCOLORBTN:
1682 case WM_CTLCOLORDLG:
1683 case WM_CTLCOLORSTATIC:
1684 case WM_CTLCOLORSCROLLBAR:
1685 return DefWndControlColor(Msg - WM_CTLCOLORMSGBOX, (HDC)wParam);
1686
1687 case WM_CTLCOLOR:
1688 return DefWndControlColor(HIWORD(lParam), (HDC)wParam);
1689
1690 case WM_VKEYTOITEM:
1691 case WM_CHARTOITEM:
1692 return -1;
1693
1694 case WM_PARENTNOTIFY:
1695 return 0;
1696
1697 case WM_MOUSEACTIVATE:
1698 {
1699 HWND hwnd = getWindowHandle();
1700
1701 dprintf(("DefWndProc: WM_MOUSEACTIVATE for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1702 if (::GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)
1703 {
1704 LONG ret = ::SendMessageW( ::GetParent(hwnd), WM_MOUSEACTIVATE, wParam, lParam );
1705 if (ret) return ret;
1706 }
1707
1708 /* Caption clicks are handled by the NC_HandleNCLButtonDown() */
1709 return (LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE;
1710 }
1711
1712 case WM_ACTIVATE:
1713 /* The default action in Windows is to set the keyboard focus to
1714 * the window, if it's being activated and not minimized */
1715 if (LOWORD(wParam) != WA_INACTIVE) {
1716 if(!(getStyle() & WS_MINIMIZE))
1717 SetFocus(getWindowHandle());
1718 }
1719 return 0;
1720
1721 case WM_SETCURSOR:
1722 {
1723 dprintf(("DefWndProc: WM_SETCURSOR for %x Msg %s", Win32Hwnd, GetMsgText(HIWORD(lParam))));
1724 if((getStyle() & WS_CHILD))
1725 {
1726 if(getParent()) {
1727 LRESULT rc = SendMessageA(getParent()->getWindowHandle(), WM_SETCURSOR, wParam, lParam);
1728 if(rc) return rc;
1729 }
1730 }
1731 if (wParam == getWindowHandle())
1732 {
1733 HCURSOR hCursor;
1734
1735 switch(LOWORD(lParam))
1736 {
1737 case HTCLIENT:
1738 hCursor = windowClass ? windowClass->getCursor():LoadCursorA(0,IDC_ARROWA);
1739 break;
1740
1741 case HTLEFT:
1742 case HTRIGHT:
1743 hCursor = LoadCursorA(0,IDC_SIZEWEA);
1744 break;
1745
1746 case HTTOP:
1747 case HTBOTTOM:
1748 hCursor = LoadCursorA(0,IDC_SIZENSA);
1749 break;
1750
1751 case HTTOPLEFT:
1752 case HTBOTTOMRIGHT:
1753 hCursor = LoadCursorA(0,IDC_SIZENWSEA);
1754 break;
1755
1756 case HTTOPRIGHT:
1757 case HTBOTTOMLEFT:
1758 hCursor = LoadCursorA(0,IDC_SIZENESWA);
1759 break;
1760
1761 default:
1762 hCursor = LoadCursorA(0,IDC_ARROWA);
1763 break;
1764 }
1765
1766 if (hCursor)
1767 {
1768 SetCursor(hCursor);
1769 return 1;
1770 }
1771 else return 0;
1772 }
1773 else return 0;
1774 }
1775
1776 case WM_MOUSEMOVE:
1777 return 0;
1778
1779 case WM_MOUSEWHEEL:
1780 if (::GetWindowLongA( getWindowHandle(), GWL_STYLE ) & WS_CHILD)
1781 return ::SendMessageA( ::GetParent(getWindowHandle()), WM_MOUSEWHEEL, wParam, lParam );
1782 break;
1783
1784 case WM_WINDOWPOSCHANGED:
1785 {
1786 PWINDOWPOS wpos = (PWINDOWPOS)lParam;
1787 WPARAM wp = SIZE_RESTORED;
1788
1789 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1790 //show otherwise
1791 if (!(wpos->flags & SWP_NOMOVE) && !(wpos->flags & SWP_NOCLIENTMOVE))
1792 {
1793 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left,rectClient.top));
1794 }
1795 //According to Wine these are always sent, but experiments in Windows NT4, SP6
1796 //show otherwise
1797 if (!(wpos->flags & SWP_NOSIZE) && !(wpos->flags & SWP_NOCLIENTSIZE))
1798 {
1799 if (dwStyle & WS_MAXIMIZE) wp = SIZE_MAXIMIZED;
1800 else
1801 if (dwStyle & WS_MINIMIZE) wp = SIZE_MINIMIZED;
1802
1803 SendMessageA(getWindowHandle(),WM_SIZE, wp, MAKELONG(rectClient.right - rectClient.left,
1804 rectClient.bottom - rectClient.top));
1805 }
1806 return 0;
1807 }
1808 case WM_WINDOWPOSCHANGING:
1809 return HandleWindowPosChanging((WINDOWPOS *)lParam);
1810
1811 case WM_ERASEBKGND:
1812 case WM_ICONERASEBKGND:
1813 {
1814 HBRUSH hBrush;
1815 RECT rect;
1816 int rc;
1817
1818 if (!windowClass || (!windowClass->getBackgroundBrush()
1819 && !(getStyle() & WS_MINIMIZE))) return 0;
1820
1821 //PF For PM desktop/MDI icons allocate brush as well to avoid
1822 //garbage in icons
1823
1824 if (!windowClass->getBackgroundBrush())
1825 hBrush = GetStockObject(GRAY_BRUSH);
1826 else
1827 {
1828 hBrush = windowClass->getBackgroundBrush();
1829 if (hBrush <= (HBRUSH)(SYSCOLOR_GetLastColor()+1))
1830 hBrush = GetSysColorBrush(hBrush-1);
1831 }
1832
1833
1834 rc = GetClipBox( (HDC)wParam, &rect );
1835 if ((rc == SIMPLEREGION) || (rc == COMPLEXREGION))
1836 FillRect( (HDC)wParam, &rect, hBrush);
1837
1838 return 1;
1839 }
1840
1841 case WM_PRINT:
1842 return DefWndPrint(wParam,lParam);
1843
1844 case WM_SYNCPAINT:
1845 RedrawWindow(getWindowHandle(), NULL, 0, RDW_ERASENOW | RDW_ERASE | RDW_ALLCHILDREN);
1846 return 0;
1847
1848 case WM_PAINTICON:
1849 case WM_PAINT:
1850 {
1851 PAINTSTRUCT ps;
1852 HDC hdc = BeginPaint(getWindowHandle(), &ps );
1853 if( hdc )
1854 {
1855 if( (getStyle() & WS_MINIMIZE) && (getWindowClass()->getIcon() || hIcon))
1856 {
1857 int x = (rectWindow.right - rectWindow.left - GetSystemMetrics(SM_CXICON))/2;
1858 int y = (rectWindow.bottom - rectWindow.top - GetSystemMetrics(SM_CYICON))/2;
1859 dprintf(("Painting class icon: vis rect=(%i,%i - %i,%i)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom ));
1860 DrawIcon(hdc, x, y, hIcon ? hIcon:getWindowClass()->getIcon() );
1861 }
1862 EndPaint(getWindowHandle(), &ps );
1863 }
1864 return 0;
1865 }
1866
1867 case WM_GETDLGCODE:
1868 return 0;
1869
1870 case WM_NCPAINT:
1871 return HandleNCPaint((HRGN)wParam);
1872
1873 case WM_NCACTIVATE:
1874 return HandleNCActivate(wParam);
1875
1876 case WM_NCCREATE:
1877 return(TRUE);
1878
1879 case WM_NCDESTROY:
1880 return 0;
1881
1882 case WM_NCCALCSIZE:
1883 return HandleNCCalcSize((BOOL)wParam,(RECT*)lParam);
1884
1885 case WM_NCLBUTTONDOWN:
1886 return HandleNCLButtonDown(wParam,lParam);
1887
1888 case WM_LBUTTONDBLCLK:
1889 case WM_NCLBUTTONDBLCLK:
1890 return HandleNCLButtonDblClk(wParam,lParam);
1891
1892 case WM_NCRBUTTONDOWN:
1893 case WM_NCRBUTTONDBLCLK:
1894 case WM_NCMBUTTONDOWN:
1895 case WM_NCMBUTTONDBLCLK:
1896 if (lastHitTestVal == HTERROR) MessageBeep(MB_ICONEXCLAMATION);
1897 return 0;
1898
1899 case WM_NCRBUTTONUP:
1900 return HandleNCRButtonUp(wParam,lParam);
1901
1902 case WM_NCMBUTTONUP:
1903 return 0;
1904
1905 case WM_NCHITTEST:
1906 {
1907 POINT point;
1908 LRESULT retvalue;
1909
1910 point.x = (SHORT)LOWORD(lParam);
1911 point.y = (SHORT)HIWORD(lParam);
1912
1913 retvalue = HandleNCHitTest(point);
1914#if 0 //CB: let the Corel people fix the bugs first
1915 if(retvalue == HTMENU)
1916 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,TRUE);
1917 else
1918 MENU_TrackMouseMenuBar_MouseMove(Win32Hwnd,point,FALSE);
1919#endif
1920 dprintf(("Hittest: %X", retvalue));
1921 return retvalue;
1922 }
1923
1924 case WM_SYSCOMMAND:
1925 {
1926 POINT point;
1927
1928 point.x = LOWORD(lParam);
1929 point.y = HIWORD(lParam);
1930 return HandleSysCommand(wParam,&point);
1931 }
1932
1933 case WM_KEYDOWN:
1934 if(wParam == VK_F10) iF10Key = VK_F10;
1935 break;
1936
1937 case WM_SYSKEYDOWN:
1938 {
1939 if( HIWORD(lParam) & KEYDATA_ALT )
1940 {
1941 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1942 if( wParam == VK_MENU && !iMenuSysKey )
1943 iMenuSysKey = 1;
1944 else
1945 iMenuSysKey = 0;
1946
1947 iF10Key = 0;
1948
1949 if( wParam == VK_F4 ) /* try to close the window */
1950 {
1951 HWND top = GetTopParent();
1952 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
1953 PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
1954 }
1955
1956 //Default OS/2 app behaviour for system keys
1957 if(fOS2Look)
1958 {
1959 if( wParam == VK_F5 ) /* try to restore the window */
1960 {
1961 HWND top = GetTopParent();
1962 /* No checks needed SC_RESTORE handler does them */
1963 PostMessageW( top, WM_SYSCOMMAND, SC_RESTORE, 0 );
1964 }
1965
1966 if( wParam == VK_F7 ) /* size the window */
1967 {
1968 HWND top = GetTopParent();
1969 PostMessageW( top, WM_SYSCOMMAND, SC_MOVE, 0 );
1970 }
1971
1972 if( wParam == VK_F8 ) /* move the window */
1973 {
1974 HWND top = GetTopParent();
1975 if ( GetWindowLongA(top, GWL_STYLE) & WS_SIZEBOX)
1976 PostMessageW( top, WM_SYSCOMMAND, SC_SIZE, 0 );
1977 }
1978
1979 if( wParam == VK_F9 ) /* try to minimize the window */
1980 {
1981 HWND top = GetTopParent();
1982 if ( GetWindowLongA(top, GWL_STYLE) & WS_MINIMIZEBOX)
1983 PostMessageW( top, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
1984 }
1985
1986 if( wParam == VK_F10 ) /* try to maximize the window */
1987 {
1988 HWND top = GetTopParent();
1989 if ( GetWindowLongA(top, GWL_STYLE) & WS_MAXIMIZEBOX)
1990 PostMessageW( top, WM_SYSCOMMAND, SC_MAXIMIZE, 0 );
1991 }
1992 }
1993
1994 }
1995 else if( wParam == VK_F10 )
1996 iF10Key = 1;
1997 else
1998 if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1999 SendMessageW(getWindowHandle(), WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE );
2000 return 0;
2001 }
2002
2003 case WM_KEYUP:
2004 //Single Alt down + up always generates WM_SYSKEYUP
2005 iMenuSysKey = 0;
2006 // no break;
2007 case WM_SYSKEYUP:
2008 /* Press and release F10 or ALT */
2009 if (((wParam == VK_MENU) && iMenuSysKey) ||
2010 ((wParam == VK_F10) && iF10Key))
2011 ::SendMessageW( GetTopParent(), WM_SYSCOMMAND, SC_KEYMENU, 0L );
2012 iMenuSysKey = iF10Key = 0;
2013 break;
2014
2015 case WM_SYSCHAR:
2016 {
2017 iMenuSysKey = 0;
2018 if (wParam == VK_RETURN && (getStyle() & WS_MINIMIZE))
2019 {
2020 PostMessageA(getWindowHandle(), WM_SYSCOMMAND,
2021 (WPARAM)SC_RESTORE, 0L );
2022 break;
2023 }
2024 if((HIWORD(lParam) & KEYDATA_ALT) && wParam)
2025 {
2026 if (wParam == VK_TAB || wParam == VK_ESCAPE || wParam == VK_F4)
2027 break;
2028 if (wParam == VK_SPACE && (getStyle() & WS_CHILD)) {
2029 ::SendMessageW(GetParent(), Msg, wParam, lParam );
2030 }
2031 else ::SendMessageA(getWindowHandle(), WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
2032 }
2033#if 0
2034 else /* check for Ctrl-Esc */
2035 if (wParam != VK_ESCAPE) MessageBeep(0);
2036 break;
2037#endif
2038 }
2039
2040 case WM_SETHOTKEY:
2041 hotkey = wParam;
2042 return 1; //CB: always successful
2043
2044 case WM_GETHOTKEY:
2045 return hotkey;
2046
2047 case WM_RBUTTONUP:
2048 {
2049 POINT pt;
2050 pt.x = SLOWORD(lParam);
2051 pt.y = SHIWORD(lParam);
2052 ClientToScreen(getWindowHandle(), &pt);
2053 SendMessageA( getWindowHandle(), WM_CONTEXTMENU, getWindowHandle(),MAKELPARAM(pt.x, pt.y) );
2054 }
2055 break;
2056
2057 case WM_CONTEXTMENU:
2058 if ((dwStyle & WS_CHILD) && getParent())
2059 SendMessageA(getParent()->getWindowHandle(), WM_CONTEXTMENU,wParam,lParam);
2060 else
2061 {
2062 LONG hitcode;
2063 POINT pt;
2064 if (!GetSysMenu()) return 0;
2065 pt.x = SLOWORD(lParam);
2066 pt.y = SHIWORD(lParam);
2067 hitcode = HandleNCHitTest(pt);
2068
2069 /* Track system popup if click was in the caption area. */
2070 if (hitcode==HTCAPTION || hitcode==HTSYSMENU)
2071 TrackPopupMenu(GetSysMenu(),
2072 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
2073 pt.x, pt.y, 0, getWindowHandle(), NULL);
2074 }
2075 return 0;
2076
2077 case WM_SHOWWINDOW:
2078 if (!lParam) return 0; /* sent from ShowWindow */
2079 if (!(dwStyle & WS_POPUP) || !owner) return 0;
2080 if ((dwStyle & WS_VISIBLE) && wParam) return 0;
2081 else if (!(dwStyle & WS_VISIBLE) && !wParam) return 0;
2082 ShowWindow(wParam ? SW_SHOW:SW_HIDE);
2083 return 0;
2084
2085 case WM_CANCELMODE:
2086 if (getParent() == windowDesktop) EndMenu();
2087 if (GetCapture() == Win32Hwnd) ReleaseCapture();
2088 return 0;
2089
2090 case WM_DROPOBJECT:
2091 return DRAG_FILE;
2092
2093 case WM_QUERYDROPOBJECT:
2094 return (dwExStyle & WS_EX_ACCEPTFILES) ? 1:0;
2095
2096 case WM_QUERYDRAGICON:
2097 {
2098 HICON hDragIcon = windowClass->getCursor();
2099 UINT len;
2100
2101 if(hDragIcon) return (LRESULT)hDragIcon;
2102 for(len = 1; len < 64; len++)
2103 {
2104 hDragIcon = LoadIconA(hInstance,MAKEINTRESOURCEA(len));
2105 if(hDragIcon)
2106 return (LRESULT)hDragIcon;
2107 }
2108 return (LRESULT)LoadIconA(0,IDI_APPLICATIONA);
2109 }
2110
2111 case WM_QUERYOPEN:
2112 case WM_QUERYENDSESSION:
2113 return 1;
2114
2115 case WM_NOTIFYFORMAT:
2116 return IsWindowUnicode() ? NFR_UNICODE:NFR_ANSI;
2117
2118 case WM_SETICON:
2119 case WM_GETICON:
2120 {
2121 LRESULT result = 0;
2122
2123 /* Set the appropriate icon members in the window structure. */
2124 if (wParam == ICON_SMALL)
2125 {
2126 result = hIconSm;
2127 if (Msg == WM_SETICON)
2128 hIconSm = (HICON)lParam;
2129 }
2130 else
2131 {
2132 result = hIcon;
2133 if (Msg == WM_SETICON)
2134 {
2135 hIcon = (HICON)lParam;
2136 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2137 OSLibWinSetIcon(OS2HwndFrame,hIcon);
2138 }
2139 }
2140 if ((Msg == WM_SETICON) && ((dwStyle & WS_CAPTION) == WS_CAPTION))
2141 HandleNCPaint((HRGN)1);
2142
2143 return result;
2144 }
2145
2146 case WM_HELP:
2147 if (getParent()) SendMessageA(getParent()->getWindowHandle(), Msg,wParam,lParam);
2148 break;
2149
2150 case WM_NOTIFY:
2151 return 0; //comctl32 controls expect this
2152
2153 case WM_IME_CHAR:
2154 if( wParam & 0xFF00 ) // DBCS ?
2155 SendMessageA( getWindowHandle(), WM_CHAR, ( WPARAM )( BYTE )( wParam >> 8 ), lParam );
2156 SendMessageA( getWindowHandle(), WM_CHAR, ( WPARAM )( BYTE )( wParam & 0xFF ), lParam );
2157 break;
2158
2159 default:
2160 return 0;
2161 }
2162 return 0;
2163}
2164//******************************************************************************
2165//******************************************************************************
2166LRESULT Win32BaseWindow::DefWindowProcW(UINT Msg, WPARAM wParam, LPARAM lParam)
2167{
2168 switch(Msg)
2169 {
2170 case WM_GETTEXTLENGTH:
2171 return windowNameLengthW;
2172
2173 case WM_GETTEXT:
2174 if (!lParam || !wParam)
2175 return 0;
2176 if (!windowNameW)
2177 ((LPWSTR)lParam)[0] = 0;
2178 else
2179 lstrcpynW(( LPWSTR )lParam, windowNameW, wParam );
2180
2181 return strlenW(( LPWSTR )lParam );
2182
2183 case WM_SETTEXT:
2184 {
2185 LPWSTR lpsz = (LPWSTR)lParam;
2186
2187 // reallocate if new buffer is larger
2188 if (!lParam)
2189 {
2190 free(windowNameA);
2191 free(windowNameW);
2192 windowNameLengthA = 0;
2193 windowNameLengthW = 0;
2194 windowNameA = NULL;
2195 windowNameW = NULL;
2196 }
2197 else
2198 {
2199 if (windowNameA)
2200 {
2201 free(windowNameA);
2202 windowNameA = NULL;
2203 }
2204
2205 if (windowNameW)
2206 {
2207 free(windowNameW);
2208 windowNameW = NULL;
2209 }
2210
2211 windowNameLengthW = lstrlenW( lpsz );
2212 windowNameW = (LPWSTR)_smalloc((windowNameLengthW+1)*sizeof(WCHAR));
2213 strcpyW(windowNameW, lpsz);
2214 windowNameLengthA = lstrlenWtoA( lpsz, -1 );
2215 windowNameA = (LPSTR)_smalloc( windowNameLengthA + 1 );
2216 lstrcpyWtoA( windowNameA, windowNameW );
2217 }
2218
2219 dprintf(("WM_SETTEXT of %x to %s\n", Win32Hwnd, windowNameA));
2220 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
2221 {
2222 HandleNCPaint((HRGN)1);
2223 if(hTaskList) {
2224 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), (getStyle() & WS_VISIBLE) ? 1 : 0);
2225 }
2226 if(fOS2Look) {
2227 OSLibWinSetTitleBarText(OS2HwndFrame, getWindowNameA());
2228 }
2229 }
2230
2231 return TRUE;
2232 }
2233
2234 case WM_IME_CHAR:
2235 SendMessageW( getWindowHandle(), WM_CHAR, wParam, lParam );
2236 return 0;
2237
2238 default:
2239 return DefWindowProcA(Msg, wParam, lParam);
2240 }
2241}
2242//******************************************************************************
2243//******************************************************************************
2244void Win32BaseWindow::NotifyParent(UINT Msg, WPARAM wParam, LPARAM lParam)
2245{
2246 Win32BaseWindow *window = this;
2247 Win32BaseWindow *parentwindow;
2248
2249 while(window)
2250 {
2251 if(window->getStyle() & WS_CHILD && !(window->getExStyle() & WS_EX_NOPARENTNOTIFY) )
2252 {
2253 /* Notify the parent window only */
2254 parentwindow = window->getParent();
2255 if(parentwindow) {
2256 /* PF We should map points for each window accordingly! */
2257 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN || Msg == WM_RBUTTONDOWN ||
2258 Msg == WM_LBUTTONUP || Msg == WM_MBUTTONUP || Msg == WM_RBUTTONUP)
2259 {
2260 POINTS pt = MAKEPOINTS(lParam);
2261 POINT point;
2262
2263 point.x = pt.x;
2264 point.y = pt.y;
2265
2266 MapWindowPoints(getWindowHandle(),parentwindow->getWindowHandle(), &point, 1);
2267 lParam = MAKELPARAM(point.x, point.y);
2268 wParam = MAKEWPARAM(Msg, 0 /* undefined according to MSDN, 0 under XP */);
2269 }
2270 else
2271 {
2272 lParam = getWindowHandle();
2273 wParam = MAKEWPARAM(Msg, getWindowId());
2274 }
2275 SendMessageA(parentwindow->getWindowHandle(), WM_PARENTNOTIFY, wParam, lParam);
2276 }
2277
2278 }
2279 else break;
2280
2281 window = parentwindow;
2282 }
2283}
2284//******************************************************************************
2285// Returns the big or small icon for the window, falling back to the
2286// class as windows does.
2287//******************************************************************************
2288HICON Win32BaseWindow::IconForWindow(WPARAM fType)
2289{
2290 HICON hWndIcon;
2291
2292 if (fType == ICON_BIG)
2293 {
2294 if (hIcon)
2295 hWndIcon = hIcon;
2296 else
2297 if (windowClass && windowClass->getIcon())
2298 hWndIcon = windowClass->getIcon();
2299 else
2300 if (!(dwStyle & DS_MODALFRAME))
2301 {//SvL: load it as shared or else we'll leak icons
2302 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2303 }
2304 else hWndIcon = 0;
2305 }
2306 else
2307 {
2308 if (hIconSm)
2309 hWndIcon = hIconSm;
2310 else
2311 if (hIcon)
2312 hWndIcon = hIcon;
2313 else
2314 if (windowClass && windowClass->getIconSm())
2315 hWndIcon = windowClass->getIconSm();
2316 else
2317 if (windowClass && windowClass->getIcon())
2318 hWndIcon = windowClass->getIcon();
2319 else
2320 if (!(dwStyle & DS_MODALFRAME))
2321 {//SvL: load it as shared or else we'll leak icons
2322 hWndIcon = LoadImageA(0,MAKEINTRESOURCEA(OIC_ODINICON),IMAGE_ICON,0,0,LR_DEFAULTCOLOR|LR_SHARED);
2323 }
2324 else hWndIcon = 0;
2325 }
2326
2327 return hWndIcon;
2328}
2329//******************************************************************************
2330//******************************************************************************
2331BOOL Win32BaseWindow::ShowWindow(ULONG nCmdShow)
2332{
2333 ULONG swp = 0;
2334 HWND hWinAfter;
2335 BOOL rc,wasVisible,showFlag;
2336 RECT newPos = {0, 0, 0, 0};
2337
2338 dprintf(("ShowWindow %x %x", getWindowHandle(), nCmdShow));
2339 wasVisible = (getStyle() & WS_VISIBLE) != 0;
2340
2341 dwOldStyle = getStyle();
2342
2343 /*
2344 * SW_SHOWDEFAULT is an reference to the startup info wShowWindow member.
2345 */
2346 if (nCmdShow == SW_SHOWDEFAULT)
2347 {
2348 nCmdShow = GetProcessDword(0, GPD_STARTF_SHOWWINDOW);
2349 dprintf(("ShowWindow: GetProcessDword(0, GPD_STARTF_SHOWWINDOW) -> %x", nCmdShow));
2350 }
2351
2352
2353 switch(nCmdShow)
2354 {
2355 case SW_HIDE:
2356 if (!wasVisible) goto END;
2357
2358 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER;
2359 break;
2360
2361 case SW_SHOWMINNOACTIVE:
2362 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2363 /* fall through */
2364 case SW_SHOWMINIMIZED:
2365 swp |= SWP_SHOWWINDOW;
2366 /* fall through */
2367 case SW_MINIMIZE:
2368 swp |= SWP_FRAMECHANGED;
2369 if( !(getStyle() & WS_MINIMIZE) ) {
2370 swp |= MinMaximize(SW_MINIMIZE, &newPos );
2371 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2372 }
2373 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2374 break;
2375
2376 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
2377 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2378 if( !(getStyle() & WS_MAXIMIZE) ) {
2379 swp |= MinMaximize(SW_MAXIMIZE, &newPos );
2380 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2381 }
2382 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2383 break;
2384
2385 case SW_SHOWNA:
2386 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2387 /* fall through */
2388 case SW_SHOW:
2389 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2390
2391 /*
2392 * ShowWindow has a little peculiar behavior that if the
2393 * window is already the topmost window, it will not
2394 * activate it.
2395 */
2396 if (::GetTopWindow((HWND)0)==getWindowHandle() && (wasVisible || GetActiveWindow() == getWindowHandle()))
2397 swp |= SWP_NOACTIVATE;
2398
2399 break;
2400
2401 case SW_SHOWNOACTIVATE:
2402 swp |= SWP_NOZORDER | SWP_NOACTIVATE;
2403 /* fall through */
2404 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
2405 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2406 case SW_RESTORE:
2407 dprintf(("ShowWindow:restoring window"));
2408
2409 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
2410 if( getStyle() & (WS_MINIMIZE | WS_MAXIMIZE) ) {
2411 swp |= MinMaximize(SW_RESTORE, &newPos );
2412 fMinMaxChange = TRUE; //-> invalidate entire window in WM_CALCINVALIDRECT
2413 }
2414 else swp |= SWP_NOSIZE | SWP_NOMOVE;
2415 break;
2416 }
2417
2418 showFlag = (nCmdShow != SW_HIDE);
2419 if (showFlag != wasVisible)
2420 {
2421 SendMessageA(getWindowHandle(),WM_SHOWWINDOW, showFlag, 0 );
2422 if (!::IsWindow( getWindowHandle() )) goto END;
2423 }
2424
2425 /* We can't activate a child window */
2426 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_MDICHILD))
2427 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2428
2429 if (!(getStyle() & WS_MINIMIZE)) {
2430 SetWindowPos(HWND_TOP, newPos.left, newPos.top, newPos.right, newPos.bottom, LOWORD(swp), TRUE);
2431 }
2432 else OSLibWinMinimizeWindow(getOS2FrameWindowHandle());
2433
2434 if(!(swp & SWP_NOACTIVATE) && (!(getStyle() & WS_MINIMIZE))) {
2435 OSLibWinSetActiveWindow(OS2HwndFrame);
2436 }
2437
2438 if (flags & WIN_NEED_SIZE)
2439 {
2440 /* should happen only in CreateWindowEx() */
2441 int wParam = SIZE_RESTORED;
2442
2443 flags &= ~WIN_NEED_SIZE;
2444 if (dwStyle & WS_MAXIMIZE)
2445 wParam = SIZE_MAXIMIZED;
2446 else
2447 if (dwStyle & WS_MINIMIZE)
2448 wParam = SIZE_MINIMIZED;
2449
2450 SendMessageA(getWindowHandle(),WM_SIZE, wParam,
2451 MAKELONG(rectClient.right-rectClient.left,
2452 rectClient.bottom-rectClient.top));
2453 SendMessageA(getWindowHandle(),WM_MOVE,0,MAKELONG(rectClient.left,rectClient.top));
2454 }
2455//testestest
2456 //temporary workaround for file dialogs with template dialog child
2457 //they don't redraw when switching directories
2458 //For some reason the new child's (syslistview32) update rectangle stays
2459 //empty after its parent is made visible with ShowWindow
2460 //TODO: find real cause
2461 if(!wasVisible) {
2462 InvalidateRect(getWindowHandle(), NULL, TRUE);
2463 }
2464//testestest
2465
2466END:
2467 fMinMaxChange = FALSE;
2468 return wasVisible;
2469}
2470//******************************************************************************
2471//******************************************************************************
2472BOOL Win32BaseWindow::SetWindowPos(HWND hwndInsertAfter, int x, int y, int cx,
2473 int cy, UINT fuFlags, BOOL fShowWindow)
2474{
2475 BOOL rc = FALSE;
2476 Win32BaseWindow *window;
2477 HWND hParent = 0;
2478 RECT oldClientRect = rectClient;
2479
2480 if (fuFlags &
2481 ~(SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
2482 SWP_NOREDRAW | SWP_NOACTIVATE | SWP_FRAMECHANGED |
2483 SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOCOPYBITS |
2484 SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_DEFERERASE |
2485 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS))
2486 {
2487 dprintf(("ERROR: SetWindowPos; UNKNOWN flag"));
2488 return FALSE;
2489 }
2490
2491 if( fuFlags & (SWP_DEFERERASE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_ASYNCWINDOWPOS)) {
2492 dprintf(("WARNING: SetWindowPos; unsupported flag"));
2493 }
2494
2495 if(IsWindowDestroyed()) {
2496 //changing the position of a window that's being destroyed can cause crashes in PMMERGE
2497 dprintf(("SetWindowPos; window already destroyed"));
2498 return TRUE;
2499 }
2500
2501 if(state >= STATE_CREATED) {
2502 /* Fix redundant flags */
2503 if(getStyle() & WS_VISIBLE) {
2504 fuFlags &= ~SWP_SHOWWINDOW;
2505 }
2506 else
2507 {
2508 if (!(fuFlags & SWP_SHOWWINDOW))
2509 fuFlags |= SWP_NOREDRAW;
2510 fuFlags &= ~SWP_HIDEWINDOW;
2511 }
2512 //SvL: These checks are causing problems in Lotus Notes 6
2513 // It's not entirely clear why, but child windows are not placed
2514 // correctly when enabling them.
2515#if 0
2516 if((rectWindow.right - rectWindow.left == cx) && (rectWindow.bottom - rectWindow.top == cy)) {
2517 fuFlags |= SWP_NOSIZE; /* Already the right size */
2518 }
2519
2520 if((rectWindow.left == x) && (rectWindow.top == y)) {
2521 fuFlags |= SWP_NOMOVE; /* Already the right position */
2522 }
2523#endif
2524
2525 if(getWindowHandle() == GetActiveWindow()) {
2526 fuFlags |= SWP_NOACTIVATE; /* Already active */
2527 }
2528 else
2529 if((getStyle() & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2530 {
2531 if(!(fuFlags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2532 {
2533 fuFlags &= ~SWP_NOZORDER;
2534 hwndInsertAfter = HWND_TOP;
2535 }
2536 }
2537 }
2538
2539 /* TODO: Check hwndInsertAfter */
2540
2541 //Note: Solitaire crashes when receiving WM_SIZE messages before WM_CREATE
2542 if(state < STATE_POST_WMNCCREATE)
2543 {//don't change size; modify internal structures only
2544 //TODO: not 100% correct yet (activate)
2545 dprintf2(("state < STATE_POST_WMNCCREATE"));
2546 if(!(fuFlags & SWP_NOZORDER)) {
2547 hwndLinkAfter = hwndInsertAfter;
2548 }
2549 if(!(fuFlags & SWP_NOMOVE)) {
2550 rectWindow.bottom = (rectWindow.bottom - rectWindow.top) + y;
2551 rectWindow.top = y;
2552 rectWindow.right = (rectWindow.right - rectWindow.left) + x;
2553 rectWindow.left = x;
2554 }
2555 if(!(fuFlags & SWP_NOSIZE)) {
2556 rectWindow.bottom = rectWindow.top + cy;
2557 rectWindow.right = rectWindow.left + cx;
2558 }
2559 return TRUE;
2560 }
2561
2562 WINDOWPOS wpos;
2563 SWP swp, swpOld;
2564 wpos.flags = fuFlags;
2565 wpos.cy = cy;
2566 wpos.cx = cx;
2567 wpos.x = x;
2568 wpos.y = y;
2569 wpos.hwndInsertAfter = hwndInsertAfter;
2570 wpos.hwnd = getWindowHandle();
2571
2572 if(~fuFlags & (SWP_NOMOVE | SWP_NOSIZE))
2573 {
2574 if (isChild())
2575 {
2576 if(!getParent()) {
2577 dprintf(("WARNING: Win32BaseWindow::SetWindowPos window %x is child but has no parent!!", getWindowHandle()));
2578 }
2579 }
2580 OSLibWinQueryWindowPos(OS2HwndFrame, &swpOld);
2581 }
2582 if((dwOldStyle & WS_MINIMIZE) && (getStyle() & WS_MINIMIZE))
2583 {//don't allow size changes if the window is minimized
2584 //we will update the restore position at the end of this method
2585 if(!(wpos.flags & SWP_NOSIZE)) {
2586 //TODO: updating the window rectangle doesn't look right
2587 wpos.flags |= SWP_NOSIZE;
2588 rectWindow.right = rectWindow.left + wpos.cx;
2589 rectWindow.bottom = rectWindow.top + wpos.cy;
2590 dprintf(("WARNING: Don't allow size change for minimized window; only save new restore position"));
2591 dprintf(("new window rectangle (%d,%d)(%d,%d)", rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2592 }
2593 }
2594
2595 // Hack alert: This makes sure the tooltips windows in OpenOffice don't
2596 // activate the owner windows too.
2597 // First condition takes care of SetWindowPos during window
2598 // creation. The 2nd one for calls made by OpenOffice
2599 if(((getStyle() & WS_POPUP) && (getExStyle() & WS_EX_TOPMOST)) || (fuFlags & SWP_NOOWNERZORDER))
2600 {
2601 //SWP_NOOWNERZORDER means only the z-order of this window changes; it
2602 //should not affect the owner
2603 //PM doesn't support this feature, so this hack might work
2604 wpos.flags |= SWP_NOZORDER;
2605 }
2606
2607 if(getParent()) {
2608 OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, getParent()->getClientHeight(),
2609 OS2HwndFrame);
2610 }
2611 else OSLibMapWINDOWPOStoSWP(&wpos, &swp, &swpOld, OSLibQueryScreenHeight(), OS2HwndFrame);
2612
2613 if (swp.fl == 0) {
2614 dprintf2(("swp.fl == 0"));
2615 if(fuFlags & SWP_FRAMECHANGED)
2616 {
2617 NotifyFrameChanged(&wpos, &oldClientRect);
2618 }
2619 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)) && !(fuFlags & (SWP_NOSIZE | SWP_NOMOVE)))
2620 {
2621 //Restore position always changes when the window position is changed
2622 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2623 windowpos.rcNormalPosition = rectWindow;
2624 }
2625 return TRUE;
2626 }
2627
2628// if ((swp.fl & SWPOS_ZORDER) && (swp.hwndInsertBehind > HWNDOS_BOTTOM))
2629 if ((swp.hwndInsertBehind > HWNDOS_BOTTOM))
2630 {
2631 Win32BaseWindow *wndBehind = Win32BaseWindow::GetWindowFromHandle(swp.hwndInsertBehind);
2632 if(wndBehind) {
2633 swp.hwndInsertBehind = wndBehind->getOS2FrameWindowHandle();
2634 RELEASE_WNDOBJ(wndBehind);
2635 }
2636 else {
2637 dprintf(("ERROR: SetWindowPos: hwndInsertBehind %x invalid!",swp.hwndInsertBehind));
2638 swp.hwndInsertBehind = 0;
2639 }
2640 }
2641 swp.hwnd = OS2HwndFrame;
2642
2643 //SvL: Must also deactivate the window when hiding it or else focus won't
2644 // change. (NOTE: make sure this doesn't cause regressions (01-02-2003)
2645 if((swp.fl & (SWPOS_HIDE|SWPOS_DEACTIVATE)) == (SWPOS_HIDE|SWPOS_DEACTIVATE))
2646 {
2647 //we must make sure the owner is not disabled or else the focus will
2648 //be switched to the wrong window
2649 Win32BaseWindow *topOwner;
2650
2651 if(getOwner() == NULL) {
2652 windowDesktop->addRef();
2653 topOwner = windowDesktop;
2654 }
2655 else topOwner = GetWindowFromHandle(getOwner()->GetTopParent());
2656
2657 if(topOwner != NULL) {
2658 DWORD dwStyle = topOwner->GetWindowLong(GWL_STYLE, FALSE);
2659 if(dwStyle & WS_DISABLED) {
2660 swp.fl &= ~SWPOS_DEACTIVATE;
2661 }
2662 }
2663 else DebugInt3();
2664 }
2665
2666 if(fuFlags & SWP_SHOWWINDOW && !IsWindowVisible(getWindowHandle())) {
2667 setStyle(getStyle() | WS_VISIBLE);
2668 if(hTaskList) {
2669 dprintf(("Adding window %x to tasklist", getWindowHandle()));
2670 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 1);
2671 }
2672 }
2673 else
2674 if((fuFlags & SWP_HIDEWINDOW) && IsWindowVisible(getWindowHandle())) {
2675 setStyle(getStyle() & ~WS_VISIBLE);
2676 if(hTaskList && !(getStyle() & WS_MINIMIZE)) {
2677 dprintf(("Removing window %x from tasklist", getWindowHandle()));
2678 OSLibWinChangeTaskList(hTaskList, OS2HwndFrame, getWindowNameA(), 0);
2679 }
2680 }
2681 dprintf (("WinSetWindowPos %x %x (%d,%d)(%d,%d) %x", swp.hwnd, swp.hwndInsertBehind, swp.x, swp.y, swp.cx, swp.cy, swp.fl));
2682
2683 rc = OSLibWinSetMultWindowPos(&swp, 1);
2684 if(rc == FALSE)
2685 {
2686 dprintf(("OSLibWinSetMultWindowPos failed! Error %x",OSLibWinGetLastError()));
2687 return 0;
2688 }
2689
2690 if((fuFlags & SWP_FRAMECHANGED) && (fuFlags & (SWP_NOMOVE | SWP_NOSIZE) == (SWP_NOMOVE | SWP_NOSIZE)))
2691 {
2692 NotifyFrameChanged(&wpos, &oldClientRect);
2693 }
2694 if(!fShowWindow && !(getStyle() & (WS_MINIMIZE|WS_MAXIMIZE)))
2695 {
2696 //Restore position always changes when the window position is changed
2697 dprintf(("Save new restore position %x (%d,%d)(%d,%d)", getWindowHandle(), rectWindow.left, rectWindow.top, rectWindow.right, rectWindow.bottom));
2698 windowpos.rcNormalPosition = rectWindow;
2699 }
2700 //MSDN says the entire client area will be invalidated when SWP_NOCOPYBITS
2701 //is specified (fixes repaint issues when window is made smaller)
2702 if((fuFlags & (SWP_NOCOPYBITS|SWP_NOREDRAW)) == SWP_NOCOPYBITS) {
2703 InvalidateRect(getWindowHandle(), NULL, TRUE);
2704 }
2705
2706 if(!(fuFlags & SWP_NOSIZE))
2707 {
2708 // We must call this function or open DC will get out of sync
2709 // (PM will not always send us a WM_VRNENABLED message)
2710 RecalcVisibleRegion(this);
2711 }
2712 return (rc);
2713}
2714//******************************************************************************
2715//Called by ScrollWindowEx (dc.cpp) to notify child window that it has moved
2716//******************************************************************************
2717BOOL Win32BaseWindow::ScrollWindow(int dx, int dy)
2718{
2719 rectWindow.left += dx;
2720 rectWindow.right += dx;
2721 rectWindow.top += dy;
2722 rectWindow.bottom += dy;
2723 SendMessageA(getWindowHandle(),WM_MOVE, 0, MAKELONG(rectClient.left, rectClient.top));
2724 return TRUE;
2725}
2726//******************************************************************************
2727//******************************************************************************
2728void Win32BaseWindow::NotifyFrameChanged(WINDOWPOS *wpos, RECT *oldClientRect)
2729{
2730 HRGN hrgn, hrgnClient;
2731 RECT rect;
2732
2733 MsgFormatFrame(NULL);
2734
2735 if(RECT_WIDTH(rectClient) != RECT_WIDTH(*oldClientRect) ||
2736 RECT_HEIGHT(rectClient) != RECT_HEIGHT(*oldClientRect))
2737 {
2738 wpos->flags &= ~(SWP_NOSIZE|SWP_NOCLIENTSIZE);
2739 wpos->cx = RECT_WIDTH(rectWindow);
2740 wpos->cy = RECT_HEIGHT(rectWindow);
2741 }
2742
2743 if(rectClient.left != oldClientRect->left ||
2744 rectClient.top != oldClientRect->top)
2745 {
2746 wpos->flags &= ~(SWP_NOMOVE|SWP_NOCLIENTMOVE);
2747 wpos->x = rectWindow.left;
2748 wpos->y = rectWindow.top;
2749 }
2750
2751 WINDOWPOS wpOld = *wpos;
2752 if(!(wpos->flags & SWP_NOSENDCHANGING))
2753 SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGING, 0, (LPARAM)wpos);
2754
2755 if ((wpos->hwndInsertAfter != wpOld.hwndInsertAfter) ||
2756 (wpos->x != wpOld.x) || (wpos->y != wpOld.y) || (wpos->cx != wpOld.cx) || (wpos->cy != wpOld.cy) || (wpos->flags != wpOld.flags))
2757 {
2758 dprintf(("WARNING, NotifyFrameChanged: TODO -> adjust flags!!!!"));
2759 SetWindowPos(wpos->hwndInsertAfter, wpos->x, wpos->y, wpos->cx, wpos->cy, wpos->flags | SWP_NOSENDCHANGING);
2760 }
2761 else SendMessageA(getWindowHandle(),WM_WINDOWPOSCHANGED, 0, (LPARAM)wpos);
2762
2763 //Calculate invalid areas
2764 rect = rectWindow;
2765 OffsetRect(&rect, -rectWindow.left, -rectWindow.top);
2766 hrgn = CreateRectRgnIndirect(&rect);
2767 if (!hrgn) {
2768 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2769 return;
2770 }
2771 rect = rectClient;
2772 hrgnClient = CreateRectRgnIndirect(&rect);
2773 if (!hrgn) {
2774 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2775 return;
2776 }
2777 CombineRgn(hrgn, hrgn, hrgnClient, RGN_DIFF);
2778 DeleteObject(hrgnClient);
2779
2780 if(!EqualRect(oldClientRect, &rectClient)) {
2781 UnionRect(oldClientRect, oldClientRect, &rectClient);
2782 hrgnClient = CreateRectRgnIndirect(oldClientRect);
2783 if (!hrgn) {
2784 dprintf(("ERROR: NotifyFrameChanged, CreateRectRgnIndirect failed!!"));
2785 return;
2786 }
2787 CombineRgn(hrgn, hrgn, hrgnClient, RGN_OR);
2788 DeleteObject(hrgnClient);
2789 }
2790 RedrawWindow(getWindowHandle(), NULL, hrgn, RDW_ALLCHILDREN |
2791 RDW_INVALIDATE | RDW_ERASE | RDW_FRAME);
2792 DeleteObject(hrgn);
2793}
2794//******************************************************************************
2795//TODO: Check how this api really works in NT
2796//******************************************************************************
2797BOOL Win32BaseWindow::SetWindowPlacement(WINDOWPLACEMENT *wndpl)
2798{
2799 dprintf(("SetWindowPlacement %x min (%d,%d)", getWindowHandle(), wndpl->ptMinPosition.x, wndpl->ptMinPosition.y));
2800 dprintf(("SetWindowPlacement %x max (%d,%d)", getWindowHandle(), wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y));
2801 dprintf(("SetWindowPlacement %x norm (%d,%d)(%d,%d)", getWindowHandle(), wndpl->rcNormalPosition.left, wndpl->rcNormalPosition.top, wndpl->rcNormalPosition.right, wndpl->rcNormalPosition.bottom));
2802 windowpos.ptMinPosition = wndpl->ptMinPosition;
2803 windowpos.ptMaxPosition = wndpl->ptMaxPosition;
2804 windowpos.rcNormalPosition = wndpl->rcNormalPosition;
2805
2806 if(getStyle() & WS_MINIMIZE )
2807 {
2808 //TODO: Why can't this be (0,0)?
2809 if(wndpl->flags & WPF_SETMINPOSITION && !(!windowpos.ptMinPosition.x && !windowpos.ptMinPosition.y)) {
2810 SetWindowPos(0, windowpos.ptMinPosition.x, windowpos.ptMinPosition.y,
2811 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2812 }
2813 }
2814 else
2815 if(getStyle() & WS_MAXIMIZE )
2816 {
2817 //TODO: Why can't this be (0,0)?
2818 if(windowpos.ptMaxPosition.x != 0 || windowpos.ptMaxPosition.y != 0 )
2819 SetWindowPos(0, windowpos.ptMaxPosition.x, windowpos.ptMaxPosition.y,
2820 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
2821 }
2822 else {
2823 SetWindowPos(0, windowpos.rcNormalPosition.left, windowpos.rcNormalPosition.top,
2824 windowpos.rcNormalPosition.right - windowpos.rcNormalPosition.left,
2825 windowpos.rcNormalPosition.bottom - windowpos.rcNormalPosition.top,
2826 SWP_NOZORDER | SWP_NOACTIVATE );
2827 }
2828 ShowWindow(wndpl->showCmd);
2829 if( ::IsWindow(getWindowHandle()) && getStyle() & WS_MINIMIZE )
2830 {
2831 /* SDK: ...valid only the next time... */
2832 if(wndpl->flags & WPF_RESTORETOMAXIMIZED)
2833 setFlags(getFlags() | WIN_RESTORE_MAX);
2834 }
2835 return TRUE;
2836}
2837//******************************************************************************
2838//******************************************************************************
2839BOOL Win32BaseWindow::GetWindowPlacement(LPWINDOWPLACEMENT wndpl)
2840{
2841 wndpl->length = sizeof(*wndpl);
2842 if(getStyle() & WS_MINIMIZE )
2843 wndpl->showCmd = SW_SHOWMINIMIZED;
2844 else wndpl->showCmd = (getStyle() & WS_MAXIMIZE) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
2845
2846 //TODO: Verify if this is correct -> SDK docs claim this flag must always be set to 0
2847 if(getFlags() & WIN_RESTORE_MAX )
2848 wndpl->flags = WPF_RESTORETOMAXIMIZED;
2849 else wndpl->flags = 0;
2850
2851 wndpl->ptMinPosition = windowpos.ptMinPosition;
2852 wndpl->ptMaxPosition = windowpos.ptMaxPosition;
2853 //Must be in parent coordinates (or screen if no parent); verified in NT4, SP6
2854 wndpl->rcNormalPosition = windowpos.rcNormalPosition;
2855
2856 return TRUE;
2857}
2858//******************************************************************************
2859//Also destroys all the child windows (destroy children first, parent last)
2860//TODO: Don't rely on PM to do the right thing. Send WM_(NC)DESTROY &
2861// destroy children ourselves (see Wine)
2862//******************************************************************************
2863BOOL Win32BaseWindow::DestroyWindow()
2864{
2865 HWND hwnd = getWindowHandle();
2866
2867 dprintf(("DestroyWindow %x", hwnd));
2868
2869#if 0
2870 /* Look whether the focus is within the tree of windows we will
2871 * be destroying.
2872 */
2873 HWND hwndFocus = GetFocus();
2874 if (hwndFocus == hwnd || ::IsChild( hwnd, hwndFocus ))
2875 {
2876 HWND parent = GetAncestor( hwnd, GA_PARENT );
2877 if (parent == GetDesktopWindow()) parent = 0;
2878 SetFocus( parent );
2879 }
2880#endif
2881 /* Call hooks */
2882 if(HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, getWindowHandle(), 0L))
2883 {
2884 return FALSE;
2885 }
2886
2887 if(!(getStyle() & WS_CHILD) && getOwner() == NULL)
2888 {
2889 HOOK_CallHooksA(WH_SHELL, HSHELL_WINDOWDESTROYED, getWindowHandle(), 0L);
2890 /* FIXME: clean up palette - see "Internals" p.352 */
2891 }
2892
2893 if((getStyle() & WS_CHILD) && !(getExStyle() & WS_EX_NOPARENTNOTIFY))
2894 {
2895 if(getParent() && getParent()->IsWindowDestroyed() == FALSE)
2896 {
2897 /* Notify the parent window only */
2898 SendMessageA(getParent()->getWindowHandle(), WM_PARENTNOTIFY, MAKEWPARAM(WM_DESTROY, getWindowId()), (LPARAM)getWindowHandle());
2899 if(!::IsWindow(hwnd) )
2900 {
2901 return TRUE;
2902 }
2903 }
2904//// else DebugInt3();
2905 }
2906 //Must remove the switch entry here to avoid problems with XWorkPlace
2907 if(hTaskList) {
2908 OSLibWinRemoveFromTasklist(hTaskList);
2909 hTaskList = 0;
2910 }
2911
2912 /* Hide the window */
2913 if(IsWindowVisible(getWindowHandle()))
2914 {
2915 SetWindowPos(0, 0, 0, 0, 0, SWP_HIDEWINDOW |
2916 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2917 if(!::IsWindow(hwnd))
2918 {
2919 return TRUE;
2920 }
2921 }
2922 dprintf(("DestroyWindow %x -> HIDDEN", hwnd));
2923
2924 // check the handle for the last active popup window
2925 Win32BaseWindow* owner = getOwner();
2926 if (NULL != owner)
2927 {
2928 if (owner->getLastActive() == hwnd)
2929 owner->setLastActive( owner->getWindowHandle() );
2930
2931 //SvL: Not sure this is correct, but it solves the problem of reassigning
2932 // activation. A disabled window will never be activated ->
2933 // possible that the wrong window is chosen by PM.
2934 // PM chooses another window to be activated before WM_DESTROY is
2935 // sent. VPC enables the owner when it receives that message,
2936 // but by then it's too late.
2937 // (MFC created modeless dialog)
2938 //TODO: This might be the wrong place to do it. EndDialog is called,
2939 // so perhaps it should be done there. (although Wine only
2940 // enables the owner if the dialog is modal)
2941 ::EnableWindow(owner->getWindowHandle(), 1);
2942 }
2943
2944 fDestroyWindowCalled = TRUE;
2945
2946//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2947// handler; must postpone it
2948 if(fChildDestructionInProgress) {
2949 dprintf(("Postponing parent destruction because of dying child"));
2950 OSLibPostMessageDirect(OS2HwndFrame, WIN32APP_POSTPONEDESTROY, 0, 0);
2951 return TRUE;
2952 }
2953
2954 BOOL fOldChildDestructionInProgress = FALSE;
2955 if(GetParent()) {
2956 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2957 if(window) {
2958 fOldChildDestructionInProgress = window->IsChildDestructionInProgress();
2959 window->SetChildDestructionInProgress(TRUE);
2960 RELEASE_WNDOBJ(window);
2961 }
2962 }
2963//hack end
2964
2965 BOOL ret = OSLibWinDestroyWindow(OS2HwndFrame);
2966
2967//hack alert; PM crashes if child calls DestroyWindow for parent/owner in WM_DESTROY
2968// handler; must postpone it
2969 if(GetParent()) {
2970 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(GetParent());
2971 if(window) {
2972 window->SetChildDestructionInProgress(fOldChildDestructionInProgress);
2973 RELEASE_WNDOBJ(window);
2974 }
2975 }
2976//hack end
2977 return ret;
2978}
2979//******************************************************************************
2980//******************************************************************************
2981Win32BaseWindow *Win32BaseWindow::getParent()
2982{
2983 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
2984 //experiment
2985#if 0
2986 return ((ULONG)wndparent == (ULONG)windowDesktop) ? NULL : wndparent;
2987#else
2988 return wndparent;
2989#endif
2990}
2991//******************************************************************************
2992// Win32BaseWindow::GetParent
2993//
2994// If the window is a child window, then return the parent window handle.
2995// If it's a popup window, then return the owner
2996//
2997// Returns window handle of parent or owner window
2998//
2999// Note: does not set last error if no parent (verified in NT4, SP6)
3000//******************************************************************************
3001HWND Win32BaseWindow::GetParent()
3002{
3003 Win32BaseWindow *wndparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3004
3005 if(getStyle() & WS_CHILD)
3006 {
3007 if(wndparent) {
3008 return wndparent->getWindowHandle();
3009 }
3010 dprintf(("WARNING: GetParent: WS_CHILD but no parent!!"));
3011 DebugInt3();
3012 return 0;
3013 }
3014 else
3015 if(getStyle() & WS_POPUP)
3016 return (getOwner()) ? getOwner()->getWindowHandle() : 0;
3017 else return 0;
3018}
3019//******************************************************************************
3020//******************************************************************************
3021HWND Win32BaseWindow::SetParent(HWND hwndNewParent)
3022{
3023 HWND oldhwnd;
3024 Win32BaseWindow *newparent;
3025 Win32BaseWindow *oldparent = (Win32BaseWindow *)ChildWindow::getParentOfChild();
3026 BOOL fShow = FALSE;
3027
3028 if(oldparent) {
3029 oldhwnd = oldparent->getWindowHandle();
3030 oldparent->removeChild(this);
3031 }
3032 else oldhwnd = 0;
3033
3034 /* Windows hides the window first, then shows it again
3035 * including the WM_SHOWWINDOW messages and all */
3036 if(IsWindowCreated() && (getStyle() & WS_VISIBLE)) {
3037 ShowWindow(SW_HIDE);
3038 fShow = TRUE;
3039 }
3040 if(oldparent) {
3041 //release parent here (increased refcount during creation)
3042 RELEASE_WNDOBJ(oldparent);
3043 }
3044 newparent = GetWindowFromHandle(hwndNewParent);
3045 if(newparent && !newparent->isDesktopWindow())
3046 {
3047 setParent(newparent);
3048 getParent()->addChild(this);
3049 fParentChange = TRUE;
3050 // in case we haven't finished creating the window whose parent we're
3051 // setting here, the OS/2 HWND might not exist yet and we call the PM
3052 // API with a NULLHANDLE - no problem
3053 // when we create the OS/2 window lateron, we will create it with the
3054 // right parent anyway.
3055 OSLibWinSetParent(getOS2FrameWindowHandle(), getParent()->getOS2WindowHandle());
3056 if(!(getStyle() & WS_CHILD))
3057 {
3058 if(getWindowId())
3059 {
3060 DestroyMenu( (HMENU) getWindowId() );
3061 setWindowId(0);
3062 }
3063 }
3064 //SvL: Even though the win32 coordinates might not change, the PM
3065 // coordinates can. We must make sure the control stays at the
3066 // same position (y) relative to the (new) parent.
3067 // TODO: shouldn't we check the state of the window and not do it in INIT state?
3068 SetWindowPos(HWND_TOPMOST, rectWindow.left, rectWindow.top, 0, 0,
3069 SWP_NOACTIVATE|SWP_NOSIZE);
3070 fParentChange = FALSE;
3071 }
3072 else {
3073 if(newparent) RELEASE_WNDOBJ(newparent);
3074
3075 setParent(windowDesktop);
3076 windowDesktop->addRef();
3077 windowDesktop->addChild(this);
3078 OSLibWinSetParent(getOS2FrameWindowHandle(), OSLIB_HWND_DESKTOP);
3079
3080 //Do not change the window id!
3081//// setWindowId(0);
3082 }
3083 /* SetParent additionally needs to make hwndChild the topmost window
3084 in the x-order and send the expected WM_WINDOWPOSCHANGING and
3085 WM_WINDOWPOSCHANGED notification messages.
3086 */
3087 if(state >= STATE_PRE_WMNCCREATE) {
3088 SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
3089 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|(fShow? SWP_SHOWWINDOW : 0));
3090
3091 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
3092 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
3093 }
3094 return oldhwnd;
3095}
3096//******************************************************************************
3097//******************************************************************************
3098BOOL Win32BaseWindow::IsChild(HWND hwndParent)
3099{
3100 // PH: Optimizer won't unroll calls to getParent() even
3101 // in release build.
3102 Win32BaseWindow *_parent = getParent();
3103
3104 if(_parent)
3105 {
3106 if(_parent->getWindowHandle() == hwndParent)
3107 return TRUE;
3108
3109 return _parent->IsChild(hwndParent);
3110 }
3111 else
3112 return 0;
3113}
3114//******************************************************************************
3115//******************************************************************************
3116HWND Win32BaseWindow::GetTopWindow()
3117{
3118 HWND hwndTop;
3119 Win32BaseWindow *topwindow;
3120
3121 hwndTop = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3122 if(!isDesktopWindow())
3123 {
3124 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3125 //Note: GetTopWindow can't return a window that hasn't processed
3126 // WM_NCCREATE yet (verified in NT4, SP6)
3127 if(topwindow) {
3128 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3129 hwndTop = topwindow->getWindowHandle();
3130 }
3131 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3132 RELEASE_WNDOBJ(topwindow);
3133 return hwndTop;
3134 }
3135 if(topwindow) RELEASE_WNDOBJ(topwindow);
3136 return 0;
3137 }
3138 while(hwndTop) {
3139 topwindow = GetWindowFromOS2FrameHandle(hwndTop);
3140 //Note: GetTopWindow can't return a window that hasn't processed
3141 // WM_NCCREATE yet (verified in NT4, SP6)
3142 if(topwindow) {
3143 if(topwindow->state >= STATE_POST_WMNCCREATE) {
3144 hwndTop = topwindow->getWindowHandle();
3145 }
3146 else hwndTop = topwindow->GetWindow(GW_HWNDNEXT);
3147 RELEASE_WNDOBJ(topwindow);
3148 return hwndTop;
3149 }
3150 if(topwindow) RELEASE_WNDOBJ(topwindow);
3151 hwndTop = OSLibWinQueryWindow(hwndTop, QWOS_NEXT);
3152 }
3153
3154 return 0;
3155}
3156//******************************************************************************
3157// Get the top-level parent for a child window.
3158//******************************************************************************
3159HWND Win32BaseWindow::GetTopParent()
3160{
3161 Win32BaseWindow *window = this;
3162 HWND hwndTopParent = 0;
3163
3164 lock();
3165 while(window && (window->getStyle() & WS_CHILD))
3166 {
3167 window = window->getParent();
3168 }
3169 if(window) {
3170 hwndTopParent = window->getWindowHandle();
3171 }
3172 unlock();
3173 return hwndTopParent;
3174}
3175//******************************************************************************
3176//TODO: Should not enumerate children that are created during the enumeration!
3177//TODO: Do this more efficiently
3178//******************************************************************************
3179BOOL Win32BaseWindow::EnumChildWindows(WNDENUMPROC lpfn, LPARAM lParam)
3180{
3181 BOOL rc = TRUE;
3182 HWND hwnd;
3183 Win32BaseWindow *prevchild = 0, *child = 0;
3184
3185 dprintf(("EnumChildWindows of %x parameter %x %x (%x)", getWindowHandle(), lpfn, lParam, getFirstChild()));
3186 lock();
3187 for (child = (Win32BaseWindow *)getFirstChild(); child != NULL; child = (Win32BaseWindow *)child->getNextChild())
3188 {
3189 dprintf(("EnumChildWindows: enumerating child %x (owner %x; parent %x)", child->getWindowHandle(), (child->getOwner()) ? child->getOwner()->getWindowHandle() : 0, getWindowHandle()));
3190 hwnd = child->getWindowHandle();
3191 if(child->IsWindowDestroyed() || child->getOwner()) {
3192 continue; //shouldn't have an owner (Wine)
3193 }
3194 child->addRef();
3195 unlock();
3196 if(WrapCallback2((WNDPROC)lpfn, hwnd, lParam) == FALSE)
3197 {
3198 child->release();
3199 return FALSE;
3200 }
3201 child->release();
3202 lock();
3203 //check if the window still exists
3204 if(!::IsWindow(hwnd))
3205 {
3206 child = prevchild;
3207 if(child == NULL) break;
3208 continue;
3209 }
3210 if(child->getFirstChild() != NULL)
3211 {
3212 dprintf(("EnumChildWindows: Enumerate children of %x", child->getWindowHandle()));
3213 child->addRef();
3214 unlock();
3215 if(child->EnumChildWindows(lpfn, lParam) == FALSE)
3216 {
3217 child->release();
3218 return FALSE;
3219 }
3220 child->release();
3221 lock();
3222 }
3223 prevchild = child;
3224 }
3225 unlock();
3226 return rc;
3227}
3228//******************************************************************************
3229//Enumerate first-level children only and check thread id
3230//NOTE: NT4 returns first-level children in Z-order!
3231//******************************************************************************
3232BOOL Win32BaseWindow::EnumThreadWindows(DWORD dwThreadId, WNDENUMPROC lpfn, LPARAM lParam)
3233{
3234 Win32BaseWindow *wnd = NULL;
3235 HWND henum, hwnd, hwndWin32;
3236 ULONG tid, pid;
3237 BOOL rc;
3238
3239 //Enumerate all top-level windows and check the process and thread ids
3240 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3241 hwnd = OSLibWinGetNextWindow(henum);
3242
3243 while(hwnd)
3244 {
3245 wnd = GetWindowFromOS2FrameHandle(hwnd);
3246 if(wnd) {
3247 hwndWin32 = wnd->getWindowHandle();
3248 }
3249 else hwndWin32 = 0;
3250
3251 if(wnd) RELEASE_WNDOBJ(wnd);
3252
3253 if(hwndWin32) {
3254 OSLibWinQueryWindowProcess(hwnd, &pid, &tid);
3255
3256 if(dwThreadId == tid) {
3257 dprintf(("EnumThreadWindows: Found Window %x", hwndWin32));
3258 if((rc = WrapCallback2((WNDPROC)lpfn, hwndWin32, lParam)) == FALSE) {
3259 break;
3260 }
3261 }
3262 }
3263 hwnd = OSLibWinGetNextWindow(henum);
3264 }
3265 OSLibWinEndEnumWindows(henum);
3266 return TRUE;
3267}
3268//******************************************************************************
3269//Enumerate first-level children only
3270//******************************************************************************
3271BOOL Win32BaseWindow::EnumWindows(WNDENUMPROC lpfn, LPARAM lParam)
3272{
3273 Win32BaseWindow *window;
3274 BOOL rc;
3275 HWND hwnd = WNDHANDLE_MAGIC_HIGHWORD;
3276 DWORD dwStyle;
3277
3278 dprintf(("EnumWindows %x %x", lpfn, lParam));
3279
3280 for(int i=0;i<MAX_WINDOW_HANDLES;i++)
3281 {
3282 window = Win32BaseWindow::GetWindowFromHandle(hwnd);
3283 if(window) {
3284 if(window->getWindowHandle() != hwnd) {
3285 dprintf(("CORRUPT WINDOW %x %x", window, hwnd));
3286 }
3287 RELEASE_WNDOBJ(window);
3288 dwStyle = ::GetWindowLongA(hwnd, GWL_STYLE);
3289 if ((dwStyle & WS_POPUP) || ((dwStyle & WS_CAPTION) == WS_CAPTION))
3290 {
3291 dprintf2(("EnumWindows: Found Window %x", hwnd));
3292 if((rc = WrapCallback2((WNDPROC)lpfn, hwnd, lParam)) == FALSE) {
3293 break;
3294 }
3295 }
3296 }
3297 hwnd++;
3298 }
3299 return TRUE;
3300}
3301//******************************************************************************
3302//******************************************************************************
3303HWND Win32BaseWindow::FindWindowById(int id)
3304{
3305 HWND hwnd;
3306
3307 lock();
3308 for (Win32BaseWindow *child = (Win32BaseWindow *)getFirstChild(); child; child = (Win32BaseWindow *)child->getNextChild())
3309 {
3310 if (child->getWindowId() == id)
3311 {
3312 hwnd = child->getWindowHandle();
3313 unlock();
3314 return hwnd;
3315 }
3316 }
3317 unlock();
3318 return 0;
3319}
3320//******************************************************************************
3321//TODO:
3322//We assume (for now) that if hwndParent or hwndChildAfter are real window handles, that
3323//the current process owns them.
3324//******************************************************************************
3325HWND Win32BaseWindow::FindWindowEx(HWND hwndParent, HWND hwndChildAfter, ATOM atom, LPSTR lpszWindow)
3326{
3327 Win32BaseWindow *parent = GetWindowFromHandle(hwndParent);
3328 Win32BaseWindow *child = GetWindowFromHandle(hwndChildAfter);
3329 Win32BaseWindow *firstchild = child;
3330
3331 dprintf(("FindWindowEx %x %x %x %s", hwndParent, hwndChildAfter, atom, lpszWindow));
3332 if((hwndParent != 0 && !parent) ||
3333 (hwndChildAfter != 0 && !child) ||
3334 (hwndParent == 0 && hwndChildAfter != 0))
3335 {
3336 if(parent) RELEASE_WNDOBJ(parent);
3337 if(firstchild) RELEASE_WNDOBJ(firstchild);
3338 dprintf(("Win32BaseWindow::FindWindowEx: parent or child not found %x %x", hwndParent, hwndChildAfter));
3339 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
3340 return 0;
3341 }
3342 SetLastError(0);
3343 if(hwndParent != 0)
3344 {//if the current process owns the window, just do a quick search
3345 lock(&critsect);
3346 child = (Win32BaseWindow *)parent->getFirstChild();
3347 if(hwndChildAfter != 0)
3348 {
3349 while(child)
3350 {
3351 if(child->getWindowHandle() == hwndChildAfter)
3352 {
3353 child = (Win32BaseWindow *)child->getNextChild();
3354 break;
3355 }
3356 child = (Win32BaseWindow *)child->getNextChild();
3357 }
3358 }
3359 while(child)
3360 {
3361 //According to Wine, the class doesn't need to be specified
3362 if((!atom || child->getWindowClass()->getAtom() == atom) &&
3363 (!lpszWindow || child->hasWindowName(lpszWindow)))
3364 {
3365 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3366 HWND hwndChild = child->getWindowHandle();
3367 unlock(&critsect);
3368 if(parent) RELEASE_WNDOBJ(parent);
3369 if(firstchild) RELEASE_WNDOBJ(firstchild);
3370 dprintf(("FindWindowEx: Found window %x", child->getWindowHandle()));
3371 return hwndChild;
3372 }
3373 child = (Win32BaseWindow *)child->getNextChild();
3374 }
3375 unlock(&critsect);
3376 if(parent) RELEASE_WNDOBJ(parent);
3377 if(firstchild) RELEASE_WNDOBJ(firstchild);
3378 }
3379 else {
3380 Win32BaseWindow *wnd;
3381 HWND henum, hwnd;
3382
3383 henum = OSLibWinBeginEnumWindows(OSLIB_HWND_DESKTOP);
3384 hwnd = OSLibWinGetNextWindow(henum);
3385
3386 while(hwnd)
3387 {
3388 wnd = GetWindowFromOS2FrameHandle(hwnd);
3389 if(wnd) {
3390 //According to Wine, the class doesn't need to be specified
3391 if((!atom || wnd->getWindowClass()->getAtom() == atom) &&
3392 (!lpszWindow || wnd->hasWindowName(lpszWindow)))
3393 {
3394 OSLibWinEndEnumWindows(henum);
3395 dprintf(("FindWindowEx: Found window %x", wnd->getWindowHandle()));
3396 HWND hwndret = wnd->getWindowHandle();
3397 RELEASE_WNDOBJ(wnd);
3398 return hwndret;
3399 }
3400 RELEASE_WNDOBJ(wnd);
3401 }
3402 hwnd = OSLibWinGetNextWindow(henum);
3403 }
3404 OSLibWinEndEnumWindows(henum);
3405 if(parent) RELEASE_WNDOBJ(parent);
3406 if(firstchild) RELEASE_WNDOBJ(firstchild);
3407 }
3408 SetLastError(ERROR_CANNOT_FIND_WND_CLASS); //TODO: not always correct
3409 return 0;
3410}
3411//******************************************************************************
3412//******************************************************************************
3413HWND Win32BaseWindow::GetWindow(UINT uCmd)
3414{
3415 HWND hwndRelated = 0;
3416 Win32BaseWindow *window;
3417
3418 switch(uCmd)
3419 {
3420 case GW_HWNDFIRST:
3421 window = (Win32BaseWindow *)getParent();
3422 if(window)
3423 {
3424 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_TOP);
3425 window = GetWindowFromOS2FrameHandle(hwndRelated);
3426 if(window) {
3427 hwndRelated = window->getWindowHandle();
3428 RELEASE_WNDOBJ(window);
3429 }
3430 else hwndRelated = 0;
3431 }
3432 else {
3433 dprintf(("WARNING: GW_HWNDFIRST not correctly implemented for toplevel/most windows!"));
3434 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3435 }
3436 break;
3437
3438 case GW_HWNDLAST:
3439 window = (Win32BaseWindow *)getParent();
3440 if(window) {
3441 hwndRelated = OSLibWinQueryWindow(window->getOS2WindowHandle(), QWOS_BOTTOM);
3442 dprintf(("os2 handle %x", hwndRelated));
3443 window = GetWindowFromOS2FrameHandle(hwndRelated);
3444 if(window) {
3445 hwndRelated = window->getWindowHandle();
3446 RELEASE_WNDOBJ(window);
3447 }
3448 else hwndRelated = 0;
3449 }
3450 else {
3451 dprintf(("WARNING: GW_HWNDLAST not correctly implemented for toplevel/most windows!"));
3452 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3453 }
3454 break;
3455
3456 case GW_HWNDNEXT:
3457 if(getParent()) {
3458 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_NEXT);
3459 window = GetWindowFromOS2FrameHandle(hwndRelated);
3460 if(window) {
3461 hwndRelated = window->getWindowHandle();
3462 RELEASE_WNDOBJ(window);
3463 }
3464 else hwndRelated = 0;
3465 }
3466 else {
3467 dprintf(("WARNING: GW_HWNDNEXT not correctly implemented for toplevel/most windows!"));
3468 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3469 }
3470 break;
3471
3472 case GW_HWNDPREV:
3473 if(getParent()) {
3474 hwndRelated = OSLibWinQueryWindow(getOS2FrameWindowHandle(), QWOS_PREV);
3475 window = GetWindowFromOS2FrameHandle(hwndRelated);
3476 if(window) {
3477 hwndRelated = window->getWindowHandle();
3478 RELEASE_WNDOBJ(window);
3479 }
3480 else hwndRelated = 0;
3481 }
3482 else {
3483 dprintf(("WARNING: GW_HWNDPREV not correctly implemented for toplevel/most windows!"));
3484 hwndRelated = 0; //TODO: not correct; should get first child in z-order of desktop
3485 }
3486 break;
3487
3488 case GW_OWNER:
3489 {
3490 Win32BaseWindow *owner = getOwner();
3491 if(owner) {
3492 hwndRelated = owner->getWindowHandle();
3493 }
3494 break;
3495 }
3496
3497 case GW_CHILD:
3498 hwndRelated = OSLibWinQueryWindow(getOS2WindowHandle(), QWOS_TOP);
3499 window = GetWindowFromOS2FrameHandle(hwndRelated);
3500
3501 //Before a window has processed WM_NCCREATE:
3502 //- GetWindow(parent, GW_CHILD) can't return that window handle
3503 //(verified in NT4, SP6)
3504 if(window) {
3505 if(window->state >= STATE_POST_WMNCCREATE) {
3506 hwndRelated = window->getWindowHandle();
3507 RELEASE_WNDOBJ(window);
3508 }
3509 else {
3510 hwndRelated = window->GetWindow(GW_HWNDNEXT);
3511 RELEASE_WNDOBJ(window);
3512 }
3513 }
3514 else hwndRelated = 0;
3515
3516 break;
3517
3518 //for internal use only
3519 case GW_HWNDNEXTCHILD:
3520 lock();
3521 window = (Win32BaseWindow *)getNextChild();
3522 if(window) {
3523 hwndRelated = window->getWindowHandle();
3524 }
3525 else hwndRelated = 0;
3526 unlock();
3527 break;
3528
3529 case GW_HWNDPREVCHILD:
3530 DebugInt3();
3531 break;
3532
3533 case GW_HWNDFIRSTCHILD:
3534 lock();
3535 window = (Win32BaseWindow *)getFirstChild();
3536 if(window) {
3537 hwndRelated = window->getWindowHandle();
3538 }
3539 else hwndRelated = 0;
3540 unlock();
3541 break;
3542
3543 case GW_HWNDLASTCHILD:
3544 lock();
3545 window = (Win32BaseWindow *)getFirstChild();
3546 if(window) {
3547 while (window->getNextChild())
3548 {
3549 window = (Win32BaseWindow *)window->getNextChild();
3550 }
3551 hwndRelated = window->getWindowHandle();
3552 }
3553 else hwndRelated = 0;
3554 unlock();
3555 break;
3556 }
3557end:
3558 dprintf(("GetWindow %x %d returned %x", getWindowHandle(), uCmd, hwndRelated));
3559 return hwndRelated;
3560}
3561//******************************************************************************
3562//******************************************************************************
3563PRECT Win32BaseWindow::getWindowRect()
3564{
3565 return &rectWindow;
3566}
3567//******************************************************************************
3568//******************************************************************************
3569HWND Win32BaseWindow::SetActiveWindow()
3570{
3571 HWND hwndActive;
3572
3573 dprintf(("SetActiveWindow %x", getWindowHandle()));
3574 if(getStyle() & WS_CHILD) {
3575// if(getStyle() & (WS_DISABLED | WS_CHILD)) {
3576 dprintf(("WARNING: Window is a child or disabled"));
3577 return 0;
3578 }
3579
3580 if(GetActiveWindow() == getWindowHandle()) {
3581 dprintf(("Window already active"));
3582 return getWindowHandle();
3583 }
3584 if (HOOK_IsHooked( WH_CBT ))
3585 {
3586 CBTACTIVATESTRUCT cbta;
3587 LRESULT ret;
3588
3589 cbta.fMouse = FALSE;
3590 cbta.hWndActive = GetActiveWindow();
3591 ret = HOOK_CallHooksA(WH_CBT, HCBT_ACTIVATE, getWindowHandle(), (LPARAM)&cbta);
3592 if(ret)
3593 {
3594 dprintf(("SetActiveWindow %x, CBT hook cancelled operation", getWindowHandle()));
3595 return cbta.hWndActive;
3596 }
3597 }
3598 SetWindowPos(HWND_TOP, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
3599
3600// if(OSLibWinSetActiveWindow(OS2Hwnd) == FALSE) {
3601// dprintf(("OSLibWinSetActiveWindow %x returned FALSE!", OS2Hwnd));
3602// }
3603 hwndActive = GetActiveWindow();
3604 return (hwndActive) ? hwndActive : windowDesktop->getWindowHandle(); //pretend the desktop was active
3605}
3606//******************************************************************************
3607//Used to change active status of an mdi window
3608//******************************************************************************
3609BOOL Win32BaseWindow::DeactivateChildWindow()
3610{
3611 /* child windows get a WM_CHILDACTIVATE message */
3612 if((getStyle() & (WS_CHILD | WS_POPUP)) == WS_CHILD )
3613 {
3614 ULONG flags = OSLibWinGetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS);
3615 OSLibWinSetWindowULong(getOS2WindowHandle(), OFFSET_WIN32FLAGS, (flags & ~WINDOWFLAG_ACTIVE));
3616 return TRUE;
3617 }
3618 DebugInt3(); //should not be called for non-child window
3619 return FALSE;
3620}
3621//******************************************************************************
3622//WM_ENABLE is sent to hwnd, but not to its children (as it should be)
3623//******************************************************************************
3624BOOL Win32BaseWindow::EnableWindow(BOOL fEnable)
3625{
3626 BOOL rc;
3627
3628 dprintf(("Win32BaseWindow::EnableWindow %x %d", getWindowHandle(), fEnable));
3629 //return true if previous state was disabled, else false (sdk docs)
3630 rc = (getStyle() & WS_DISABLED) != 0;
3631 if(rc && !fEnable) {
3632 SendMessageA(getWindowHandle(), WM_CANCELMODE, 0, 0);
3633 }
3634 OSLibWinEnableWindow(OS2HwndFrame, fEnable);
3635 if(fEnable == FALSE) {
3636 //SvL: No need to clear focus as PM already does this
3637 if(getWindowHandle() == GetCapture()) {
3638 ReleaseCapture(); /* A disabled window can't capture the mouse */
3639 dprintf(("Released capture for window %x that is being disabled", getWindowHandle()));
3640 }
3641 }
3642 return rc;
3643}
3644//******************************************************************************
3645//******************************************************************************
3646BOOL Win32BaseWindow::CloseWindow()
3647{
3648 if (::GetWindowLongW( getWindowHandle() , GWL_STYLE ) & WS_CHILD) return FALSE;
3649 ShowWindow( SW_MINIMIZE );
3650 return TRUE;
3651}
3652//******************************************************************************
3653//TODO: Not be 100% correct; should return active window of current thread
3654// or NULL when there is none -> WinQueryActiveWindow just returns
3655// the current active window
3656//******************************************************************************
3657HWND Win32BaseWindow::GetActiveWindow()
3658{
3659 HWND hwndActive;
3660
3661 hwndActive = OSLibWinQueryActiveWindow();
3662 return OS2ToWin32Handle(hwndActive);
3663}
3664//******************************************************************************
3665//******************************************************************************
3666BOOL Win32BaseWindow::hasWindowName(LPSTR wndname, BOOL fUnicode)
3667{
3668 INT len = GetWindowTextLength(fUnicode);
3669 BOOL res;
3670
3671 if (wndname == NULL)
3672 return (len == 0);
3673
3674 len++;
3675 if (fUnicode)
3676 {
3677 WCHAR *text = (WCHAR*)malloc(len*sizeof(WCHAR));
3678
3679 GetWindowTextW(text,len);
3680 res = (lstrcmpW(text,(LPWSTR)wndname) == 0);
3681 free(text);
3682 }
3683 else
3684 {
3685 CHAR *text = (CHAR*)malloc(len*sizeof(CHAR));
3686
3687 GetWindowTextA(text,len);
3688 res = (strcmp(text,wndname) == 0);
3689 free(text);
3690 }
3691
3692 return res;
3693}
3694//******************************************************************************
3695//******************************************************************************
3696CHAR *Win32BaseWindow::getWindowNamePtrA()
3697{
3698 INT len = GetWindowTextLength(FALSE);
3699 CHAR *text;
3700
3701 if (len == 0) return NULL;
3702 len++;
3703 text = (CHAR*)malloc(len*sizeof(CHAR));
3704 GetWindowTextA(text,len);
3705
3706 return text;
3707}
3708//******************************************************************************
3709//******************************************************************************
3710WCHAR *Win32BaseWindow::getWindowNamePtrW()
3711{
3712 INT len = GetWindowTextLength(TRUE);
3713 WCHAR *text;
3714
3715 if (len == 0) return NULL;
3716 len++;
3717 text = (WCHAR*)malloc(len*sizeof(WCHAR));
3718 GetWindowTextW(text,len);
3719
3720 return text;
3721}
3722//******************************************************************************
3723//******************************************************************************
3724VOID Win32BaseWindow::freeWindowNamePtr(PVOID namePtr)
3725{
3726 if (namePtr) free(namePtr);
3727}
3728//******************************************************************************
3729//When using this API for a window that was created by a different process, NT
3730//does NOT send WM_GETTEXTLENGTH.
3731//******************************************************************************
3732int Win32BaseWindow::GetWindowTextLength(BOOL fUnicode)
3733{
3734 //if the destination window is created by this process, send message
3735 if(dwProcessId == currentProcessId)
3736 {
3737 if(fUnicode) {
3738 return SendMessageW(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3739 }
3740 else return SendMessageA(getWindowHandle(), WM_GETTEXTLENGTH,0,0);
3741 }
3742 //else get data directory from window structure
3743 //TODO: must lock window structure.... (TODO)
3744 return fUnicode ? windowNameLengthW : windowNameLengthA;
3745}
3746//******************************************************************************
3747//When using this API for a window that was created by a different process, NT
3748//does NOT send WM_GETTEXT.
3749//******************************************************************************
3750int Win32BaseWindow::GetWindowTextA(LPSTR lpsz, int cch)
3751{
3752 //if the destination window is created by this process, send message
3753 if(dwProcessId == currentProcessId) {
3754 return SendMessageA(getWindowHandle(),WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3755 }
3756
3757 //else get data directory from window structure
3758 if (!lpsz || !cch) return 0;
3759 if (!windowNameA) lpsz[0] = 0;
3760 else lstrcpynA( lpsz, windowNameA, cch );
3761 return strlen( lpsz );
3762}
3763//******************************************************************************
3764//When using this API for a window that was created by a different process, NT
3765//does NOT send WM_GETTEXT.
3766//******************************************************************************
3767int Win32BaseWindow::GetWindowTextW(LPWSTR lpsz, int cch)
3768{
3769 //if the destination window is created by this process, send message
3770 if(dwProcessId == currentProcessId) {
3771 return ::SendMessageW(getWindowHandle(), WM_GETTEXT,(WPARAM)cch,(LPARAM)lpsz);
3772 }
3773 //else get data directory from window structure
3774 if (!lpsz || !cch)
3775 return 0;
3776 if (!windowNameW)
3777 lpsz[0] = 0;
3778 else
3779 lstrcpynW( lpsz, windowNameW, cch );
3780
3781 return strlenW( lpsz );
3782}
3783//******************************************************************************
3784//TODO: How does this work when the target window belongs to a different process???
3785//******************************************************************************
3786BOOL Win32BaseWindow::SetWindowTextA(LPSTR lpsz)
3787{
3788 return SendMessageA(getWindowHandle(),WM_SETTEXT,0,(LPARAM)lpsz);
3789}
3790//******************************************************************************
3791//******************************************************************************
3792BOOL Win32BaseWindow::SetWindowTextW(LPWSTR lpsz)
3793{
3794 return SendMessageW(getWindowHandle(), WM_SETTEXT,0,(LPARAM)lpsz);
3795}
3796//******************************************************************************
3797//******************************************************************************
3798LONG Win32BaseWindow::SetWindowLong(int index, ULONG value, BOOL fUnicode)
3799{
3800 LONG oldval;
3801
3802 switch(index) {
3803 case GWL_EXSTYLE:
3804 {
3805 STYLESTRUCT ss;
3806
3807 if(dwExStyle == value) {
3808 oldval = value;
3809 break;
3810 }
3811 ss.styleOld = dwExStyle;
3812 ss.styleNew = value;
3813 dprintf(("SetWindowLong GWL_EXSTYLE %x old %x new style %x", getWindowHandle(), dwExStyle, value));
3814 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&ss);
3815 setExStyle(ss.styleNew);
3816 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&ss);
3817
3818 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3819 getStyle(), getExStyle(),ss.styleOld);
3820
3821 oldval = ss.styleOld;
3822 break;
3823 }
3824 case GWL_STYLE:
3825 {
3826 STYLESTRUCT ss;
3827
3828 //SvL: TODO: Can you change minimize or maximize status here too?
3829
3830 if(dwStyle == value) {
3831 oldval = value;
3832 break;
3833 }
3834 dprintf(("SetWindowLong GWL_STYLE %x old %x new style %x (%x)", getWindowHandle(), dwStyle, value));
3835
3836 //Changing WS_CHILD style is allowed
3837 ss.styleOld = getStyle();
3838 ss.styleNew = value;
3839 SendMessageA(getWindowHandle(),WM_STYLECHANGING,GWL_STYLE,(LPARAM)&ss);
3840 setStyle(ss.styleNew);
3841 SendMessageA(getWindowHandle(),WM_STYLECHANGED,GWL_STYLE,(LPARAM)&ss);
3842
3843 OSLibSetWindowStyle(getOS2FrameWindowHandle(), getOS2WindowHandle(),
3844 getStyle(), getExStyle(),ss.styleOld);
3845
3846 //TODO: Might not be correct to use ShowWindow here
3847 if((ss.styleOld & WS_VISIBLE) != (ss.styleNew & WS_VISIBLE)) {
3848 if(ss.styleNew & WS_VISIBLE)
3849 ShowWindow(SW_SHOWNOACTIVATE);
3850 else ShowWindow(SW_HIDE);
3851 }
3852
3853#ifdef DEBUG
3854 PrintWindowStyle(ss.styleNew, 0);
3855#endif
3856 oldval = ss.styleOld;
3857 break;
3858 }
3859 case GWL_WNDPROC:
3860 {
3861 //Note: Type of SetWindowLong determines new window proc type
3862 // UNLESS the new window proc has already been registered
3863 // (use the old type in that case)
3864 // (VERIFIED in NT 4, SP6)
3865 WINDOWPROCTYPE type = WINPROC_GetProcType((HWINDOWPROC)value);
3866 if(type == WIN_PROC_INVALID) {
3867 type = (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A;
3868 }
3869 oldval = (LONG)WINPROC_GetProc((HWINDOWPROC)win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3870 dprintf(("SetWindowLong%c GWL_WNDPROC %x old %x new wndproc %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), oldval, value));
3871 WINPROC_SetProc((HWINDOWPROC *)&win32wndproc, (WNDPROC)value, type, WIN_PROC_WINDOW);
3872 break;
3873 }
3874 case GWL_HINSTANCE:
3875 oldval = hInstance;
3876 hInstance = value;
3877 break;
3878
3879 case GWL_HWNDPARENT:
3880 dprintf(("GWL_ID GWL_HWNDPARENT %x, new %x", GetParent(), value));
3881 oldval = SetParent((HWND)value);
3882 break;
3883
3884 case GWL_ID:
3885 dprintf(("GWL_ID old %x, new %x", getWindowId(), value));
3886 oldval = getWindowId();
3887 setWindowId(value);
3888 break;
3889
3890 case GWL_USERDATA:
3891 oldval = userData;
3892 userData = value;
3893 break;
3894
3895 default:
3896 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3897 {
3898 oldval = *(ULONG *)(userWindowBytes + index);
3899 *(ULONG *)(userWindowBytes + index) = value;
3900 break;
3901 }
3902 dprintf(("WARNING: SetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3903 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3904 return 0;
3905 }
3906 //Note: NT4, SP6 does not set the last error to 0
3907 SetLastError(ERROR_SUCCESS);
3908 dprintf2(("SetWindowLong%c %x %d %x returned %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value, oldval));
3909 return oldval;
3910}
3911//******************************************************************************
3912//******************************************************************************
3913ULONG Win32BaseWindow::GetWindowLong(int index, BOOL fUnicode)
3914{
3915 ULONG value;
3916
3917 switch(index) {
3918 case GWL_EXSTYLE:
3919 value = dwExStyle;
3920 break;
3921 case GWL_STYLE:
3922 value = dwStyle;
3923 break;
3924 case GWL_WNDPROC:
3925 value = (LONG)WINPROC_GetProc((HWINDOWPROC)win32wndproc, (fUnicode) ? WIN_PROC_32W : WIN_PROC_32A);
3926 break;
3927 case GWL_HINSTANCE:
3928 value = hInstance;
3929 break;
3930 case GWL_HWNDPARENT:
3931 value = GetParent();
3932 break;
3933 case GWL_ID:
3934 value = getWindowId();
3935 break;
3936 case GWL_USERDATA:
3937 value = userData;
3938 break;
3939 default:
3940 if(index >= 0 && index + sizeof(ULONG) <= nrUserWindowBytes)
3941 {
3942 value = *(ULONG *)(userWindowBytes + index);
3943 break;
3944 }
3945 dprintf(("WARNING: GetWindowLong%c %x %d %x returned %x INVALID index!", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3946 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3947 return 0;
3948 }
3949 dprintf2(("GetWindowLong%c %x %d %x", (fUnicode) ? 'W' : 'A', getWindowHandle(), index, value));
3950 //Note: NT4, SP6 does not set the last error to 0
3951 SetLastError(ERROR_SUCCESS);
3952 return value;
3953}
3954//******************************************************************************
3955//******************************************************************************
3956WORD Win32BaseWindow::SetWindowWord(int index, WORD value)
3957{
3958 WORD oldval;
3959
3960 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
3961 {
3962 oldval = *(WORD *)(userWindowBytes + index);
3963 *(WORD *)(userWindowBytes + index) = value;
3964 //Note: NT4, SP6 does not set the last error to 0
3965 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3966 SetLastError(ERROR_SUCCESS);
3967 return oldval;
3968 }
3969 switch(index)
3970 {
3971 case GWW_HINSTANCE:
3972 oldval = hInstance;
3973 hInstance = value;
3974 break;
3975
3976 case GWW_HWNDPARENT:
3977 oldval = SetParent((HWND)(WNDHANDLE_MAGIC_HIGHWORD | value));
3978 break;
3979
3980 case GWW_ID:
3981 oldval = getWindowId();
3982 setWindowId(value);
3983 break;
3984
3985 default:
3986 dprintf(("WARNING: SetWindowWord %x %d %x returned %x INVALID index!", getWindowHandle(), index, value));
3987 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
3988 return 0;
3989 }
3990 //Note: NT4, SP6 does not set the last error to 0
3991 SetLastError(ERROR_SUCCESS);
3992 dprintf2(("SetWindowWord %x %d %x returned %x", getWindowHandle(), index, value, oldval));
3993 return oldval;
3994}
3995//******************************************************************************
3996//******************************************************************************
3997WORD Win32BaseWindow::GetWindowWord(int index)
3998{
3999 if(index >= 0 && index + sizeof(WORD) <= nrUserWindowBytes)
4000 {
4001 //Note: NT4, SP6 does not set the last error to 0
4002 SetLastError(ERROR_SUCCESS);
4003 dprintf2(("GetWindowWord %x %d %x", getWindowHandle(), index, *(WORD *)(userWindowBytes + index)));
4004 return *(WORD *)(userWindowBytes + index);
4005 }
4006 switch(index)
4007 {
4008 case GWW_ID:
4009 if(HIWORD(getWindowId()))
4010 dprintf(("WARNING: GWW_ID: discards high bits of 0x%08x!\n", getWindowId()));
4011 return (WORD)getWindowId();
4012
4013 case GWW_HWNDPARENT:
4014 dprintf(("WARNING: GWW_HWNDPARENT: discards high bits of 0x%08x!\n", GetParent()));
4015 return (WORD) GetParent();
4016
4017 case GWW_HINSTANCE:
4018 if (HIWORD(hInstance))
4019 dprintf(("WARNING: GWW_HINSTANCE: discards high bits of 0x%08x!\n", hInstance));
4020 return (WORD)hInstance;
4021 }
4022
4023 dprintf(("WARNING: GetWindowWord %x %d returned %x INVALID index!", getWindowHandle(), index));
4024 SetLastError(ERROR_INVALID_INDEX); //verified in NT4, SP6
4025 return 0;
4026}
4027//******************************************************************************
4028// Win32BaseWindow::setVisibleRgnNotifyProc
4029//
4030// Sets the visible region change notification handler. Called when
4031// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4032//
4033// Parameters:
4034// VISRGN_NOTIFY_PROC lpNotifyProc - notification handler
4035// DWORD dwUserData - caller supplied parameter for handler invocations
4036//
4037// Returns:
4038// TRUE - Success
4039// FALSE - Failure
4040//
4041//******************************************************************************
4042BOOL Win32BaseWindow::setVisibleRgnNotifyProc(VISRGN_NOTIFY_PROC lpNotifyProc, DWORD dwUserData)
4043{
4044 lpVisRgnNotifyProc = lpNotifyProc;
4045 dwVisRgnNotifyParam = dwUserData;
4046 return TRUE;
4047}
4048//******************************************************************************
4049// Win32BaseWindow::callVisibleRgnNotifyProc
4050//
4051// Call the visible region change notification handler. Called when
4052// the window receives a WM_VRNDISABLED or WM_VRNENABLED message (PM).
4053//
4054// Parameters:
4055// BOOL fDrawingAllowed - drawing is allowed or not
4056//
4057// Returns:
4058// TRUE - Success
4059// FALSE - Failure
4060//
4061//******************************************************************************
4062void Win32BaseWindow::callVisibleRgnNotifyProc(BOOL fDrawingAllowed)
4063{
4064 if(fDrawingAllowed) {
4065 fWindowLocked = TRUE;
4066 }
4067 else {
4068 fWindowLocked = FALSE;
4069 }
4070 if(lpVisRgnNotifyProc) {
4071 lpVisRgnNotifyProc(getWindowHandle(), fDrawingAllowed, dwVisRgnNotifyParam);
4072 }
4073}
4074//******************************************************************************
4075// Win32BaseWindow::queryOpenDCs
4076//
4077// Return the DCs that are currently open for this window
4078//
4079// Parameters:
4080// HDC *phdcWindow - pointer to HDC array (IN)
4081// int chdcWindow - size of HDC array (IN)
4082// int *pnrdcs - number of HDCs returned (OUT)
4083//
4084// Returns:
4085// TRUE - Success
4086// FALSE - Failure
4087//
4088//******************************************************************************
4089BOOL Win32BaseWindow::queryOpenDCs(HDC *phdcWindow, int chdcWindow, int *pnrdcs)
4090{
4091 if(nrOpenDCs == 0) return FALSE;
4092
4093 if(chdcWindow < nrOpenDCs) {
4094 DebugInt3();
4095 return FALSE;
4096 }
4097
4098 lock(&critsect);
4099 int j = 0;
4100 for(int i=0;i<MAX_OPENDCS && j<nrOpenDCs;i++) {
4101 if(hdcWindow[i] != 0) {
4102 phdcWindow[j] = hdcWindow[i];
4103 j++;
4104 }
4105 }
4106 unlock(&critsect);
4107 *pnrdcs = nrOpenDCs;
4108 return TRUE;
4109}
4110//******************************************************************************
4111// Win32BaseWindow::addOpenDC
4112//
4113// Add DC to list of open DCS
4114//
4115// Parameters:
4116// HDC hdc - HDC to be added to our list of open DCs
4117//
4118// Returns:
4119//
4120//******************************************************************************
4121void Win32BaseWindow::addOpenDC(HDC hdc)
4122{
4123 lock(&critsect);
4124 int i;
4125 for(i=0;i<MAX_OPENDCS;i++) {
4126 if(hdcWindow[i] == 0) {
4127 hdcWindow[i] = hdc;
4128 break;
4129 }
4130 }
4131 unlock(&critsect);
4132 if(i == MAX_OPENDCS) {
4133 dprintf(("Open DCs:"));
4134 for(int i=0;i<MAX_OPENDCS;i++) {
4135 dprintf(("Window %x DC %x", WindowFromDC(hdcWindow[i]), hdcWindow[i]));
4136 }
4137 DebugInt3(); //no room!
4138 return;
4139 }
4140
4141 dprintf2(("Win32BaseWindow::addOpenDC %x %x %d", getWindowHandle(), hdc, nrOpenDCs+1));
4142 nrOpenDCs++;
4143}
4144//******************************************************************************
4145// Win32BaseWindow::removeOpenDC
4146//
4147// Remove DC from list of open DCS
4148//
4149// Parameters:
4150// HDC hdc - HDC to be removed from our list of open DCs
4151//
4152// Returns:
4153//
4154//******************************************************************************
4155void Win32BaseWindow::removeOpenDC(HDC hdc)
4156{
4157 if(nrOpenDCs == 0) {
4158 dprintf(("Win32BaseWindow::removeOpenDC %x hdc %x not found!! (1)", getWindowHandle(), hdc));
4159 //Some applications call ReleaseDC before EndPaint
4160// DebugInt3();
4161 return;
4162 }
4163 lock(&critsect);
4164 int i;
4165 for(i=0;i<MAX_OPENDCS;i++) {
4166 if(hdcWindow[i] == hdc) {
4167 hdcWindow[i] = 0;
4168 break;
4169 }
4170 }
4171 unlock(&critsect);
4172 if(i == MAX_OPENDCS) {
4173 dprintf(("Win32BaseWindow::removeOpenDC hdc %x not found!!", hdc));
4174 DebugInt3(); //not found
4175 return;
4176 }
4177 dprintf2(("Win32BaseWindow::removeOpenDC %x %x", getWindowHandle(), hdc, nrOpenDCs-1));
4178 nrOpenDCs--;
4179}
4180//******************************************************************************
4181//Locates window in linked list and increases reference count (if found)
4182//Window object must be unreferenced after usage
4183//******************************************************************************
4184Win32BaseWindow *Win32BaseWindow::GetWindowFromHandle(HWND hwnd)
4185{
4186 Win32BaseWindow *window;
4187
4188////TODO: temporary workaround for crashes in Opera (pmwinx; releasesemaphore)
4189//// while browsing
4190//// Not thread safe now!
4191//// lock(&critsect);
4192 if(HwGetWindowHandleData(hwnd, (DWORD *)&window) == TRUE) {
4193 if(window) {
4194//// dprintf(("addRef %x; refcount %d", hwnd, window->getRefCount()+1));
4195 window->addRef();
4196 }
4197//// unlock(&critsect);
4198 return window;
4199 }
4200//// unlock(&critsect);
4201// dprintf2(("Win32BaseWindow::GetWindowFromHandle: not a win32 window %x", hwnd));
4202 return NULL;
4203}
4204//******************************************************************************
4205//Locates window in linked list and increases reference count (if found)
4206//Window object must be unreferenced after usage
4207//******************************************************************************
4208Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2Handle(HWND hwndOS2)
4209{
4210 DWORD magic;
4211 HWND hwnd;
4212
4213 if(hwndOS2 == OSLIB_HWND_DESKTOP)
4214 {
4215 windowDesktop->addRef();
4216 return windowDesktop;
4217 }
4218
4219 hwnd = (HWND)OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32WNDPTR);
4220 magic = OSLibWinGetWindowULong(hwndOS2, OFFSET_WIN32PM_MAGIC);
4221
4222 if(hwnd && CheckMagicDword(magic)) {
4223 return GetWindowFromHandle(hwnd);
4224 }
4225// dprintf2(("Win32BaseWindow::GetWindowFromOS2Handle: not an Odin os2 window %x", hwndOS2));
4226
4227 //Now check if it's a fake window
4228 Win32FakeWindow *window = Win32FakeWindow::GetWindowFromOS2Handle(hwndOS2);
4229 if(window) {
4230 return window;
4231 }
4232 return 0;
4233}
4234//******************************************************************************
4235//Locates window in linked list and increases reference count (if found)
4236//Window object must be unreferenced after usage
4237//******************************************************************************
4238Win32BaseWindow *Win32BaseWindow::GetWindowFromOS2FrameHandle(HWND hwnd)
4239{
4240 return GetWindowFromOS2Handle(OSLibWinWindowFromID(hwnd,OSLIB_FID_CLIENT));
4241}
4242//******************************************************************************
4243//******************************************************************************
4244HWND WIN32API Win32ToOS2Handle(HWND hwnd)
4245{
4246 HWND hwndOS2;
4247
4248 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4249
4250 if(window) {
4251 hwndOS2 = window->getOS2WindowHandle();
4252 RELEASE_WNDOBJ(window);
4253 return hwndOS2;
4254 }
4255// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4256 return hwnd;
4257}
4258//******************************************************************************
4259//******************************************************************************
4260HWND WIN32API Win32ToOS2FrameHandle(HWND hwnd)
4261{
4262 HWND hwndOS2;
4263
4264 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromHandle(hwnd);
4265
4266 if(window) {
4267 hwndOS2 = window->getOS2FrameWindowHandle();
4268 RELEASE_WNDOBJ(window);
4269 return hwndOS2;
4270 }
4271// dprintf2(("Win32BaseWindow::Win32ToOS2Handle: not a win32 window %x", hwnd));
4272 return hwnd;
4273}
4274//******************************************************************************
4275//******************************************************************************
4276HWND WIN32API OS2ToWin32Handle(HWND hwnd)
4277{
4278 Win32BaseWindow *window = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
4279 HWND hwndWin32;
4280
4281 if(window) {
4282 hwndWin32 = window->getWindowHandle();
4283 RELEASE_WNDOBJ(window);
4284 return hwndWin32;
4285 }
4286 window = Win32BaseWindow::GetWindowFromOS2FrameHandle(hwnd);
4287 if(window) {
4288 hwndWin32 = window->getWindowHandle();
4289 RELEASE_WNDOBJ(window);
4290 return hwndWin32;
4291 }
4292
4293// dprintf2(("Win32BaseWindow::OS2ToWin32Handle: not a win32 window %x", hwnd));
4294 return 0;
4295// else return hwnd; //OS/2 window handle
4296}
4297#ifdef DEBUG
4298LONG Win32BaseWindow::addRef()
4299{
4300// dprintf2(("addRef %x %d", getWindowHandle(), getRefCount()+1));
4301 return GenericObject::addRef();
4302}
4303//******************************************************************************
4304//******************************************************************************
4305LONG Win32BaseWindow::release(const char *function, int line)
4306{
4307// dprintf2(("release %s %d %x %d", function, line, getWindowHandle(), getRefCount()-1));
4308 return GenericObject::release();
4309}
4310#endif
4311//******************************************************************************
4312//******************************************************************************
4313GenericObject *Win32BaseWindow::windows = NULL;
4314VMutex Win32BaseWindow::critsect;
4315
4316//******************************************************************************
4317//******************************************************************************
4318#ifdef DEBUG
4319void PrintWindowStyle(DWORD dwStyle, DWORD dwExStyle)
4320{
4321 char style[256] = "";
4322 char exstyle[256] = "";
4323
4324 /* Window styles */
4325 if(dwStyle & WS_CHILD)
4326 strcat(style, "WS_CHILD ");
4327 if(dwStyle & WS_POPUP)
4328 strcat(style, "WS_POPUP ");
4329 if(dwStyle & WS_VISIBLE)
4330 strcat(style, "WS_VISIBLE ");
4331 if(dwStyle & WS_DISABLED)
4332 strcat(style, "WS_DISABLED ");
4333 if(dwStyle & WS_CLIPSIBLINGS)
4334 strcat(style, "WS_CLIPSIBLINGS ");
4335 if(dwStyle & WS_CLIPCHILDREN)
4336 strcat(style, "WS_CLIPCHILDREN ");
4337 if(dwStyle & WS_MAXIMIZE)
4338 strcat(style, "WS_MAXIMIZE ");
4339 if(dwStyle & WS_MINIMIZE)
4340 strcat(style, "WS_MINIMIZE ");
4341 if(dwStyle & WS_GROUP)
4342 strcat(style, "WS_GROUP ");
4343 if(dwStyle & WS_TABSTOP)
4344 strcat(style, "WS_TABSTOP ");
4345
4346 if((dwStyle & WS_CAPTION) == WS_CAPTION)
4347 strcat(style, "WS_CAPTION ");
4348 if(dwStyle & WS_DLGFRAME)
4349 strcat(style, "WS_DLGFRAME ");
4350 if(dwStyle & WS_BORDER)
4351 strcat(style, "WS_BORDER ");
4352
4353 if(dwStyle & WS_VSCROLL)
4354 strcat(style, "WS_VSCROLL ");
4355 if(dwStyle & WS_HSCROLL)
4356 strcat(style, "WS_HSCROLL ");
4357 if(dwStyle & WS_SYSMENU)
4358 strcat(style, "WS_SYSMENU ");
4359 if(dwStyle & WS_THICKFRAME)
4360 strcat(style, "WS_THICKFRAME ");
4361 if(dwStyle & WS_MINIMIZEBOX)
4362 strcat(style, "WS_MINIMIZEBOX ");
4363 if(dwStyle & WS_MAXIMIZEBOX)
4364 strcat(style, "WS_MAXIMIZEBOX ");
4365
4366 if(dwExStyle & WS_EX_DLGMODALFRAME)
4367 strcat(exstyle, "WS_EX_DLGMODALFRAME ");
4368 if(dwExStyle & WS_EX_ACCEPTFILES)
4369 strcat(exstyle, "WS_EX_ACCEPTFILES ");
4370 if(dwExStyle & WS_EX_NOPARENTNOTIFY)
4371 strcat(exstyle, "WS_EX_NOPARENTNOTIFY ");
4372 if(dwExStyle & WS_EX_TOPMOST)
4373 strcat(exstyle, "WS_EX_TOPMOST ");
4374 if(dwExStyle & WS_EX_TRANSPARENT)
4375 strcat(exstyle, "WS_EX_TRANSPARENT ");
4376
4377 if(dwExStyle & WS_EX_MDICHILD)
4378 strcat(exstyle, "WS_EX_MDICHILD ");
4379 if(dwExStyle & WS_EX_TOOLWINDOW)
4380 strcat(exstyle, "WS_EX_TOOLWINDOW ");
4381 if(dwExStyle & WS_EX_WINDOWEDGE)
4382 strcat(exstyle, "WS_EX_WINDOWEDGE ");
4383 if(dwExStyle & WS_EX_CLIENTEDGE)
4384 strcat(exstyle, "WS_EX_CLIENTEDGE ");
4385 if(dwExStyle & WS_EX_CONTEXTHELP)
4386 strcat(exstyle, "WS_EX_CONTEXTHELP ");
4387 if(dwExStyle & WS_EX_RIGHT)
4388 strcat(exstyle, "WS_EX_RIGHT ");
4389 if(dwExStyle & WS_EX_LEFT)
4390 strcat(exstyle, "WS_EX_LEFT ");
4391 if(dwExStyle & WS_EX_RTLREADING)
4392 strcat(exstyle, "WS_EX_RTLREADING ");
4393 if(dwExStyle & WS_EX_LTRREADING)
4394 strcat(exstyle, "WS_EX_LTRREADING ");
4395 if(dwExStyle & WS_EX_LEFTSCROLLBAR)
4396 strcat(exstyle, "WS_EX_LEFTSCROLLBAR ");
4397 if(dwExStyle & WS_EX_RIGHTSCROLLBAR)
4398 strcat(exstyle, "WS_EX_RIGHTSCROLLBAR ");
4399 if(dwExStyle & WS_EX_CONTROLPARENT)
4400 strcat(exstyle, "WS_EX_CONTROLPARENT ");
4401 if(dwExStyle & WS_EX_STATICEDGE)
4402 strcat(exstyle, "WS_EX_STATICEDGE ");
4403 if(dwExStyle & WS_EX_APPWINDOW)
4404 strcat(exstyle, "WS_EX_APPWINDOW ");
4405
4406 dprintf(("Window style: %x %s", dwStyle, style));
4407 dprintf(("Window exStyle: %x %s", dwExStyle, exstyle));
4408}
4409#endif
4410//******************************************************************************
4411//******************************************************************************
Note: See TracBrowser for help on using the repository browser.