2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include <X11/Xatom.h>
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
24 #include "nonclient.h"
29 #include "shm_main_blk.h"
31 #include "clipboard.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
39 static WND *pWndDesktop = NULL;
41 static HWND hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern HCURSOR16 CURSORICON_IconToCursor(HICON16);
47 extern HWND32 CARET_GetHwnd(void);
48 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
49 extern void WINPOS_CheckActive(HWND32);
51 /***********************************************************************
54 * Return a pointer to the WND structure corresponding to a HWND.
56 WND * WIN_FindWndPtr( HWND32 hwnd )
60 if (!hwnd || HIWORD(hwnd)) return NULL;
61 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
62 if (ptr->dwMagic != WND_MAGIC) return NULL;
63 if (ptr->hwndSelf != hwnd)
65 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
66 hwnd, ptr->hwndSelf );
73 /***********************************************************************
76 * Dump the content of a window structure to stderr.
78 void WIN_DumpWindow( HWND32 hwnd )
84 if (!(ptr = WIN_FindWndPtr( hwnd )))
86 fprintf( stderr, "%04x is not a window handle\n", hwnd );
90 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
91 strcpy( className, "#NULL#" );
93 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
95 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
96 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
97 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
98 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
99 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
100 ptr->next, ptr->child, ptr->parent, ptr->owner,
101 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
102 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
103 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
104 ptr->text ? ptr->text : "",
105 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
106 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
107 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
108 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
109 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
111 if (ptr->class->cbWndExtra)
113 fprintf( stderr, "extra bytes:" );
114 for (i = 0; i < ptr->class->cbWndExtra; i++)
115 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
116 fprintf( stderr, "\n" );
118 fprintf( stderr, "\n" );
122 /***********************************************************************
125 * Walk the windows tree and print each window on stderr.
127 void WIN_WalkWindows( HWND32 hwnd, int indent )
132 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
135 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
139 if (!indent) /* first time around */
140 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
141 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
145 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
147 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
149 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
150 (DWORD)ptr, ptr->hmemTaskQ, className,
151 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
153 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
159 /***********************************************************************
162 * Return the X window associated to a window.
164 Window WIN_GetXWindow( HWND32 hwnd )
166 WND *wndPtr = WIN_FindWndPtr( hwnd );
167 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
168 return wndPtr ? wndPtr->window : 0;
172 /***********************************************************************
175 * Remove a window from the siblings linked list.
177 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
179 WND *wndPtr, **ppWnd;
181 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
182 ppWnd = &wndPtr->parent->child;
183 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
184 *ppWnd = wndPtr->next;
189 /***********************************************************************
192 * Insert a window into the siblings linked list.
193 * The window is inserted after the specified window, which can also
194 * be specified as HWND_TOP or HWND_BOTTOM.
196 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
198 WND *wndPtr, **ppWnd;
200 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
202 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
204 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
205 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
206 while (*ppWnd) ppWnd = &(*ppWnd)->next;
208 else /* Normal case */
210 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
211 if (!afterPtr) return FALSE;
212 ppWnd = &afterPtr->next;
214 wndPtr->next = *ppWnd;
220 /***********************************************************************
221 * WIN_FindWinToRepaint
223 * Find a window that needs repaint.
225 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
228 WND *pWnd = pWndDesktop;
230 /* Note: the desktop window never gets WM_PAINT messages
231 * The real reason why is because Windows DesktopWndProc
232 * does ValidateRgn inside WM_ERASEBKGND handler.
235 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
237 for ( ; pWnd ; pWnd = pWnd->next )
239 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
241 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
245 if ((pWnd->hmemTaskQ == hQueue) &&
246 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
249 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
255 hwndRet = pWnd->hwndSelf;
257 /* look among siblings if we got a transparent window */
258 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
259 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
263 if (pWnd) hwndRet = pWnd->hwndSelf;
264 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
269 /***********************************************************************
270 * WIN_SendParentNotify
272 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
273 * the window has the WS_EX_NOPARENTNOTIFY style.
275 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
277 LPPOINT16 lppt = (LPPOINT16)&lValue;
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
279 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
281 /* if lValue contains cursor coordinates they have to be
282 * mapped to the client area of parent window */
284 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
288 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
289 !(wndPtr->dwStyle & WS_CHILD)) break;
293 lppt->x += wndPtr->rectClient.left;
294 lppt->y += wndPtr->rectClient.top;
297 wndPtr = wndPtr->parent;
298 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
299 MAKEWPARAM( event, idChild ), lValue );
304 /***********************************************************************
307 * Destroy storage associated to a window. "Internals" p.358
309 static void WIN_DestroyWindow( WND* wndPtr )
311 HWND hwnd = wndPtr->hwndSelf;
316 DDE_DestroyWindow(wndPtr->hwndSelf);
317 #endif /* CONFIG_IPC */
319 /* free child windows */
321 pNext = wndPtr->child;
322 while( (pWnd = pNext) )
325 WIN_DestroyWindow( pWnd );
328 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
330 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
332 WINPOS_CheckActive( hwnd );
333 if( hwnd == GetCapture32()) ReleaseCapture();
335 /* free resources associated with the window */
337 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
338 PROPERTY_RemoveWindowProps( wndPtr );
340 wndPtr->dwMagic = 0; /* Mark it as invalid */
341 wndPtr->hwndSelf = 0;
343 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
345 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
346 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
349 /* toss stale messages from the queue */
351 if( wndPtr->hmemTaskQ )
354 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
356 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
357 QUEUE_RemoveMsg(msgQ, pos);
358 wndPtr->hmemTaskQ = 0;
361 if (!(wndPtr->dwStyle & WS_CHILD))
362 if (wndPtr->wIDmenu) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
363 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
364 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
365 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
367 WINPROC_FreeProc( wndPtr->winproc );
369 wndPtr->class->cWindows--;
370 wndPtr->class = NULL;
372 USER_HEAP_FREE( hwnd );
376 /***********************************************************************
377 * WIN_DestroyQueueWindows
379 void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue )
386 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
387 else WIN_DestroyQueueWindows( wnd->child, hQueue );
393 /***********************************************************************
394 * WIN_CreateDesktopWindow
396 * Create the desktop window.
398 BOOL32 WIN_CreateDesktopWindow(void)
403 dprintf_win(stddeb,"Creating desktop window\n");
405 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
408 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
409 if (!hwndDesktop) return FALSE;
410 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
412 pWndDesktop->next = NULL;
413 pWndDesktop->child = NULL;
414 pWndDesktop->parent = NULL;
415 pWndDesktop->owner = NULL;
416 pWndDesktop->class = class;
417 pWndDesktop->winproc = NULL;
418 pWndDesktop->dwMagic = WND_MAGIC;
419 pWndDesktop->hwndSelf = hwndDesktop;
420 pWndDesktop->hInstance = 0;
421 pWndDesktop->rectWindow.left = 0;
422 pWndDesktop->rectWindow.top = 0;
423 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
424 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
425 pWndDesktop->rectClient = pWndDesktop->rectWindow;
426 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
427 pWndDesktop->ptIconPos.x = -1;
428 pWndDesktop->ptIconPos.y = -1;
429 pWndDesktop->ptMaxPos.x = -1;
430 pWndDesktop->ptMaxPos.y = -1;
431 pWndDesktop->text = NULL;
432 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
433 pWndDesktop->hrgnUpdate = 0;
434 pWndDesktop->hwndLastActive = hwndDesktop;
435 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
437 pWndDesktop->dwExStyle = 0;
438 pWndDesktop->dce = NULL;
439 pWndDesktop->pVScroll = NULL;
440 pWndDesktop->pHScroll = NULL;
441 pWndDesktop->pProp = NULL;
442 pWndDesktop->wIDmenu = 0;
443 pWndDesktop->flags = 0;
444 pWndDesktop->window = rootWindow;
445 pWndDesktop->hSysMenu = 0;
446 pWndDesktop->userdata = 0;
448 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
449 EVENT_RegisterWindow( pWndDesktop );
450 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
451 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
456 /***********************************************************************
459 * Implementation of CreateWindowEx().
461 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
466 HWND16 hwnd, hwndLinkAfter;
467 POINT16 maxSize, maxPos, minTrack, maxTrack;
470 dprintf_win( stddeb, "CreateWindowEx: " );
471 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
472 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
473 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
474 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
476 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
477 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
478 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
480 /* Find the parent window */
484 /* Make sure parent is valid */
485 if (!IsWindow( cs->hwndParent ))
487 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
491 else if (cs->style & WS_CHILD)
493 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
494 return 0; /* WS_CHILD needs a parent */
497 /* Find the window class */
499 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
500 GetExePtr(cs->hInstance) )))
503 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
504 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
508 /* Fix the coordinates */
510 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
511 if (cs->cx == CW_USEDEFAULT32)
513 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
521 /* Create the window structure */
523 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
524 - sizeof(wndPtr->wExtra) )))
526 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
530 /* Fill the window structure */
532 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
534 wndPtr->child = NULL;
536 if (cs->style & WS_CHILD)
538 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
539 wndPtr->owner = NULL;
543 wndPtr->parent = pWndDesktop;
544 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
545 wndPtr->owner = NULL;
547 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
551 wndPtr->class = classPtr;
552 wndPtr->winproc = NULL;
553 wndPtr->dwMagic = WND_MAGIC;
554 wndPtr->hwndSelf = hwnd;
555 wndPtr->hInstance = cs->hInstance;
556 wndPtr->ptIconPos.x = -1;
557 wndPtr->ptIconPos.y = -1;
558 wndPtr->ptMaxPos.x = -1;
559 wndPtr->ptMaxPos.y = -1;
561 wndPtr->hmemTaskQ = GetTaskQueue(0);
562 wndPtr->hrgnUpdate = 0;
563 wndPtr->hwndLastActive = hwnd;
564 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
565 wndPtr->dwExStyle = cs->dwExStyle;
568 wndPtr->pVScroll = NULL;
569 wndPtr->pHScroll = NULL;
570 wndPtr->pProp = NULL;
571 wndPtr->hSysMenu = MENU_GetDefSysMenu();
572 wndPtr->userdata = 0;
574 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
576 /* Call the WH_CBT hook */
578 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
580 if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
582 CBT_CREATEWND16* cbtc;
584 if ((cbtc = SEGPTR_NEW(CBT_CREATEWND16)))
586 /* Dummy message params to use WINPROC_MapMsg functions */
591 /* Map the CREATESTRUCT to 16-bit format */
594 WINPROC_MapMsg32WTo16( WM_CREATE, 0, &msg, &wparam, &lparam );
596 WINPROC_MapMsg32ATo16( WM_CREATE, 0, &msg, &wparam, &lparam );
597 cbtc->lpcs = (CREATESTRUCT16 *)lparam;
598 cbtc->hwndInsertAfter = hwndLinkAfter;
599 wmcreate = !HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, hwnd,
600 (LPARAM)SEGPTR_GET(cbtc) );
601 WINPROC_UnmapMsg32ATo16( WM_CREATE, 0, lparam );
605 dprintf_win(stddeb,"CreateWindowEx: CBT-hook returned 0\n" );
606 USER_HEAP_FREE( hwnd );
612 /* Set the window procedure */
614 classPtr->cWindows++;
615 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
617 /* Correct the window style */
619 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
621 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
622 wndPtr->flags |= WIN_NEED_SIZE;
624 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
626 /* Get class or window DC if needed */
628 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
629 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
630 else wndPtr->dce = NULL;
632 /* Insert the window in the linked list */
634 WIN_LinkWindow( hwnd, hwndLinkAfter );
636 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
638 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
640 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
641 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
642 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
643 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
644 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
646 if (cs->cx <= 0) cs->cx = 1;
647 if (cs->cy <= 0) cs->cy = 1;
649 wndPtr->rectWindow.left = cs->x;
650 wndPtr->rectWindow.top = cs->y;
651 wndPtr->rectWindow.right = cs->x + cs->cx;
652 wndPtr->rectWindow.bottom = cs->y + cs->cy;
653 wndPtr->rectClient = wndPtr->rectWindow;
654 wndPtr->rectNormal = wndPtr->rectWindow;
656 /* Create the X window (only for top-level windows, and then only */
657 /* when there's no desktop window) */
659 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
661 XSetWindowAttributes win_attr;
662 Atom XA_WM_DELETE_WINDOW;
664 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
665 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
667 win_attr.event_mask = ExposureMask | KeyPressMask |
668 KeyReleaseMask | PointerMotionMask |
669 ButtonPressMask | ButtonReleaseMask |
670 FocusChangeMask | StructureNotifyMask;
671 win_attr.override_redirect = FALSE;
672 wndPtr->flags |= WIN_MANAGED;
676 win_attr.event_mask = ExposureMask | KeyPressMask |
677 KeyReleaseMask | PointerMotionMask |
678 ButtonPressMask | ButtonReleaseMask |
679 FocusChangeMask | StructureNotifyMask;
680 win_attr.override_redirect = TRUE;
682 win_attr.colormap = COLOR_GetColormap();
683 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
684 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
685 win_attr.cursor = CURSORICON_XCursor;
686 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
687 cs->cx, cs->cy, 0, CopyFromParent,
688 InputOutput, CopyFromParent,
689 CWEventMask | CWOverrideRedirect |
690 CWColormap | CWCursor | CWSaveUnder |
691 CWBackingStore, &win_attr );
692 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
694 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
696 if ((wndPtr->flags & WIN_MANAGED) &&
697 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
699 XSizeHints* size_hints = XAllocSizeHints();
703 size_hints->min_width = size_hints->max_width = cs->cx;
704 size_hints->min_height = size_hints->max_height = cs->cy;
705 size_hints->flags = (PSize | PMinSize | PMaxSize);
706 XSetWMSizeHints( display, wndPtr->window, size_hints,
707 XA_WM_NORMAL_HINTS );
712 if (cs->hwndParent) /* Get window owner */
714 Window win = WIN_GetXWindow( cs->hwndParent );
715 if (win) XSetTransientForHint( display, wndPtr->window, win );
717 EVENT_RegisterWindow( wndPtr );
720 /* Set the window menu */
722 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
724 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
727 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
728 if (classPtr->menuNameA)
729 cs->hMenu = HIWORD(classPtr->menuNameA) ?
730 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
731 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
733 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
734 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
737 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
739 else wndPtr->wIDmenu = (UINT)cs->hMenu;
741 /* Send the WM_CREATE message */
745 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
748 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
749 NULL, NULL, 0, &wndPtr->rectClient );
750 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
755 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
758 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
759 NULL, NULL, 0, &wndPtr->rectClient );
760 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
766 /* Abort window creation */
767 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
768 WIN_UnlinkWindow( hwnd );
769 WIN_DestroyWindow( wndPtr );
773 /* Send the size messages */
775 if (!(wndPtr->flags & WIN_NEED_SIZE))
778 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
779 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
780 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
781 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
782 wndPtr->rectClient.top ));
785 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
786 if (!IsWindow(hwnd)) return 0;
788 /* Show the window, maximizing or minimizing if needed */
790 if (wndPtr->dwStyle & WS_MINIMIZE)
792 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
794 wndPtr->dwStyle &= ~WS_MAXIMIZE;
795 WINPOS_FindIconPos( hwnd );
796 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
797 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
798 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
800 else if (wndPtr->dwStyle & WS_MAXIMIZE)
802 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
804 POINT16 maxSize, maxPos, minTrack, maxTrack;
805 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
806 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
807 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
810 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
812 /* Call WH_SHELL hook */
814 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
815 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
817 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
822 /***********************************************************************
823 * CreateWindow16 (USER.41)
825 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
826 DWORD style, INT16 x, INT16 y, INT16 width,
827 INT16 height, HWND16 parent, HMENU16 menu,
828 HINSTANCE16 instance, LPVOID data )
830 return CreateWindowEx16( 0, className, windowName, style,
831 x, y, width, height, parent, menu, instance, data );
835 /***********************************************************************
836 * CreateWindowEx16 (USER.452)
838 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
839 DWORD style, INT16 x, INT16 y, INT16 width,
840 INT16 height, HWND16 parent, HMENU16 menu,
841 HINSTANCE16 instance, LPVOID data )
846 /* Find the class atom */
848 if (!(classAtom = GlobalFindAtom32A( className )))
850 fprintf( stderr, "CreateWindowEx16: bad class name " );
851 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
852 else fprintf( stderr, "'%s'\n", className );
856 /* Fix the coordinates */
858 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
859 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
860 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
861 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
863 /* Create the window */
865 cs.lpCreateParams = data;
866 cs.hInstance = (HINSTANCE32)instance;
867 cs.hMenu = (HMENU32)menu;
868 cs.hwndParent = (HWND32)parent;
870 cs.lpszName = windowName;
871 cs.lpszClass = className;
872 cs.dwExStyle = exStyle;
873 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
877 /***********************************************************************
878 * CreateWindowEx32A (USER32.82)
880 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
881 DWORD style, INT32 x, INT32 y, INT32 width,
882 INT32 height, HWND32 parent, HMENU32 menu,
883 HINSTANCE32 instance, LPVOID data )
888 /* Find the class atom */
890 if (!(classAtom = GlobalFindAtom32A( className )))
892 fprintf( stderr, "CreateWindowEx32A: bad class name " );
893 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
894 else fprintf( stderr, "'%s'\n", className );
898 /* Create the window */
900 cs.lpCreateParams = data;
901 cs.hInstance = instance;
903 cs.hwndParent = parent;
909 cs.lpszName = windowName;
910 cs.lpszClass = className;
911 cs.dwExStyle = exStyle;
912 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
916 /***********************************************************************
917 * CreateWindowEx32W (USER32.83)
919 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
920 DWORD style, INT32 x, INT32 y, INT32 width,
921 INT32 height, HWND32 parent, HMENU32 menu,
922 HINSTANCE32 instance, LPVOID data )
927 /* Find the class atom */
929 if (!(classAtom = GlobalFindAtom32W( className )))
931 if (HIWORD(className))
933 LPSTR cn = STRING32_DupUniToAnsi(className);
934 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
938 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
942 /* Create the window */
944 cs.lpCreateParams = data;
945 cs.hInstance = instance;
947 cs.hwndParent = parent;
953 cs.lpszName = windowName;
954 cs.lpszClass = className;
955 cs.dwExStyle = exStyle;
956 /* Note: we rely on the fact that CREATESTRUCT32A and */
957 /* CREATESTRUCT32W have the same layout. */
958 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
962 /***********************************************************************
965 static void WIN_CheckFocus( WND* pWnd )
967 if( GetFocus16() == pWnd->hwndSelf )
968 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
971 /***********************************************************************
974 static void WIN_SendDestroyMsg( WND* pWnd )
978 WIN_CheckFocus(pWnd);
980 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
981 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
983 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
985 if( !IsWindow(pWnd->hwndSelf) )
987 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
991 pChild = pWnd->child;
994 WIN_SendDestroyMsg( pChild );
995 pChild = pChild->next;
997 WIN_CheckFocus(pWnd);
1001 /***********************************************************************
1002 * DestroyWindow (USER.53)
1004 BOOL DestroyWindow( HWND hwnd )
1008 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
1010 /* Initialization */
1012 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1013 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1017 if( HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1020 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1022 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1023 /* FIXME: clean up palette - see "Internals" p.352 */
1026 if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1027 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1028 if( !IsWindow(hwnd) ) return TRUE;
1030 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1032 /* Hide the window */
1034 if (wndPtr->dwStyle & WS_VISIBLE)
1036 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1037 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
1038 ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1039 if( !IsWindow(hwnd) ) return TRUE;
1042 /* Recursively destroy owned windows */
1044 if( !(wndPtr->dwStyle & WS_CHILD) )
1048 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1051 if (siblingPtr->owner == wndPtr)
1052 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1055 siblingPtr->owner = NULL;
1056 siblingPtr = siblingPtr->next;
1058 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1062 WINPOS_ActivateOtherWindow(wndPtr);
1064 if( wndPtr->owner &&
1065 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1066 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1069 /* Send destroy messages */
1071 WIN_SendDestroyMsg( wndPtr );
1072 if( !IsWindow(hwnd) ) return TRUE;
1074 /* Unlink now so we won't bother with the children later on */
1076 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1078 /* Destroy the window storage */
1080 WIN_DestroyWindow( wndPtr );
1085 /***********************************************************************
1086 * CloseWindow (USER.43)
1088 BOOL CloseWindow(HWND hWnd)
1090 WND * wndPtr = WIN_FindWndPtr(hWnd);
1091 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
1092 ShowWindow(hWnd, SW_MINIMIZE);
1097 /***********************************************************************
1098 * OpenIcon (USER.44)
1100 BOOL OpenIcon(HWND hWnd)
1102 if (!IsIconic(hWnd)) return FALSE;
1103 ShowWindow(hWnd, SW_SHOWNORMAL);
1108 /***********************************************************************
1111 * Implementation of FindWindow() and FindWindowEx().
1113 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1117 CLASS *pClass = NULL;
1121 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1124 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1126 else if (pWnd->parent != pWndDesktop) return 0;
1131 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1134 if (!pWnd) return 0;
1136 /* For a child window, all siblings will have the same hInstance, */
1137 /* so we can look for the class once and for all. */
1139 if (className && (pWnd->dwStyle & WS_CHILD))
1141 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1145 for ( ; pWnd; pWnd = pWnd->next)
1147 if (className && !(pWnd->dwStyle & WS_CHILD))
1149 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1150 continue; /* Skip this window */
1152 if (pClass && (pWnd->class != pClass))
1153 continue; /* Not the right class */
1155 /* Now check the title */
1157 if (!title) return pWnd->hwndSelf;
1158 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1165 /***********************************************************************
1166 * FindWindow16 (USER.50)
1168 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1170 return FindWindowEx16( 0, 0, className, title );
1174 /***********************************************************************
1175 * FindWindowEx16 (USER.427)
1177 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1178 SEGPTR className, LPCSTR title )
1184 /* If the atom doesn't exist, then no class */
1185 /* with this name exists either. */
1186 if (!(atom = GlobalFindAtom16( className ))) return 0;
1188 return WIN_FindWindow( parent, child, atom, title );
1192 /***********************************************************************
1193 * FindWindow32A (USER32.197)
1195 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1197 return FindWindowEx32A( 0, 0, className, title );
1201 /***********************************************************************
1202 * FindWindowEx32A (USER32.198)
1204 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1205 LPCSTR className, LPCSTR title )
1211 /* If the atom doesn't exist, then no class */
1212 /* with this name exists either. */
1213 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1215 return WIN_FindWindow( 0, 0, atom, title );
1219 /***********************************************************************
1220 * FindWindowEx32W (USER32.199)
1222 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1223 LPCWSTR className, LPCWSTR title )
1231 /* If the atom doesn't exist, then no class */
1232 /* with this name exists either. */
1233 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1235 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1236 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1237 if (buffer) free( buffer );
1242 /***********************************************************************
1243 * FindWindow32W (USER32.200)
1245 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1247 return FindWindowEx32W( 0, 0, className, title );
1251 /**********************************************************************
1254 WND *WIN_GetDesktop(void)
1260 /**********************************************************************
1261 * GetDesktopWindow16 (USER.286)
1263 HWND16 GetDesktopWindow16(void)
1265 return (HWND16)pWndDesktop->hwndSelf;
1269 /**********************************************************************
1270 * GetDesktopWindow32 (USER32.231)
1272 HWND32 GetDesktopWindow32(void)
1274 return pWndDesktop->hwndSelf;
1278 /**********************************************************************
1279 * GetDesktopHwnd (USER.278)
1281 * Exactly the same thing as GetDesktopWindow(), but not documented.
1282 * Don't ask me why...
1284 HWND16 GetDesktopHwnd(void)
1286 return (HWND16)pWndDesktop->hwndSelf;
1290 /*******************************************************************
1291 * EnableWindow (USER.34)
1293 BOOL EnableWindow( HWND hwnd, BOOL enable )
1297 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1298 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1301 wndPtr->dwStyle &= ~WS_DISABLED;
1302 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1305 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1307 /* Disable window */
1308 wndPtr->dwStyle |= WS_DISABLED;
1309 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1310 SetFocus32( 0 ); /* A disabled window can't have the focus */
1311 if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
1312 ReleaseCapture(); /* A disabled window can't capture the mouse */
1313 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1316 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1320 /***********************************************************************
1321 * IsWindowEnabled (USER.35) (USER32.348)
1323 BOOL IsWindowEnabled(HWND hWnd)
1327 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1328 return !(wndPtr->dwStyle & WS_DISABLED);
1332 /***********************************************************************
1333 * IsWindowUnicode (USER32.349)
1335 BOOL32 IsWindowUnicode( HWND32 hwnd )
1339 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1340 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1344 /**********************************************************************
1345 * GetWindowWord (USER.133) (USER32.313)
1347 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1349 WND * wndPtr = WIN_FindWndPtr( hwnd );
1350 if (!wndPtr) return 0;
1353 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1355 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1358 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1362 case GWW_ID: return wndPtr->wIDmenu;
1363 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1364 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1366 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1372 /**********************************************************************
1373 * WIN_GetWindowInstance
1375 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1377 WND * wndPtr = WIN_FindWndPtr( hwnd );
1378 if (!wndPtr) return (HINSTANCE16)0;
1379 return wndPtr->hInstance;
1383 /**********************************************************************
1384 * SetWindowWord (USER.134) (USER32.523)
1386 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1389 WND * wndPtr = WIN_FindWndPtr( hwnd );
1390 if (!wndPtr) return 0;
1393 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1395 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1398 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1402 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1403 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1405 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1414 /**********************************************************************
1417 * Helper function for GetWindowLong().
1419 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1422 WND * wndPtr = WIN_FindWndPtr( hwnd );
1423 if (!wndPtr) return 0;
1426 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1428 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1431 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1432 /* Special case for dialog window procedure */
1433 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1434 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1439 case GWL_USERDATA: return wndPtr->userdata;
1440 case GWL_STYLE: return wndPtr->dwStyle;
1441 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1442 case GWL_ID: return wndPtr->wIDmenu;
1443 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1445 case GWL_HWNDPARENT: return wndPtr->parent ?
1446 (HWND32)wndPtr->parent->hwndSelf : 0;
1447 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1449 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1455 /**********************************************************************
1458 * Helper function for SetWindowLong().
1460 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1461 WINDOWPROCTYPE type )
1464 WND * wndPtr = WIN_FindWndPtr( hwnd );
1465 if (!wndPtr) return 0;
1468 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1470 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1473 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1474 /* Special case for dialog window procedure */
1475 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1477 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1478 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1486 return SetWindowWord( hwnd, offset, (WORD)newval );
1488 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1489 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1492 ptr = &wndPtr->dwStyle;
1493 /* Some bits can't be changed this way */
1494 newval &= ~(WS_VISIBLE | WS_CHILD);
1495 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1497 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1498 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1500 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1509 /**********************************************************************
1510 * GetWindowLong16 (USER.135)
1512 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1514 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1518 /**********************************************************************
1519 * GetWindowLong32A (USER32.304)
1521 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1523 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1527 /**********************************************************************
1528 * GetWindowLong32W (USER32.305)
1530 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1532 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1536 /**********************************************************************
1537 * SetWindowLong16 (USER.136)
1539 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1541 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1545 /**********************************************************************
1546 * SetWindowLong32A (USER32.516)
1548 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1550 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1554 /**********************************************************************
1555 * SetWindowLong32W (USER32.517)
1557 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1559 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1563 /*******************************************************************
1564 * GetWindowText16 (USER.36)
1566 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1568 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1572 /*******************************************************************
1573 * GetWindowText32A (USER32.308)
1575 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1577 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1582 /*******************************************************************
1583 * GetWindowText32W (USER32.311)
1585 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1587 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1592 /*******************************************************************
1593 * SetWindowText16 (USER.37)
1595 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1597 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1601 /*******************************************************************
1602 * SetWindowText32A (USER32.)
1604 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1606 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1610 /*******************************************************************
1611 * SetWindowText32W (USER32.)
1613 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1615 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1619 /*******************************************************************
1620 * GetWindowTextLength (USER.38)
1622 int GetWindowTextLength(HWND hwnd)
1624 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1628 /*******************************************************************
1629 * IsWindow (USER.47) (USER32.347)
1631 BOOL16 IsWindow( HWND32 hwnd )
1633 WND * wndPtr = WIN_FindWndPtr( hwnd );
1634 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1638 /*****************************************************************
1639 * GetParent16 (USER.46)
1641 HWND16 GetParent16( HWND16 hwnd )
1643 return (HWND16)GetParent32( hwnd );
1647 /*****************************************************************
1648 * GetParent32 (USER32.277)
1650 HWND32 GetParent32( HWND32 hwnd )
1652 WND *wndPtr = WIN_FindWndPtr(hwnd);
1653 if (!wndPtr) return 0;
1654 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1655 return wndPtr ? wndPtr->hwndSelf : 0;
1659 /*****************************************************************
1662 * Get the top-level parent for a child window.
1664 HWND32 WIN_GetTopParent( HWND32 hwnd )
1666 WND *wndPtr = WIN_FindWndPtr( hwnd );
1667 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1668 return wndPtr ? wndPtr->hwndSelf : 0;
1672 /*****************************************************************
1673 * SetParent (USER.233)
1675 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1679 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1680 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1681 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1683 oldParent = wndPtr->parent->hwndSelf;
1685 WIN_UnlinkWindow(hwndChild);
1686 if (hwndNewParent) wndPtr->parent = pWndParent;
1687 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1689 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1696 /*******************************************************************
1699 BOOL IsChild( HWND parent, HWND child )
1701 WND * wndPtr = WIN_FindWndPtr( child );
1702 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1704 wndPtr = wndPtr->parent;
1705 if (wndPtr->hwndSelf == parent) return TRUE;
1711 /***********************************************************************
1712 * IsWindowVisible (USER.49) (USER32.350)
1714 BOOL IsWindowVisible( HWND hwnd )
1716 WND *wndPtr = WIN_FindWndPtr( hwnd );
1717 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1719 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1720 wndPtr = wndPtr->parent;
1722 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1725 /***********************************************************************
1726 * WIN_IsWindowDrawable
1728 * hwnd is drawable when it is visible, all parents are not
1729 * minimized, and it is itself not minimized unless we are
1730 * trying to draw icon and the default class icon is set.
1732 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1734 HWND hwnd= wnd->hwndSelf;
1739 if( wnd->dwStyle & WS_MINIMIZE )
1740 if( wnd->hwndSelf != hwnd ) break;
1741 else if( icon && wnd->class->hIcon ) break;
1743 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1744 wnd = wnd->parent; }
1745 return (!wnd && yes);
1748 /*******************************************************************
1749 * GetTopWindow (USER.229)
1751 HWND GetTopWindow( HWND hwnd )
1753 WND * wndPtr = WIN_FindWndPtr( hwnd );
1754 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1759 /*******************************************************************
1760 * GetWindow (USER.262)
1762 HWND GetWindow( HWND hwnd, WORD rel )
1764 WND * wndPtr = WIN_FindWndPtr( hwnd );
1765 if (!wndPtr) return 0;
1769 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1773 if (!wndPtr->parent) return 0; /* Desktop window */
1774 while (wndPtr->next) wndPtr = wndPtr->next;
1775 return wndPtr->hwndSelf;
1778 if (!wndPtr->next) return 0;
1779 return wndPtr->next->hwndSelf;
1782 if (!wndPtr->parent) return 0; /* Desktop window */
1783 wndPtr = wndPtr->parent->child; /* First sibling */
1784 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1785 while (wndPtr->next)
1787 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1788 wndPtr = wndPtr->next;
1793 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1796 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1802 /*******************************************************************
1803 * GetNextWindow (USER.230)
1805 HWND GetNextWindow( HWND hwnd, WORD flag )
1807 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1808 return GetWindow( hwnd, flag );
1811 /*******************************************************************
1812 * ShowOwnedPopups (USER.265)
1814 void ShowOwnedPopups( HWND owner, BOOL fShow )
1816 WND *pWnd = pWndDesktop->child;
1819 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1820 (pWnd->dwStyle & WS_POPUP))
1821 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1827 /*******************************************************************
1828 * GetLastActivePopup (USER.287)
1830 HWND GetLastActivePopup(HWND hwnd)
1833 wndPtr = WIN_FindWndPtr(hwnd);
1834 if (wndPtr == NULL) return hwnd;
1835 return wndPtr->hwndLastActive;
1839 /*******************************************************************
1842 * Build an array of pointers to all children of a given window.
1843 * The array must be freed with HeapFree(SystemHeap).
1845 WND **WIN_BuildWinArray( WND *wndPtr )
1847 WND **list, **ppWnd;
1851 /* First count the windows */
1853 if (!wndPtr) wndPtr = pWndDesktop;
1854 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1855 count++; /* For the terminating NULL */
1857 /* Now build the list of all windows */
1859 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1861 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1868 /*******************************************************************
1869 * EnumWindows16 (USER.54)
1871 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1873 WND **list, **ppWnd;
1875 /* We have to build a list of all windows first, to avoid */
1876 /* unpleasant side-effects, for instance if the callback */
1877 /* function changes the Z-order of the windows. */
1879 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1881 /* Now call the callback function for every window */
1883 for (ppWnd = list; *ppWnd; ppWnd++)
1885 /* Make sure that the window still exists */
1886 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1887 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1889 HeapFree( SystemHeap, 0, list );
1894 /*******************************************************************
1895 * EnumWindows32 (USER32.192)
1897 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1899 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1903 /**********************************************************************
1904 * EnumTaskWindows16 (USER.225)
1906 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1908 WND **list, **ppWnd;
1909 HQUEUE16 hQueue = GetTaskQueue( hTask );
1911 /* This function is the same as EnumWindows(), */
1912 /* except for an added check on the window queue. */
1914 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1916 /* Now call the callback function for every window */
1918 for (ppWnd = list; *ppWnd; ppWnd++)
1920 /* Make sure that the window still exists */
1921 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1922 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1923 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1925 HeapFree( SystemHeap, 0, list );
1930 /**********************************************************************
1931 * EnumThreadWindows (USER32.189)
1933 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1935 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1939 /**********************************************************************
1940 * WIN_EnumChildWindows
1942 * Helper function for EnumChildWindows().
1944 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1952 /* Make sure that the window still exists */
1953 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1954 /* Build children list first */
1955 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1956 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1957 ret = WIN_EnumChildWindows( childList, func, lParam );
1958 HeapFree( SystemHeap, 0, childList );
1959 if (!ret) return FALSE;
1966 /**********************************************************************
1967 * EnumChildWindows16 (USER.55)
1969 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1971 WND **list, *pParent;
1973 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1974 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1975 WIN_EnumChildWindows( list, func, lParam );
1976 HeapFree( SystemHeap, 0, list );
1981 /**********************************************************************
1982 * EnumChildWindows32 (USER32.177)
1984 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1986 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1991 /*******************************************************************
1992 * AnyPopup (USER.52)
1997 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1998 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2002 /*******************************************************************
2003 * FlashWindow [USER.105]
2005 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
2007 WND *wndPtr = WIN_FindWndPtr(hWnd);
2009 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2011 if (!wndPtr) return FALSE;
2013 if (wndPtr->dwStyle & WS_MINIMIZE)
2015 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2017 HDC32 hDC = GetDC32(hWnd);
2019 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
2020 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2022 ReleaseDC32( hWnd, hDC );
2023 wndPtr->flags |= WIN_NCACTIVATED;
2027 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2028 RDW_UPDATENOW | RDW_FRAME, 0 );
2029 wndPtr->flags &= ~WIN_NCACTIVATED;
2036 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2037 else wparam = (hWnd == GetActiveWindow());
2039 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2045 /*******************************************************************
2046 * SetSysModalWindow16 (USER.188)
2048 HWND16 SetSysModalWindow16( HWND16 hWnd )
2050 HWND hWndOldModal = hwndSysModal;
2051 hwndSysModal = hWnd;
2052 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2053 return hWndOldModal;
2057 /*******************************************************************
2058 * GetSysModalWindow16 (USER.52)
2060 HWND16 GetSysModalWindow16(void)
2062 return hwndSysModal;
2066 /*******************************************************************
2069 * recursively find a child that contains spDragInfo->pt point
2070 * and send WM_QUERYDROPOBJECT
2072 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
2074 BOOL wParam,bResult = 0;
2076 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2077 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2078 RECT16 tempRect; /* this sucks */
2080 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2082 pt = ptrDragInfo->pt;
2084 GetWindowRect16(hQueryWnd,&tempRect);
2086 if( !PtInRect16(&tempRect,pt) ||
2087 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2090 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2092 tempRect = ptrQueryWnd->rectClient;
2093 if(ptrQueryWnd->dwStyle & WS_CHILD)
2094 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2096 if( PtInRect16(&tempRect,pt) )
2100 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2101 if( ptrWnd->dwStyle & WS_VISIBLE )
2103 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2105 if( PtInRect16(&tempRect,pt) )
2111 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2112 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2113 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2114 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2115 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo);
2118 if(bResult) return bResult;
2124 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2126 ptrDragInfo->hScope = hQueryWnd;
2128 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2129 (WPARAM)wParam ,(LPARAM) spDragInfo );
2131 ptrDragInfo->pt = pt;
2136 /*******************************************************************
2137 * DragDetect ( USER.465 )
2140 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2145 rect.left = pt.x - wDragWidth;
2146 rect.right = pt.x + wDragWidth;
2148 rect.top = pt.y - wDragHeight;
2149 rect.bottom = pt.y + wDragHeight;
2155 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2157 if( msg.message == WM_LBUTTONUP )
2162 if( msg.message == WM_MOUSEMOVE )
2164 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2177 /******************************************************************************
2178 * DragObject ( USER.464 )
2181 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE16 hOfStruct,
2182 WORD szList , HCURSOR16 hCursor)
2185 LPDRAGINFO lpDragInfo;
2187 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2188 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2189 WND *wndPtr = WIN_FindWndPtr(hWnd);
2192 HCURSOR16 hCurrentCursor = 0;
2193 HWND hCurrentWnd = 0;
2196 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2197 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2199 if( !lpDragInfo || !spDragInfo ) return 0L;
2201 hBummer = LoadCursor16(0,IDC_BUMMER);
2203 if( !hBummer || !wndPtr )
2205 GlobalFree16(hDragInfo);
2211 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
2213 GlobalFree16(hDragInfo);
2217 if( hDragCursor == hCursor ) hDragCursor = 0;
2218 else hCursor = hDragCursor;
2220 hOldCursor = SetCursor(hDragCursor);
2223 lpDragInfo->hWnd = hWnd;
2224 lpDragInfo->hScope = 0;
2225 lpDragInfo->wFlags = wObj;
2226 lpDragInfo->hList = szList; /* near pointer! */
2227 lpDragInfo->hOfStruct = hOfStruct;
2237 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2240 *(lpDragInfo+1) = *lpDragInfo;
2242 lpDragInfo->pt = msg.pt;
2244 /* update DRAGINFO struct */
2245 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2247 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
2248 hCurrentCursor = hCursor;
2251 hCurrentCursor = hBummer;
2252 lpDragInfo->hScope = 0;
2254 if( hCurrentCursor )
2255 SetCursor(hCurrentCursor);
2257 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
2259 /* send WM_DRAGLOOP */
2260 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
2261 (LPARAM) spDragInfo );
2262 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2263 if( hCurrentWnd != lpDragInfo->hScope )
2266 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2267 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2268 HIWORD(spDragInfo)) );
2269 hCurrentWnd = lpDragInfo->hScope;
2271 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2275 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2278 /* check if we're done */
2279 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2288 SetCursor(hOldCursor);
2290 DestroyCursor(hDragCursor);
2293 if( hCurrentCursor != hBummer )
2294 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2295 (WPARAM)hWnd, (LPARAM)spDragInfo );
2296 GlobalFree16(hDragInfo);