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 HCURSOR CURSORICON_IconToCursor(HICON);
47 extern HQUEUE QUEUE_GetDoomedQueue();
49 /***********************************************************************
52 * Return a pointer to the WND structure corresponding to a HWND.
54 WND * WIN_FindWndPtr( HWND32 hwnd )
58 if (!hwnd || HIWORD(hwnd)) return NULL;
59 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
60 if (ptr->dwMagic != WND_MAGIC) return NULL;
61 if (ptr->hwndSelf != hwnd)
63 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
64 hwnd, ptr->hwndSelf );
71 /***********************************************************************
74 * Dump the content of a window structure to stderr.
76 void WIN_DumpWindow( HWND32 hwnd )
82 if (!(ptr = WIN_FindWndPtr( hwnd )))
84 fprintf( stderr, "%04x is not a window handle\n", hwnd );
88 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
89 strcpy( className, "#NULL#" );
91 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
93 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
94 "inst=%04x taskQ=%04x updRgn=%04x active=%04x hdce=%04x idmenu=%04x\n"
95 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
96 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
97 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
98 ptr->next, ptr->child, ptr->parent, ptr->owner,
99 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
100 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->hdce, ptr->wIDmenu,
101 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
102 ptr->text ? ptr->text : "",
103 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
104 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
105 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
106 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
107 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
109 if (ptr->class->cbWndExtra)
111 fprintf( stderr, "extra bytes:" );
112 for (i = 0; i < ptr->class->cbWndExtra; i++)
113 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
114 fprintf( stderr, "\n" );
116 fprintf( stderr, "\n" );
120 /***********************************************************************
123 * Walk the windows tree and print each window on stderr.
125 void WIN_WalkWindows( HWND32 hwnd, int indent )
130 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
133 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
137 if (!indent) /* first time around */
138 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
139 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
143 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
145 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
147 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
148 (DWORD)ptr, ptr->hmemTaskQ, className,
149 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
151 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
157 /***********************************************************************
160 * Return the X window associated to a window.
162 Window WIN_GetXWindow( HWND32 hwnd )
164 WND *wndPtr = WIN_FindWndPtr( hwnd );
165 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
166 return wndPtr ? wndPtr->window : 0;
170 /***********************************************************************
173 * Remove a window from the siblings linked list.
175 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
177 WND *wndPtr, **ppWnd;
179 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
180 ppWnd = &wndPtr->parent->child;
181 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
182 *ppWnd = wndPtr->next;
187 /***********************************************************************
190 * Insert a window into the siblings linked list.
191 * The window is inserted after the specified window, which can also
192 * be specified as HWND_TOP or HWND_BOTTOM.
194 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
196 WND *wndPtr, **ppWnd;
198 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
200 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
202 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
203 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
204 while (*ppWnd) ppWnd = &(*ppWnd)->next;
206 else /* Normal case */
208 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
209 if (!afterPtr) return FALSE;
210 ppWnd = &afterPtr->next;
212 wndPtr->next = *ppWnd;
218 /***********************************************************************
219 * WIN_FindWinToRepaint
221 * Find a window that needs repaint.
223 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
226 WND *pWnd = pWndDesktop;
228 /* Note: the desktop window never gets WM_PAINT messages */
229 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
231 for ( ; pWnd ; pWnd = pWnd->next )
233 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
235 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
239 if ((pWnd->hmemTaskQ == hQueue) &&
240 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
243 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
249 hwndRet = pWnd->hwndSelf;
251 /* look among siblings if we got a transparent window */
252 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
253 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
257 if (pWnd) hwndRet = pWnd->hwndSelf;
258 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
263 /***********************************************************************
264 * WIN_SendParentNotify
266 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
267 * the window has the WS_EX_NOPARENTNOTIFY style.
269 void WIN_SendParentNotify( HWND32 hwnd, WORD event, WORD idChild, LONG lValue )
271 LPPOINT16 lppt = (LPPOINT16)&lValue;
272 WND *wndPtr = WIN_FindWndPtr( hwnd );
273 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
275 /* if lValue contains cursor coordinates they have to be
276 * mapped to the client area of parent window */
278 if (bMouse) MapWindowPoints16(0, hwnd, lppt, 1);
280 else lValue = MAKELONG( LOWORD(lValue), idChild );
285 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
286 !(wndPtr->dwStyle & WS_CHILD)) break;
290 lppt->x += wndPtr->rectClient.left;
291 lppt->y += wndPtr->rectClient.top;
294 wndPtr = wndPtr->parent;
296 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
297 MAKEWPARAM( event, idChild ), lValue );
299 SendMessage16( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
305 /***********************************************************************
308 * Destroy storage associated to a window
310 static void WIN_DestroyWindow( HWND hwnd )
312 WND *wndPtr = WIN_FindWndPtr( hwnd );
316 DDE_DestroyWindow(hwnd);
317 #endif /* CONFIG_IPC */
320 WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
321 TIMER_RemoveWindowTimers( hwnd );
322 PROPERTY_RemoveWindowProps( wndPtr );
323 wndPtr->dwMagic = 0; /* Mark it as invalid */
324 wndPtr->hwndSelf = 0;
325 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
327 if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
328 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
330 if (!(wndPtr->dwStyle & WS_CHILD))
332 if (wndPtr->wIDmenu) DestroyMenu( (HMENU)wndPtr->wIDmenu );
334 if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
335 if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
336 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
337 WINPROC_FreeProc( wndPtr->winproc );
338 wndPtr->class->cWindows--;
339 USER_HEAP_FREE( hwnd );
343 /***********************************************************************
344 * WIN_DestroyQueueWindows
346 void WIN_DestroyQueueWindows( WND* wnd, HQUEUE hQueue )
353 if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
354 else WIN_DestroyQueueWindows( wnd->child, hQueue );
360 /***********************************************************************
361 * WIN_CreateDesktopWindow
363 * Create the desktop window.
365 BOOL32 WIN_CreateDesktopWindow(void)
371 dprintf_win(stddeb,"Creating desktop window\n");
373 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
376 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
377 if (!hwndDesktop) return FALSE;
378 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
380 pWndDesktop->next = NULL;
381 pWndDesktop->child = NULL;
382 pWndDesktop->parent = NULL;
383 pWndDesktop->owner = NULL;
384 pWndDesktop->class = class;
385 pWndDesktop->winproc = NULL;
386 pWndDesktop->dwMagic = WND_MAGIC;
387 pWndDesktop->hwndSelf = hwndDesktop;
388 pWndDesktop->hInstance = 0;
389 pWndDesktop->rectWindow.left = 0;
390 pWndDesktop->rectWindow.top = 0;
391 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
392 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
393 pWndDesktop->rectClient = pWndDesktop->rectWindow;
394 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
395 pWndDesktop->ptIconPos.x = -1;
396 pWndDesktop->ptIconPos.y = -1;
397 pWndDesktop->ptMaxPos.x = -1;
398 pWndDesktop->ptMaxPos.y = -1;
399 pWndDesktop->text = NULL;
400 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
401 pWndDesktop->hrgnUpdate = 0;
402 pWndDesktop->hwndLastActive = hwndDesktop;
403 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
405 pWndDesktop->dwExStyle = 0;
406 pWndDesktop->hdce = 0;
407 pWndDesktop->pVScroll = NULL;
408 pWndDesktop->pHScroll = NULL;
409 pWndDesktop->pProp = NULL;
410 pWndDesktop->wIDmenu = 0;
411 pWndDesktop->flags = 0;
412 pWndDesktop->window = rootWindow;
413 pWndDesktop->hSysMenu = 0;
414 pWndDesktop->userdata = 0;
416 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
417 EVENT_RegisterWindow( pWndDesktop );
418 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
419 if ((hdc = GetDC( hwndDesktop )) != 0)
421 SendMessage32A( hwndDesktop, WM_ERASEBKGND, hdc, 0 );
422 ReleaseDC( hwndDesktop, hdc );
428 /***********************************************************************
431 * Implementation of CreateWindowEx().
433 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
439 POINT16 maxSize, maxPos, minTrack, maxTrack;
442 dprintf_win( stddeb, "CreateWindowEx: " );
443 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
444 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
445 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
446 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
448 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
449 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
450 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
452 /* Find the parent window */
456 /* Make sure parent is valid */
457 if (!IsWindow( cs->hwndParent ))
459 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
463 else if (cs->style & WS_CHILD)
465 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
466 return 0; /* WS_CHILD needs a parent */
469 /* Find the window class */
471 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
472 GetExePtr(cs->hInstance) )))
475 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
476 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
480 /* Fix the coordinates */
482 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
483 if (cs->cx == CW_USEDEFAULT32)
485 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
493 /* Create the window structure */
495 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
496 - sizeof(wndPtr->wExtra) )))
498 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
502 /* Fill the window structure */
504 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
506 wndPtr->child = NULL;
507 wndPtr->parent = (cs->style & WS_CHILD) ?
508 WIN_FindWndPtr( cs->hwndParent ) : pWndDesktop;
509 wndPtr->owner = (cs->style & WS_CHILD) ? NULL :
510 WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
512 wndPtr->class = classPtr;
513 wndPtr->winproc = NULL;
514 wndPtr->dwMagic = WND_MAGIC;
515 wndPtr->hwndSelf = hwnd;
516 wndPtr->hInstance = cs->hInstance;
517 wndPtr->ptIconPos.x = -1;
518 wndPtr->ptIconPos.y = -1;
519 wndPtr->ptMaxPos.x = -1;
520 wndPtr->ptMaxPos.y = -1;
522 wndPtr->hmemTaskQ = GetTaskQueue(0);
523 wndPtr->hrgnUpdate = 0;
524 wndPtr->hwndLastActive = hwnd;
525 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
526 wndPtr->dwExStyle = cs->dwExStyle;
529 wndPtr->pVScroll = NULL;
530 wndPtr->pHScroll = NULL;
531 wndPtr->pProp = NULL;
532 wndPtr->hSysMenu = MENU_GetDefSysMenu();
533 wndPtr->userdata = 0;
535 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
536 classPtr->cWindows++;
538 /* Set the window procedure */
540 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
542 /* Correct the window style */
544 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
546 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
547 wndPtr->flags |= WIN_NEED_SIZE;
549 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
551 /* Get class or window DC if needed */
553 if (classPtr->style & CS_OWNDC) wndPtr->hdce = DCE_AllocDCE(hwnd, DCE_WINDOW_DC);
554 else if (classPtr->style & CS_CLASSDC) wndPtr->hdce = classPtr->hdce;
555 else wndPtr->hdce = 0;
557 /* Insert the window in the linked list */
559 WIN_LinkWindow( hwnd, (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP );
561 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
563 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
565 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
566 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
567 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
568 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
569 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
571 if (cs->cx <= 0) cs->cx = 1;
572 if (cs->cy <= 0) cs->cy = 1;
574 wndPtr->rectWindow.left = cs->x;
575 wndPtr->rectWindow.top = cs->y;
576 wndPtr->rectWindow.right = cs->x + cs->cx;
577 wndPtr->rectWindow.bottom = cs->y + cs->cy;
578 wndPtr->rectClient = wndPtr->rectWindow;
579 wndPtr->rectNormal = wndPtr->rectWindow;
581 /* Create the X window (only for top-level windows, and then only */
582 /* when there's no desktop window) */
584 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
586 XSetWindowAttributes win_attr;
587 Atom XA_WM_DELETE_WINDOW;
589 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
590 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
592 win_attr.event_mask = ExposureMask | KeyPressMask |
593 KeyReleaseMask | PointerMotionMask |
594 ButtonPressMask | ButtonReleaseMask |
595 FocusChangeMask | StructureNotifyMask;
596 win_attr.override_redirect = FALSE;
597 wndPtr->flags |= WIN_MANAGED;
601 win_attr.event_mask = ExposureMask | KeyPressMask |
602 KeyReleaseMask | PointerMotionMask |
603 ButtonPressMask | ButtonReleaseMask |
604 FocusChangeMask | StructureNotifyMask;
605 win_attr.override_redirect = TRUE;
607 win_attr.colormap = COLOR_GetColormap();
608 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
609 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
610 win_attr.cursor = CURSORICON_XCursor;
611 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
612 cs->cx, cs->cy, 0, CopyFromParent,
613 InputOutput, CopyFromParent,
614 CWEventMask | CWOverrideRedirect |
615 CWColormap | CWCursor | CWSaveUnder |
616 CWBackingStore, &win_attr );
617 XA_WM_DELETE_WINDOW = XInternAtom( display, "WM_DELETE_WINDOW",
619 XSetWMProtocols( display, wndPtr->window, &XA_WM_DELETE_WINDOW, 1 );
621 if ((wndPtr->flags & WIN_MANAGED) &&
622 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
624 XSizeHints* size_hints = XAllocSizeHints();
628 size_hints->min_width = size_hints->max_width = cs->cx;
629 size_hints->min_height = size_hints->max_height = cs->cy;
630 size_hints->flags = (PSize | PMinSize | PMaxSize);
631 XSetWMSizeHints( display, wndPtr->window, size_hints,
632 XA_WM_NORMAL_HINTS );
637 if (cs->hwndParent) /* Get window owner */
639 Window win = WIN_GetXWindow( cs->hwndParent );
640 if (win) XSetTransientForHint( display, wndPtr->window, win );
642 EVENT_RegisterWindow( wndPtr );
645 /* Set the window menu */
647 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
649 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
652 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
653 if (classPtr->menuNameA)
654 cs->hMenu = HIWORD(classPtr->menuNameA) ?
655 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
656 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
658 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
659 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
662 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
664 else wndPtr->wIDmenu = (UINT)cs->hMenu;
666 /* Send the WM_CREATE message */
670 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
673 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
674 NULL, NULL, 0, &wndPtr->rectClient );
675 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
680 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
683 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
684 NULL, NULL, 0, &wndPtr->rectClient );
685 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
691 /* Abort window creation */
692 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
693 WIN_DestroyWindow( hwnd );
697 /* Send the size messages */
699 if (!(wndPtr->flags & WIN_NEED_SIZE))
702 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
703 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
704 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
705 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
706 wndPtr->rectClient.top ));
709 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LONG)hwnd );
710 if (!IsWindow(hwnd)) return 0;
712 /* Show the window, maximizing or minimizing if needed */
714 if (wndPtr->dwStyle & WS_MINIMIZE)
716 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
718 wndPtr->dwStyle &= ~WS_MAXIMIZE;
719 WINPOS_FindIconPos( hwnd );
720 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
721 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
722 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
724 else if (wndPtr->dwStyle & WS_MAXIMIZE)
726 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
728 POINT16 maxSize, maxPos, minTrack, maxTrack;
729 NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
730 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
731 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
734 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
736 /* Call WH_SHELL hook */
738 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
739 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
741 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
746 /***********************************************************************
747 * CreateWindow16 (USER.41)
749 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
750 DWORD style, INT16 x, INT16 y, INT16 width,
751 INT16 height, HWND16 parent, HMENU16 menu,
752 HINSTANCE16 instance, LPVOID data )
754 return CreateWindowEx16( 0, className, windowName, style,
755 x, y, width, height, parent, menu, instance, data );
759 /***********************************************************************
760 * CreateWindowEx16 (USER.452)
762 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
763 DWORD style, INT16 x, INT16 y, INT16 width,
764 INT16 height, HWND16 parent, HMENU16 menu,
765 HINSTANCE16 instance, LPVOID data )
770 /* Find the class atom */
772 if (!(classAtom = GlobalFindAtom32A( className )))
774 fprintf( stderr, "CreateWindowEx16: bad class name " );
775 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
776 else fprintf( stderr, "'%s'\n", className );
780 /* Fix the coordinates */
782 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
783 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
784 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
785 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
787 /* Create the window */
789 cs.lpCreateParams = data;
790 cs.hInstance = (HINSTANCE32)instance;
791 cs.hMenu = (HMENU32)menu;
792 cs.hwndParent = (HWND32)parent;
794 cs.lpszName = windowName;
795 cs.lpszClass = className;
796 cs.dwExStyle = exStyle;
797 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
801 /***********************************************************************
802 * CreateWindowEx32A (USER32.82)
804 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
805 DWORD style, INT32 x, INT32 y, INT32 width,
806 INT32 height, HWND32 parent, HMENU32 menu,
807 HINSTANCE32 instance, LPVOID data )
812 /* Find the class atom */
814 if (!(classAtom = GlobalFindAtom32A( className )))
816 fprintf( stderr, "CreateWindowEx32A: bad class name " );
817 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
818 else fprintf( stderr, "'%s'\n", className );
822 /* Create the window */
824 cs.lpCreateParams = data;
825 cs.hInstance = instance;
827 cs.hwndParent = parent;
833 cs.lpszName = windowName;
834 cs.lpszClass = className;
835 cs.dwExStyle = exStyle;
836 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
840 /***********************************************************************
841 * CreateWindowEx32W (USER32.83)
843 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
844 DWORD style, INT32 x, INT32 y, INT32 width,
845 INT32 height, HWND32 parent, HMENU32 menu,
846 HINSTANCE32 instance, LPVOID data )
851 /* Find the class atom */
853 if (!(classAtom = GlobalFindAtom32W( className )))
855 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
859 /* Create the window */
861 cs.lpCreateParams = data;
862 cs.hInstance = instance;
864 cs.hwndParent = parent;
870 cs.lpszName = windowName;
871 cs.lpszClass = className;
872 cs.dwExStyle = exStyle;
873 /* Note: we rely on the fact that CREATESTRUCT32A and */
874 /* CREATESTRUCT32W have the same layout. */
875 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
879 /***********************************************************************
880 * DestroyWindow (USER.53)
882 BOOL DestroyWindow( HWND hwnd )
886 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
890 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
891 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
893 /* Top-level window */
895 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
897 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
898 /* FIXME: clean up palette - see "Internals" p.352 */
901 /* Hide the window */
903 if (wndPtr->dwStyle & WS_VISIBLE)
904 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE |
905 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE );
906 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
908 if (!QUEUE_GetDoomedQueue())
909 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LONG)hwnd );
911 CLIPBOARD_DisOwn( hwnd );
913 /* Recursively destroy owned windows */
917 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
920 if (siblingPtr->owner == wndPtr) break;
921 siblingPtr = siblingPtr->next;
923 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
927 /* Send destroy messages and destroy children */
929 SendMessage16( hwnd, WM_DESTROY, 0, 0 );
930 while (wndPtr->child) /* The child removes itself from the list */
931 DestroyWindow( wndPtr->child->hwndSelf );
932 SendMessage16( hwnd, WM_NCDESTROY, 0, 0 );
934 /* Destroy the window */
936 WIN_DestroyWindow( hwnd );
941 /***********************************************************************
942 * CloseWindow (USER.43)
944 BOOL CloseWindow(HWND hWnd)
946 WND * wndPtr = WIN_FindWndPtr(hWnd);
947 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
948 ShowWindow(hWnd, SW_MINIMIZE);
953 /***********************************************************************
956 BOOL OpenIcon(HWND hWnd)
958 if (!IsIconic(hWnd)) return FALSE;
959 ShowWindow(hWnd, SW_SHOWNORMAL);
964 /***********************************************************************
967 * Implementation of FindWindow() and FindWindowEx().
969 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
973 CLASS *pClass = NULL;
977 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
980 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
982 else if (pWnd->parent != pWndDesktop) return 0;
987 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
992 /* For a child window, all siblings will have the same hInstance, */
993 /* so we can look for the class once and for all. */
995 if (className && (pWnd->dwStyle & WS_CHILD))
997 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1001 for ( ; pWnd; pWnd = pWnd->next)
1003 if (className && !(pWnd->dwStyle & WS_CHILD))
1005 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1006 continue; /* Skip this window */
1008 if (pClass && (pWnd->class != pClass))
1009 continue; /* Not the right class */
1011 /* Now check the title */
1013 if (!title) return pWnd->hwndSelf;
1014 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1021 /***********************************************************************
1022 * FindWindow16 (USER.50)
1024 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1026 return FindWindowEx16( 0, 0, className, title );
1030 /***********************************************************************
1031 * FindWindowEx16 (USER.427)
1033 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1034 SEGPTR className, LPCSTR title )
1038 atom = className ? GlobalFindAtom16( className ) : 0;
1039 return WIN_FindWindow( parent, child, atom, title );
1043 /***********************************************************************
1044 * FindWindow32A (USER32.197)
1046 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1048 return FindWindowEx32A( 0, 0, className, title );
1052 /***********************************************************************
1053 * FindWindowEx32A (USER32.198)
1055 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1056 LPCSTR className, LPCSTR title )
1060 atom = className ? GlobalFindAtom32A( className ) : 0;
1061 return WIN_FindWindow( 0, 0, atom, title );
1065 /***********************************************************************
1066 * FindWindowEx32W (USER32.199)
1068 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1069 LPCWSTR className, LPCWSTR title )
1075 atom = className ? GlobalFindAtom32W( className ) : 0;
1076 buffer = title ? STRING32_DupUniToAnsi( title ) : NULL;
1077 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1078 if (buffer) free( buffer );
1083 /***********************************************************************
1084 * FindWindow32W (USER32.200)
1086 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1088 return FindWindowEx32W( 0, 0, className, title );
1092 /**********************************************************************
1095 WND *WIN_GetDesktop(void)
1101 /**********************************************************************
1102 * GetDesktopWindow (USER.286)
1104 HWND GetDesktopWindow(void)
1106 return pWndDesktop->hwndSelf;
1110 /**********************************************************************
1111 * GetDesktopHwnd (USER.278)
1113 * Exactly the same thing as GetDesktopWindow(), but not documented.
1114 * Don't ask me why...
1116 HWND GetDesktopHwnd(void)
1118 return pWndDesktop->hwndSelf;
1122 /*******************************************************************
1123 * EnableWindow (USER.34)
1125 BOOL EnableWindow( HWND hwnd, BOOL enable )
1129 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1130 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1133 wndPtr->dwStyle &= ~WS_DISABLED;
1134 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1137 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1139 /* Disable window */
1140 wndPtr->dwStyle |= WS_DISABLED;
1141 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
1142 SetFocus( 0 ); /* A disabled window can't have the focus */
1143 if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
1144 ReleaseCapture(); /* A disabled window can't capture the mouse */
1145 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1148 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1152 /***********************************************************************
1153 * IsWindowEnabled (USER.35) (USER32.348)
1155 BOOL IsWindowEnabled(HWND hWnd)
1159 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1160 return !(wndPtr->dwStyle & WS_DISABLED);
1164 /***********************************************************************
1165 * IsWindowUnicode (USER32.349)
1167 BOOL32 IsWindowUnicode( HWND32 hwnd )
1171 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1172 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1176 /**********************************************************************
1177 * GetWindowWord (USER.133) (USER32.313)
1179 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1181 WND * wndPtr = WIN_FindWndPtr( hwnd );
1182 if (!wndPtr) return 0;
1185 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1187 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1190 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1194 case GWW_ID: return wndPtr->wIDmenu;
1195 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1196 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1198 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1204 /**********************************************************************
1205 * WIN_GetWindowInstance
1207 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1209 WND * wndPtr = WIN_FindWndPtr( hwnd );
1210 if (!wndPtr) return (HINSTANCE16)0;
1211 return wndPtr->hInstance;
1215 /**********************************************************************
1216 * SetWindowWord (USER.134) (USER32.523)
1218 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1221 WND * wndPtr = WIN_FindWndPtr( hwnd );
1222 if (!wndPtr) return 0;
1225 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1227 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1230 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1234 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1235 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1237 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1246 /**********************************************************************
1249 * Helper function for GetWindowLong().
1251 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1254 WND * wndPtr = WIN_FindWndPtr( hwnd );
1255 if (!wndPtr) return 0;
1258 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1260 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1263 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1264 /* Special case for dialog window procedure */
1265 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1266 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1271 case GWL_USERDATA: return wndPtr->userdata;
1272 case GWL_STYLE: return wndPtr->dwStyle;
1273 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1274 case GWL_ID: return wndPtr->wIDmenu;
1275 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1277 case GWL_HWNDPARENT: return wndPtr->parent ?
1278 (HWND32)wndPtr->parent->hwndSelf : 0;
1279 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1281 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1287 /**********************************************************************
1290 * Helper function for SetWindowLong().
1292 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1293 WINDOWPROCTYPE type )
1296 WND * wndPtr = WIN_FindWndPtr( hwnd );
1297 if (!wndPtr) return 0;
1300 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1302 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1305 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1306 /* Special case for dialog window procedure */
1307 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1309 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1310 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1318 return SetWindowWord( hwnd, offset, (WORD)newval );
1320 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1321 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1324 ptr = &wndPtr->dwStyle;
1325 /* Some bits can't be changed this way */
1326 newval &= ~(WS_VISIBLE | WS_CHILD);
1327 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1329 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1330 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1332 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1341 /**********************************************************************
1342 * GetWindowLong16 (USER.135)
1344 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1346 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1350 /**********************************************************************
1351 * GetWindowLong32A (USER32.304)
1353 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1355 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1359 /**********************************************************************
1360 * GetWindowLong32W (USER32.305)
1362 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1364 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1368 /**********************************************************************
1369 * SetWindowLong16 (USER.136)
1371 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1373 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1377 /**********************************************************************
1378 * SetWindowLong32A (USER32.516)
1380 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1382 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1386 /**********************************************************************
1387 * SetWindowLong32W (USER32.517)
1389 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1391 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1395 /*******************************************************************
1396 * GetWindowText16 (USER.36)
1398 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1400 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1404 /*******************************************************************
1405 * GetWindowText32A (USER32.308)
1407 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1409 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1414 /*******************************************************************
1415 * GetWindowText32W (USER32.311)
1417 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1419 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1424 /*******************************************************************
1425 * SetWindowText16 (USER.37)
1427 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1429 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1433 /*******************************************************************
1434 * SetWindowText32A (USER32.)
1436 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1438 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1442 /*******************************************************************
1443 * SetWindowText32W (USER32.)
1445 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1447 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1451 /*******************************************************************
1452 * GetWindowTextLength (USER.38)
1454 int GetWindowTextLength(HWND hwnd)
1456 return (int)SendMessage16(hwnd, WM_GETTEXTLENGTH, 0, 0 );
1460 /*******************************************************************
1461 * IsWindow (USER.47) (USER32.347)
1463 BOOL16 IsWindow( HWND32 hwnd )
1465 WND * wndPtr = WIN_FindWndPtr( hwnd );
1466 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1470 /*****************************************************************
1471 * GetParent (USER.46)
1473 HWND GetParent(HWND hwnd)
1475 WND *wndPtr = WIN_FindWndPtr(hwnd);
1476 if (!wndPtr) return 0;
1477 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1478 return wndPtr ? wndPtr->hwndSelf : 0;
1482 /*****************************************************************
1485 * Get the top-level parent for a child window.
1487 HWND32 WIN_GetTopParent( HWND32 hwnd )
1489 WND *wndPtr = WIN_FindWndPtr( hwnd );
1490 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1491 return wndPtr ? wndPtr->hwndSelf : 0;
1495 /*****************************************************************
1496 * SetParent (USER.233)
1498 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1502 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1503 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1504 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1506 oldParent = wndPtr->parent->hwndSelf;
1508 WIN_UnlinkWindow(hwndChild);
1509 if (hwndNewParent) wndPtr->parent = pWndParent;
1510 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1512 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1519 /*******************************************************************
1522 BOOL IsChild( HWND parent, HWND child )
1524 WND * wndPtr = WIN_FindWndPtr( child );
1525 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1527 wndPtr = wndPtr->parent;
1528 if (wndPtr->hwndSelf == parent) return TRUE;
1534 /***********************************************************************
1535 * IsWindowVisible (USER.49) (USER32.350)
1537 BOOL IsWindowVisible( HWND hwnd )
1539 WND *wndPtr = WIN_FindWndPtr( hwnd );
1540 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1542 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1543 wndPtr = wndPtr->parent;
1545 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1550 /*******************************************************************
1551 * GetTopWindow (USER.229)
1553 HWND GetTopWindow( HWND hwnd )
1555 WND * wndPtr = WIN_FindWndPtr( hwnd );
1556 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1561 /*******************************************************************
1562 * GetWindow (USER.262)
1564 HWND GetWindow( HWND hwnd, WORD rel )
1566 WND * wndPtr = WIN_FindWndPtr( hwnd );
1567 if (!wndPtr) return 0;
1571 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1575 if (!wndPtr->parent) return 0; /* Desktop window */
1576 while (wndPtr->next) wndPtr = wndPtr->next;
1577 return wndPtr->hwndSelf;
1580 if (!wndPtr->next) return 0;
1581 return wndPtr->next->hwndSelf;
1584 if (!wndPtr->parent) return 0; /* Desktop window */
1585 wndPtr = wndPtr->parent->child; /* First sibling */
1586 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1587 while (wndPtr->next)
1589 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1590 wndPtr = wndPtr->next;
1595 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1598 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1604 /*******************************************************************
1605 * GetNextWindow (USER.230)
1607 HWND GetNextWindow( HWND hwnd, WORD flag )
1609 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1610 return GetWindow( hwnd, flag );
1613 /*******************************************************************
1614 * ShowOwnedPopups (USER.265)
1616 void ShowOwnedPopups( HWND owner, BOOL fShow )
1618 WND *pWnd = pWndDesktop->child;
1621 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1622 (pWnd->dwStyle & WS_POPUP))
1623 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1629 /*******************************************************************
1630 * GetLastActivePopup (USER.287)
1632 HWND GetLastActivePopup(HWND hwnd)
1635 wndPtr = WIN_FindWndPtr(hwnd);
1636 if (wndPtr == NULL) return hwnd;
1637 return wndPtr->hwndLastActive;
1641 /*******************************************************************
1644 * Build an array of pointers to all children of a given window.
1645 * The array must be freed with HeapFree(SystemHeap).
1647 WND **WIN_BuildWinArray( WND *wndPtr )
1649 WND **list, **ppWnd;
1653 /* First count the windows */
1655 if (!wndPtr) wndPtr = pWndDesktop;
1656 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1657 count++; /* For the terminating NULL */
1659 /* Now build the list of all windows */
1661 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1663 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1670 /*******************************************************************
1671 * EnumWindows16 (USER.54)
1673 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1675 WND **list, **ppWnd;
1677 /* We have to build a list of all windows first, to avoid */
1678 /* unpleasant side-effects, for instance if the callback */
1679 /* function changes the Z-order of the windows. */
1681 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1683 /* Now call the callback function for every window */
1685 for (ppWnd = list; *ppWnd; ppWnd++)
1687 /* Make sure that the window still exists */
1688 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1689 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1691 HeapFree( SystemHeap, 0, list );
1696 /*******************************************************************
1697 * EnumWindows32 (USER32.192)
1699 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1701 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1705 /**********************************************************************
1706 * EnumTaskWindows16 (USER.225)
1708 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1710 WND **list, **ppWnd;
1711 HANDLE hQueue = GetTaskQueue( hTask );
1713 /* This function is the same as EnumWindows(), */
1714 /* except for an added check on the window queue. */
1716 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1718 /* Now call the callback function for every window */
1720 for (ppWnd = list; *ppWnd; ppWnd++)
1722 /* Make sure that the window still exists */
1723 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1724 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1725 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1727 HeapFree( SystemHeap, 0, list );
1732 /**********************************************************************
1733 * EnumThreadWindows (USER32.189)
1735 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1737 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1741 /**********************************************************************
1742 * WIN_EnumChildWindows
1744 * Helper function for EnumChildWindows().
1746 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1754 /* Make sure that the window still exists */
1755 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1756 /* Build children list first */
1757 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1758 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1759 ret = WIN_EnumChildWindows( childList, func, lParam );
1760 HeapFree( SystemHeap, 0, childList );
1761 if (!ret) return FALSE;
1768 /**********************************************************************
1769 * EnumChildWindows16 (USER.55)
1771 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1773 WND **list, *pParent;
1775 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1776 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1777 WIN_EnumChildWindows( list, func, lParam );
1778 HeapFree( SystemHeap, 0, list );
1783 /**********************************************************************
1784 * EnumChildWindows32 (USER32.177)
1786 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1788 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1793 /*******************************************************************
1794 * AnyPopup (USER.52)
1799 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
1800 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
1804 /*******************************************************************
1805 * FlashWindow [USER.105]
1807 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
1809 WND *wndPtr = WIN_FindWndPtr(hWnd);
1811 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
1813 if (!wndPtr) return FALSE;
1815 if (wndPtr->dwStyle & WS_MINIMIZE)
1817 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
1819 HDC hDC = GetDC(hWnd);
1821 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM)hDC, (LPARAM)0 ))
1822 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
1824 ReleaseDC( hWnd, hDC );
1825 wndPtr->flags |= WIN_NCACTIVATED;
1829 RedrawWindow32( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
1830 RDW_UPDATENOW | RDW_FRAME );
1831 wndPtr->flags &= ~WIN_NCACTIVATED;
1838 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
1839 else wparam = (hWnd == GetActiveWindow());
1841 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
1847 /*******************************************************************
1848 * SetSysModalWindow16 (USER.188)
1850 HWND16 SetSysModalWindow16( HWND16 hWnd )
1852 HWND hWndOldModal = hwndSysModal;
1853 hwndSysModal = hWnd;
1854 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
1855 return hWndOldModal;
1859 /*******************************************************************
1860 * GetSysModalWindow16 (USER.52)
1862 HWND16 GetSysModalWindow16(void)
1864 return hwndSysModal;
1868 /*******************************************************************
1871 * recursively find a child that contains spDragInfo->pt point
1872 * and send WM_QUERYDROPOBJECT
1874 BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
1876 BOOL wParam,bResult = 0;
1878 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
1879 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
1880 RECT16 tempRect; /* this sucks */
1882 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
1884 pt = ptrDragInfo->pt;
1886 GetWindowRect16(hQueryWnd,&tempRect);
1888 if( !PtInRect16(&tempRect,pt) ||
1889 (ptrQueryWnd->dwStyle & WS_DISABLED) )
1892 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
1894 tempRect = ptrQueryWnd->rectClient;
1895 if(ptrQueryWnd->dwStyle & WS_CHILD)
1896 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
1898 if( PtInRect16(&tempRect,pt) )
1902 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
1903 if( ptrWnd->dwStyle & WS_VISIBLE )
1905 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
1907 if( PtInRect16(&tempRect,pt) )
1913 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
1914 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
1915 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
1916 if( !(ptrWnd->dwStyle & WS_DISABLED) )
1917 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo);
1920 if(bResult) return bResult;
1926 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
1928 ptrDragInfo->hScope = hQueryWnd;
1930 bResult = SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
1931 (WPARAM)wParam ,(LPARAM) spDragInfo );
1933 ptrDragInfo->pt = pt;
1938 /*******************************************************************
1939 * DragDetect ( USER.465 )
1942 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
1947 rect.left = pt.x - wDragWidth;
1948 rect.right = pt.x + wDragWidth;
1950 rect.top = pt.y - wDragHeight;
1951 rect.bottom = pt.y + wDragHeight;
1957 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
1959 if( msg.message == WM_LBUTTONUP )
1964 if( msg.message == WM_MOUSEMOVE )
1966 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
1979 /******************************************************************************
1980 * DragObject ( USER.464 )
1983 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
1984 WORD szList , HCURSOR hCursor)
1987 LPDRAGINFO lpDragInfo;
1989 HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
1990 HANDLE hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
1991 WND *wndPtr = WIN_FindWndPtr(hWnd);
1994 HCURSOR hCurrentCursor = 0;
1995 HWND hCurrentWnd = 0;
1998 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
1999 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2001 if( !lpDragInfo || !spDragInfo ) return 0L;
2003 hBummer = LoadCursor16(0,IDC_BUMMER);
2005 if( !hBummer || !wndPtr )
2007 GlobalFree16(hDragInfo);
2013 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
2015 GlobalFree16(hDragInfo);
2019 if( hDragCursor == hCursor ) hDragCursor = 0;
2020 else hCursor = hDragCursor;
2022 hOldCursor = SetCursor(hDragCursor);
2025 lpDragInfo->hWnd = hWnd;
2026 lpDragInfo->hScope = 0;
2027 lpDragInfo->wFlags = wObj;
2028 lpDragInfo->hList = szList; /* near pointer! */
2029 lpDragInfo->hOfStruct = hOfStruct;
2039 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2042 *(lpDragInfo+1) = *lpDragInfo;
2044 lpDragInfo->pt = msg.pt;
2046 /* update DRAGINFO struct */
2047 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2049 if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
2050 hCurrentCursor = hCursor;
2053 hCurrentCursor = hBummer;
2054 lpDragInfo->hScope = 0;
2056 if( hCurrentCursor )
2057 SetCursor(hCurrentCursor);
2059 dprintf_msg(stddeb,"drag: got %04x\n",btemp);
2061 /* send WM_DRAGLOOP */
2062 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
2063 (LPARAM) spDragInfo );
2064 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2065 if( hCurrentWnd != lpDragInfo->hScope )
2068 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2069 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2070 HIWORD(spDragInfo)) );
2071 hCurrentWnd = lpDragInfo->hScope;
2073 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2077 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2080 /* check if we're done */
2081 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2090 SetCursor(hOldCursor);
2092 DestroyCursor(hDragCursor);
2095 if( hCurrentCursor != hBummer )
2096 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2097 (WPARAM)hWnd, (LPARAM)spDragInfo );
2098 GlobalFree16(hDragInfo);