CreateWindowEx32[AW] now creates an MDI chils when the WM_EX_MDICHILD
[wine.git] / windows / win.c
blob62280d9c6568276c9b1c7778e521b47f8af06938
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <string.h>
9 #include <X11/Xatom.h>
11 #include "options.h"
12 #include "class.h"
13 #include "win.h"
14 #include "heap.h"
15 #include "user.h"
16 #include "dce.h"
17 #include "sysmetrics.h"
18 #include "cursoricon.h"
19 #include "heap.h"
20 #include "hook.h"
21 #include "menu.h"
22 #include "message.h"
23 #include "nonclient.h"
24 #include "queue.h"
25 #include "winpos.h"
26 #include "color.h"
27 #include "shm_main_blk.h"
28 #include "dde_proc.h"
29 #include "clipboard.h"
30 #include "winproc.h"
31 #include "thread.h"
32 #include "process.h"
33 #include "debug.h"
34 #include "winerror.h"
35 #include "mdi.h"
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND32 hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 /***********************************************************************
46 * WIN_FindWndPtr
48 * Return a pointer to the WND structure corresponding to a HWND.
50 WND * WIN_FindWndPtr( HWND32 hwnd )
52 WND * ptr;
54 if (!hwnd || HIWORD(hwnd)) return NULL;
55 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
56 if (ptr->dwMagic != WND_MAGIC) return NULL;
57 if (ptr->hwndSelf != hwnd)
59 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
60 hwnd, ptr->hwndSelf );
61 return NULL;
63 return ptr;
67 /***********************************************************************
68 * WIN_DumpWindow
70 * Dump the content of a window structure to stderr.
72 void WIN_DumpWindow( HWND32 hwnd )
74 WND *ptr;
75 char className[80];
76 int i;
78 if (!(ptr = WIN_FindWndPtr( hwnd )))
80 WARN( win, "%04x is not a window handle\n", hwnd );
81 return;
84 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
85 strcpy( className, "#NULL#" );
87 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
88 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
89 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
90 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
91 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
92 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
93 ptr->next, ptr->child, ptr->parent, ptr->owner,
94 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
95 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
96 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
97 ptr->text ? ptr->text : "",
98 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
99 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
100 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
101 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
103 if (ptr->class->cbWndExtra)
105 DUMP( "extra bytes:" );
106 for (i = 0; i < ptr->class->cbWndExtra; i++)
107 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
108 DUMP( "\n" );
110 DUMP( "\n" );
114 /***********************************************************************
115 * WIN_WalkWindows
117 * Walk the windows tree and print each window on stderr.
119 void WIN_WalkWindows( HWND32 hwnd, int indent )
121 WND *ptr;
122 char className[80];
124 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
125 if (!ptr)
127 WARN( win, "Invalid window handle %04x\n", hwnd );
128 return;
131 if (!indent) /* first time around */
132 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
133 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc"
134 " Text");
136 while (ptr)
138 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
140 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
142 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
143 (DWORD)ptr, ptr->hmemTaskQ, className,
144 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
145 ptr->text?ptr->text:"<null>");
147 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
148 ptr = ptr->next;
153 /***********************************************************************
154 * WIN_GetXWindow
156 * Return the X window associated to a window.
158 Window WIN_GetXWindow( HWND32 hwnd )
160 WND *wndPtr = WIN_FindWndPtr( hwnd );
161 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
162 return wndPtr ? wndPtr->window : 0;
166 /***********************************************************************
167 * WIN_UnlinkWindow
169 * Remove a window from the siblings linked list.
171 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
173 WND *wndPtr, **ppWnd;
175 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
176 ppWnd = &wndPtr->parent->child;
177 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
178 *ppWnd = wndPtr->next;
179 return TRUE;
183 /***********************************************************************
184 * WIN_LinkWindow
186 * Insert a window into the siblings linked list.
187 * The window is inserted after the specified window, which can also
188 * be specified as HWND_TOP or HWND_BOTTOM.
190 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
192 WND *wndPtr, **ppWnd;
194 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
196 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
198 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
199 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
200 while (*ppWnd) ppWnd = &(*ppWnd)->next;
202 else /* Normal case */
204 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
205 if (!afterPtr) return FALSE;
206 ppWnd = &afterPtr->next;
208 wndPtr->next = *ppWnd;
209 *ppWnd = wndPtr;
210 return TRUE;
214 /***********************************************************************
215 * WIN_FindWinToRepaint
217 * Find a window that needs repaint.
219 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
221 HWND32 hwndRet;
222 WND *pWnd = pWndDesktop;
224 /* Note: the desktop window never gets WM_PAINT messages
225 * The real reason why is because Windows DesktopWndProc
226 * does ValidateRgn inside WM_ERASEBKGND handler.
229 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
231 for ( ; pWnd ; pWnd = pWnd->next )
233 if (!(pWnd->dwStyle & WS_VISIBLE))
235 TRACE(win, "skipping window %04x\n",
236 pWnd->hwndSelf );
237 continue;
239 if ((pWnd->hmemTaskQ == hQueue) &&
240 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
242 if (pWnd->child )
243 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
244 return hwndRet;
247 if (!pWnd) return 0;
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))))
255 pWnd = pWnd->next;
257 if (pWnd) hwndRet = pWnd->hwndSelf;
258 TRACE(win,"found %04x\n",hwndRet);
259 return hwndRet;
263 /***********************************************************************
264 * WIN_DestroyWindow
266 * Destroy storage associated to a window. "Internals" p.358
268 static WND* WIN_DestroyWindow( WND* wndPtr )
270 HWND32 hwnd = wndPtr->hwndSelf;
271 WND *pWnd;
273 TRACE(win, "%04x\n", wndPtr->hwndSelf );
275 #ifdef CONFIG_IPC
276 if (main_block)
277 DDE_DestroyWindow(wndPtr->hwndSelf);
278 #endif /* CONFIG_IPC */
280 /* free child windows */
282 while ((pWnd = wndPtr->child))
283 wndPtr->child = WIN_DestroyWindow( pWnd );
285 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
287 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
289 WINPOS_CheckInternalPos( hwnd );
290 if( hwnd == GetCapture32()) ReleaseCapture();
292 /* free resources associated with the window */
294 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
295 PROPERTY_RemoveWindowProps( wndPtr );
297 wndPtr->dwMagic = 0; /* Mark it as invalid */
299 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
301 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
302 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
305 /* toss stale messages from the queue */
307 if( wndPtr->hmemTaskQ )
309 int pos;
310 BOOL32 bPostQuit = FALSE;
311 WPARAM32 wQuitParam = 0;
312 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
314 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
316 if( msgQ->messages[pos].msg.message == WM_QUIT )
318 bPostQuit = TRUE;
319 wQuitParam = msgQ->messages[pos].msg.wParam;
321 QUEUE_RemoveMsg(msgQ, pos);
323 /* repost WM_QUIT to make sure this app exits its message loop */
324 if( bPostQuit ) PostQuitMessage32(wQuitParam);
325 wndPtr->hmemTaskQ = 0;
328 if (!(wndPtr->dwStyle & WS_CHILD))
329 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
330 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
331 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
332 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
333 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
334 wndPtr->hwndSelf = 0;
335 wndPtr->class->cWindows--;
336 wndPtr->class = NULL;
337 pWnd = wndPtr->next;
339 USER_HEAP_FREE( hwnd );
340 return pWnd;
343 /***********************************************************************
344 * WIN_ResetQueueWindows
346 * Reset the queue of all the children of a given window.
347 * Return TRUE if something was done.
349 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
351 BOOL32 ret = FALSE;
353 if (hNew) /* Set a new queue */
355 for (wnd = wnd->child; (wnd); wnd = wnd->next)
357 if (wnd->hmemTaskQ == hQueue)
359 wnd->hmemTaskQ = hNew;
360 ret = TRUE;
362 if (wnd->child)
363 ret |= WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
366 else /* Queue is being destroyed */
368 while (wnd->child)
370 WND *tmp = wnd->child;
371 ret = FALSE;
372 while (tmp)
374 if (tmp->hmemTaskQ == hQueue)
376 DestroyWindow32( tmp->hwndSelf );
377 ret = TRUE;
378 break;
380 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
381 ret = TRUE;
382 else
383 tmp = tmp->next;
385 if (!ret) break;
388 return ret;
391 /***********************************************************************
392 * WIN_CreateDesktopWindow
394 * Create the desktop window.
396 BOOL32 WIN_CreateDesktopWindow(void)
398 CLASS *class;
399 HWND32 hwndDesktop;
401 TRACE(win,"Creating desktop window\n");
403 if (!ICONTITLE_Init() ||
404 !WINPOS_CreateInternalPosAtom() ||
405 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
406 return FALSE;
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->dwMagic = WND_MAGIC;
418 pWndDesktop->hwndSelf = hwndDesktop;
419 pWndDesktop->hInstance = 0;
420 pWndDesktop->rectWindow.left = 0;
421 pWndDesktop->rectWindow.top = 0;
422 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
423 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
424 pWndDesktop->rectClient = pWndDesktop->rectWindow;
425 pWndDesktop->text = NULL;
426 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
427 pWndDesktop->hrgnUpdate = 0;
428 pWndDesktop->hwndLastActive = hwndDesktop;
429 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
430 WS_CLIPSIBLINGS;
431 pWndDesktop->dwExStyle = 0;
432 pWndDesktop->dce = NULL;
433 pWndDesktop->pVScroll = NULL;
434 pWndDesktop->pHScroll = NULL;
435 pWndDesktop->pProp = NULL;
436 pWndDesktop->wIDmenu = 0;
437 pWndDesktop->helpContext = 0;
438 pWndDesktop->flags = 0;
439 pWndDesktop->window = rootWindow;
440 pWndDesktop->hSysMenu = 0;
441 pWndDesktop->userdata = 0;
443 pWndDesktop->winproc = (WNDPROC16)class->winproc;
445 EVENT_RegisterWindow( pWndDesktop );
446 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
447 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
448 return TRUE;
452 /***********************************************************************
453 * WIN_CreateWindowEx
455 * Implementation of CreateWindowEx().
457 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
458 BOOL32 win32, BOOL32 unicode )
460 CLASS *classPtr;
461 WND *wndPtr;
462 HWND16 hwnd, hwndLinkAfter;
463 POINT32 maxSize, maxPos, minTrack, maxTrack;
464 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
466 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
467 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
468 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
469 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
470 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
472 /* Find the parent window */
474 if (cs->hwndParent)
476 /* Make sure parent is valid */
477 if (!IsWindow32( cs->hwndParent ))
479 WARN( win, "Bad parent %04x\n", cs->hwndParent );
480 return 0;
482 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
483 WARN( win, "No parent for child window\n" );
484 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
487 /* Find the window class */
488 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
490 char buffer[256];
491 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
492 WARN( win, "Bad class '%s'\n", buffer );
493 return 0;
496 /* Fix the coordinates */
498 if (cs->x == CW_USEDEFAULT32)
500 PDB32 *pdb = PROCESS_Current();
501 if ( !(cs->style & (WS_CHILD | WS_POPUP))
502 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
504 cs->x = pdb->env_db->startup_info->dwX;
505 cs->y = pdb->env_db->startup_info->dwY;
507 else
509 cs->x = 0;
510 cs->y = 0;
513 if (cs->cx == CW_USEDEFAULT32)
515 PDB32 *pdb = PROCESS_Current();
516 if ( !(cs->style & (WS_CHILD | WS_POPUP))
517 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
519 cs->cx = pdb->env_db->startup_info->dwXSize;
520 cs->cy = pdb->env_db->startup_info->dwYSize;
522 else
524 cs->cx = 600; /* FIXME */
525 cs->cy = 400;
529 /* Create the window structure */
531 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
532 - sizeof(wndPtr->wExtra) )))
534 TRACE(win, "out of memory\n" );
535 return 0;
538 /* Fill the window structure */
540 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
541 wndPtr->next = NULL;
542 wndPtr->child = NULL;
544 if ((cs->style & WS_CHILD) && cs->hwndParent)
546 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
547 wndPtr->owner = NULL;
549 else
551 wndPtr->parent = pWndDesktop;
552 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
553 wndPtr->owner = NULL;
554 else
555 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
558 wndPtr->window = 0;
559 wndPtr->class = classPtr;
560 wndPtr->winproc = classPtr->winproc;
561 wndPtr->dwMagic = WND_MAGIC;
562 wndPtr->hwndSelf = hwnd;
563 wndPtr->hInstance = cs->hInstance;
564 wndPtr->text = NULL;
565 wndPtr->hmemTaskQ = GetTaskQueue(0);
566 wndPtr->hrgnUpdate = 0;
567 wndPtr->hwndLastActive = hwnd;
568 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
569 wndPtr->dwExStyle = cs->dwExStyle;
570 wndPtr->wIDmenu = 0;
571 wndPtr->helpContext = 0;
572 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
573 wndPtr->pVScroll = NULL;
574 wndPtr->pHScroll = NULL;
575 wndPtr->pProp = NULL;
576 wndPtr->userdata = 0;
577 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
578 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
580 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
582 /* Call the WH_CBT hook */
584 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
586 if (HOOK_IsHooked( WH_CBT ))
588 CBT_CREATEWND32A cbtc;
589 LRESULT ret;
591 cbtc.lpcs = cs;
592 cbtc.hwndInsertAfter = hwndLinkAfter;
593 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
594 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
595 if (ret)
597 TRACE(win, "CBT-hook returned 0\n");
598 USER_HEAP_FREE( hwnd );
599 return 0;
603 /* Increment class window counter */
605 classPtr->cWindows++;
607 /* Correct the window style */
609 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
611 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
612 wndPtr->flags |= WIN_NEED_SIZE;
614 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
616 /* Get class or window DC if needed */
618 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
619 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
620 else wndPtr->dce = NULL;
622 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
624 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
626 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
627 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
628 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
629 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
630 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
633 if(cs->style & WS_CHILD)
635 if(cs->cx < 0) cs->cx = 0;
636 if(cs->cy < 0) cs->cy = 0;
638 else
640 if (cs->cx <= 0) cs->cx = 1;
641 if (cs->cy <= 0) cs->cy = 1;
644 wndPtr->rectWindow.left = cs->x;
645 wndPtr->rectWindow.top = cs->y;
646 wndPtr->rectWindow.right = cs->x + cs->cx;
647 wndPtr->rectWindow.bottom = cs->y + cs->cy;
648 wndPtr->rectClient = wndPtr->rectWindow;
650 /* Create the X window (only for top-level windows, and then only */
651 /* when there's no desktop window) */
653 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
655 XSetWindowAttributes win_attr;
657 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
658 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
660 win_attr.event_mask = ExposureMask | KeyPressMask |
661 KeyReleaseMask | PointerMotionMask |
662 ButtonPressMask | ButtonReleaseMask |
663 FocusChangeMask | StructureNotifyMask;
664 win_attr.override_redirect = FALSE;
665 wndPtr->flags |= WIN_MANAGED;
667 else
669 win_attr.event_mask = ExposureMask | KeyPressMask |
670 KeyReleaseMask | PointerMotionMask |
671 ButtonPressMask | ButtonReleaseMask |
672 FocusChangeMask;
673 win_attr.override_redirect = TRUE;
675 win_attr.colormap = COLOR_GetColormap();
676 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
677 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
678 win_attr.cursor = CURSORICON_XCursor;
679 wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
680 cs->cx, cs->cy, 0, CopyFromParent,
681 InputOutput, CopyFromParent,
682 CWEventMask | CWOverrideRedirect |
683 CWColormap | CWCursor | CWSaveUnder |
684 CWBackingStore, &win_attr );
686 if ((wndPtr->flags & WIN_MANAGED) &&
687 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
689 XSizeHints* size_hints = TSXAllocSizeHints();
691 if (size_hints)
693 size_hints->min_width = size_hints->max_width = cs->cx;
694 size_hints->min_height = size_hints->max_height = cs->cy;
695 size_hints->flags = (PSize | PMinSize | PMaxSize);
696 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
697 XA_WM_NORMAL_HINTS );
698 TSXFree(size_hints);
702 if (cs->hwndParent) /* Get window owner */
704 Window win = WIN_GetXWindow( cs->hwndParent );
705 if (win) TSXSetTransientForHint( display, wndPtr->window, win );
707 EVENT_RegisterWindow( wndPtr );
710 /* Set the window menu */
712 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
714 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
715 else
717 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
718 if (classPtr->menuNameA)
719 cs->hMenu = HIWORD(classPtr->menuNameA) ?
720 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
721 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
722 #else
723 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
724 if (menuName)
726 /* hInstance is still 16-bit in 980215 winelib */
727 if (HIWORD(cs->hInstance) || __winelib)
728 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
729 else
730 /* doesn't work for winelib, since resources are unicode */
731 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
733 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
735 #endif
738 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
740 /* Send the WM_CREATE message
741 * Perhaps we shouldn't allow width/height changes as well.
742 * See p327 in "Internals".
745 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
747 localSend32 = unicode ? SendMessage32W : SendMessage32A;
748 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
750 /* Insert the window in the linked list */
752 WIN_LinkWindow( hwnd, hwndLinkAfter );
754 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
755 NULL, NULL, 0, &wndPtr->rectClient );
756 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
757 maxPos.y - wndPtr->rectWindow.top);
758 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
760 /* Send the size messages */
762 if (!(wndPtr->flags & WIN_NEED_SIZE))
764 /* send it anyway */
765 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
766 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
767 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
768 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
769 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
770 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
771 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
772 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
773 SendMessage32A( hwnd, WM_MOVE, 0,
774 MAKELONG( wndPtr->rectClient.left,
775 wndPtr->rectClient.top ) );
778 /* Show the window, maximizing or minimizing if needed */
780 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
782 RECT16 newPos;
783 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
784 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
785 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
786 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
787 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
788 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
791 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
793 /* Notify the parent window only */
795 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
796 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
797 if( !IsWindow32(hwnd) ) return 0;
800 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
802 /* Call WH_SHELL hook */
804 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
805 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
807 TRACE(win, "created window %04x\n", hwnd);
808 return hwnd;
810 WIN_UnlinkWindow( hwnd );
813 /* Abort window creation */
815 WARN(win, "aborted by WM_xxCREATE!\n");
816 WIN_DestroyWindow( wndPtr );
817 return 0;
821 /***********************************************************************
822 * CreateWindow16 (USER.41)
824 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
825 DWORD style, INT16 x, INT16 y, INT16 width,
826 INT16 height, HWND16 parent, HMENU16 menu,
827 HINSTANCE16 instance, LPVOID data )
829 return CreateWindowEx16( 0, className, windowName, style,
830 x, y, width, height, parent, menu, instance, data );
834 /***********************************************************************
835 * CreateWindowEx16 (USER.452)
837 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
838 LPCSTR windowName, DWORD style, INT16 x,
839 INT16 y, INT16 width, INT16 height,
840 HWND16 parent, HMENU16 menu,
841 HINSTANCE16 instance, LPVOID data )
843 ATOM classAtom;
844 CREATESTRUCT32A cs;
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 );
853 return 0;
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;
869 cs.style = style;
870 cs.lpszName = windowName;
871 cs.lpszClass = className;
872 cs.dwExStyle = exStyle;
873 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
877 /***********************************************************************
878 * CreateWindowEx32A (USER32.83)
880 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
881 LPCSTR windowName, DWORD style, INT32 x,
882 INT32 y, INT32 width, INT32 height,
883 HWND32 parent, HMENU32 menu,
884 HINSTANCE32 instance, LPVOID data )
886 ATOM classAtom;
887 CREATESTRUCT32A cs;
889 if(exStyle & WS_EX_MDICHILD)
890 return MDI_CreateMDIWindow32A(className, windowName, style, x, y, width, height, parent, instance, data);
891 /* Find the class atom */
893 if (!(classAtom = GlobalFindAtom32A( className )))
895 fprintf( stderr, "CreateWindowEx32A: bad class name " );
896 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
897 else fprintf( stderr, "'%s'\n", className );
898 return 0;
901 /* Create the window */
903 cs.lpCreateParams = data;
904 cs.hInstance = instance;
905 cs.hMenu = menu;
906 cs.hwndParent = parent;
907 cs.x = x;
908 cs.y = y;
909 cs.cx = width;
910 cs.cy = height;
911 cs.style = style;
912 cs.lpszName = windowName;
913 cs.lpszClass = className;
914 cs.dwExStyle = exStyle;
915 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
919 /***********************************************************************
920 * CreateWindowEx32W (USER32.84)
922 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
923 LPCWSTR windowName, DWORD style, INT32 x,
924 INT32 y, INT32 width, INT32 height,
925 HWND32 parent, HMENU32 menu,
926 HINSTANCE32 instance, LPVOID data )
928 ATOM classAtom;
929 CREATESTRUCT32W cs;
931 if(exStyle & WS_EX_MDICHILD)
932 return MDI_CreateMDIWindow32W(className, windowName, style, x, y, width, height, parent, instance, data);
934 /* Find the class atom */
936 if (!(classAtom = GlobalFindAtom32W( className )))
938 if (HIWORD(className))
940 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
941 WARN( win, "Bad class name '%s'\n",cn);
942 HeapFree( GetProcessHeap(), 0, cn );
944 else
945 WARN( win, "Bad class name %p\n", className );
946 return 0;
949 /* Create the window */
951 cs.lpCreateParams = data;
952 cs.hInstance = instance;
953 cs.hMenu = menu;
954 cs.hwndParent = parent;
955 cs.x = x;
956 cs.y = y;
957 cs.cx = width;
958 cs.cy = height;
959 cs.style = style;
960 cs.lpszName = windowName;
961 cs.lpszClass = className;
962 cs.dwExStyle = exStyle;
963 /* Note: we rely on the fact that CREATESTRUCT32A and */
964 /* CREATESTRUCT32W have the same layout. */
965 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
969 /***********************************************************************
970 * WIN_CheckFocus
972 static void WIN_CheckFocus( WND* pWnd )
974 if( GetFocus16() == pWnd->hwndSelf )
975 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
978 /***********************************************************************
979 * WIN_SendDestroyMsg
981 static void WIN_SendDestroyMsg( WND* pWnd )
983 WIN_CheckFocus(pWnd);
985 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
986 if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd );
988 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
990 if( IsWindow32(pWnd->hwndSelf) )
992 WND* pChild = pWnd->child;
993 while( pChild )
995 WIN_SendDestroyMsg( pChild );
996 pChild = pChild->next;
998 WIN_CheckFocus(pWnd);
1000 else
1001 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
1005 /***********************************************************************
1006 * DestroyWindow16 (USER.53)
1008 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1010 return DestroyWindow32(hwnd);
1014 /***********************************************************************
1015 * DestroyWindow32 (USER32.135)
1017 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
1019 WND * wndPtr;
1021 TRACE(win, "(%04x)\n", hwnd);
1023 /* Initialization */
1025 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1026 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1028 /* Call hooks */
1030 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1031 return FALSE;
1033 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1035 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1036 /* FIXME: clean up palette - see "Internals" p.352 */
1039 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1040 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1042 /* Notify the parent window only */
1043 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1044 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1045 if( !IsWindow32(hwnd) ) return TRUE;
1048 if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
1050 /* Hide the window */
1052 if (wndPtr->dwStyle & WS_VISIBLE)
1054 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1055 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1056 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1057 if (!IsWindow32(hwnd)) return TRUE;
1060 /* Recursively destroy owned windows */
1062 if( !(wndPtr->dwStyle & WS_CHILD) )
1064 /* make sure top menu popup doesn't get destroyed */
1065 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1067 for (;;)
1069 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1070 while (siblingPtr)
1072 if (siblingPtr->owner == wndPtr)
1073 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1074 break;
1075 else
1076 siblingPtr->owner = NULL;
1077 siblingPtr = siblingPtr->next;
1079 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1080 else break;
1083 if( !Options.managed || EVENT_CheckFocus() )
1084 WINPOS_ActivateOtherWindow(wndPtr);
1086 if( wndPtr->owner &&
1087 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1088 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1091 /* Send destroy messages */
1093 WIN_SendDestroyMsg( wndPtr );
1094 if (!IsWindow32(hwnd)) return TRUE;
1096 /* Unlink now so we won't bother with the children later on */
1098 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1100 /* Destroy the window storage */
1102 WIN_DestroyWindow( wndPtr );
1103 return TRUE;
1107 /***********************************************************************
1108 * CloseWindow16 (USER.43)
1110 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1112 return CloseWindow32( hwnd );
1116 /***********************************************************************
1117 * CloseWindow32 (USER32.56)
1119 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1121 WND * wndPtr = WIN_FindWndPtr( hwnd );
1122 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1123 ShowWindow32( hwnd, SW_MINIMIZE );
1124 return TRUE;
1128 /***********************************************************************
1129 * OpenIcon16 (USER.44)
1131 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1133 return OpenIcon32( hwnd );
1137 /***********************************************************************
1138 * OpenIcon32 (USER32.410)
1140 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1142 if (!IsIconic32( hwnd )) return FALSE;
1143 ShowWindow32( hwnd, SW_SHOWNORMAL );
1144 return TRUE;
1148 /***********************************************************************
1149 * WIN_FindWindow
1151 * Implementation of FindWindow() and FindWindowEx().
1153 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1154 LPCSTR title )
1156 WND *pWnd;
1157 CLASS *pClass = NULL;
1159 if (child)
1161 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1162 if (parent)
1164 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1166 else if (pWnd->parent != pWndDesktop) return 0;
1167 pWnd = pWnd->next;
1169 else
1171 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1172 pWnd = pWnd->child;
1174 if (!pWnd) return 0;
1176 /* For a child window, all siblings will have the same hInstance, */
1177 /* so we can look for the class once and for all. */
1179 if (className && (pWnd->dwStyle & WS_CHILD))
1181 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1182 return 0;
1186 for ( ; pWnd; pWnd = pWnd->next)
1188 if (className && !(pWnd->dwStyle & WS_CHILD))
1190 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1191 continue; /* Skip this window */
1194 if (pClass && (pWnd->class != pClass))
1195 continue; /* Not the right class */
1197 /* Now check the title */
1199 if (!title) return pWnd->hwndSelf;
1200 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1202 return 0;
1207 /***********************************************************************
1208 * FindWindow16 (USER.50)
1210 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1212 return FindWindowEx16( 0, 0, className, title );
1216 /***********************************************************************
1217 * FindWindowEx16 (USER.427)
1219 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1220 SEGPTR className, LPCSTR title )
1222 ATOM atom = 0;
1224 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1225 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1226 title ? title : "");
1228 if (className)
1230 /* If the atom doesn't exist, then no class */
1231 /* with this name exists either. */
1232 if (!(atom = GlobalFindAtom16( className ))) return 0;
1234 return WIN_FindWindow( parent, child, atom, title );
1238 /***********************************************************************
1239 * FindWindow32A (USER32.198)
1241 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1243 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1244 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1245 return ret;
1249 /***********************************************************************
1250 * FindWindowEx32A (USER32.199)
1252 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1253 LPCSTR className, LPCSTR title )
1255 ATOM atom = 0;
1257 if (className)
1259 /* If the atom doesn't exist, then no class */
1260 /* with this name exists either. */
1261 if (!(atom = GlobalFindAtom32A( className )))
1263 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1264 return 0;
1267 return WIN_FindWindow( parent, child, atom, title );
1271 /***********************************************************************
1272 * FindWindowEx32W (USER32.200)
1274 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1275 LPCWSTR className, LPCWSTR title )
1277 ATOM atom = 0;
1278 char *buffer;
1279 HWND32 hwnd;
1281 if (className)
1283 /* If the atom doesn't exist, then no class */
1284 /* with this name exists either. */
1285 if (!(atom = GlobalFindAtom32W( className )))
1287 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1288 return 0;
1291 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1292 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1293 HeapFree( GetProcessHeap(), 0, buffer );
1294 return hwnd;
1298 /***********************************************************************
1299 * FindWindow32W (USER32.201)
1301 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1303 return FindWindowEx32W( 0, 0, className, title );
1307 /**********************************************************************
1308 * WIN_GetDesktop
1310 WND *WIN_GetDesktop(void)
1312 return pWndDesktop;
1316 /**********************************************************************
1317 * GetDesktopWindow16 (USER.286)
1319 HWND16 WINAPI GetDesktopWindow16(void)
1321 return (HWND16)pWndDesktop->hwndSelf;
1325 /**********************************************************************
1326 * GetDesktopWindow32 (USER32.232)
1328 HWND32 WINAPI GetDesktopWindow32(void)
1330 return pWndDesktop->hwndSelf;
1334 /**********************************************************************
1335 * GetDesktopHwnd (USER.278)
1337 * Exactly the same thing as GetDesktopWindow(), but not documented.
1338 * Don't ask me why...
1340 HWND16 WINAPI GetDesktopHwnd(void)
1342 return (HWND16)pWndDesktop->hwndSelf;
1346 /*******************************************************************
1347 * EnableWindow16 (USER.34)
1349 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1351 return EnableWindow32( hwnd, enable );
1355 /*******************************************************************
1356 * EnableWindow32 (USER32.172)
1358 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1360 WND *wndPtr;
1362 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1363 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1365 /* Enable window */
1366 wndPtr->dwStyle &= ~WS_DISABLED;
1367 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1368 return TRUE;
1370 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1372 /* Disable window */
1373 wndPtr->dwStyle |= WS_DISABLED;
1374 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1375 SetFocus32( 0 ); /* A disabled window can't have the focus */
1376 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1377 ReleaseCapture(); /* A disabled window can't capture the mouse */
1378 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1379 return FALSE;
1381 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1385 /***********************************************************************
1386 * IsWindowEnabled16 (USER.35)
1388 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1390 return IsWindowEnabled32(hWnd);
1394 /***********************************************************************
1395 * IsWindowEnabled32 (USER32.349)
1397 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1399 WND * wndPtr;
1401 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1402 return !(wndPtr->dwStyle & WS_DISABLED);
1406 /***********************************************************************
1407 * IsWindowUnicode (USER32.350)
1409 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1411 WND * wndPtr;
1413 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1414 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1418 /**********************************************************************
1419 * GetWindowWord16 (USER.133)
1421 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1423 return GetWindowWord32( hwnd, offset );
1427 /**********************************************************************
1428 * GetWindowWord32 (USER32.314)
1430 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1432 WND * wndPtr = WIN_FindWndPtr( hwnd );
1433 if (!wndPtr) return 0;
1434 if (offset >= 0)
1436 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1438 WARN( win, "Invalid offset %d\n", offset );
1439 return 0;
1441 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1443 switch(offset)
1445 case GWW_ID:
1446 if (HIWORD(wndPtr->wIDmenu))
1447 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1448 wndPtr->wIDmenu);
1449 return (WORD)wndPtr->wIDmenu;
1450 case GWW_HWNDPARENT:
1451 return wndPtr->parent ?
1452 wndPtr->parent->hwndSelf : (
1453 wndPtr->owner ?
1454 wndPtr->owner->hwndSelf :
1456 case GWW_HINSTANCE:
1457 if (HIWORD(wndPtr->hInstance))
1458 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1459 wndPtr->hInstance);
1460 return (WORD)wndPtr->hInstance;
1461 default:
1462 WARN( win, "Invalid offset %d\n", offset );
1463 return 0;
1468 /**********************************************************************
1469 * WIN_GetWindowInstance
1471 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1473 WND * wndPtr = WIN_FindWndPtr( hwnd );
1474 if (!wndPtr) return (HINSTANCE32)0;
1475 return wndPtr->hInstance;
1479 /**********************************************************************
1480 * SetWindowWord16 (USER.134)
1482 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1484 return SetWindowWord32( hwnd, offset, newval );
1488 /**********************************************************************
1489 * SetWindowWord32 (USER32.524)
1491 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1493 WORD *ptr, retval;
1494 WND * wndPtr = WIN_FindWndPtr( hwnd );
1495 if (!wndPtr) return 0;
1496 if (offset >= 0)
1498 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1500 WARN( win, "Invalid offset %d\n", offset );
1501 return 0;
1503 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1505 else switch(offset)
1507 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1508 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1509 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1510 default:
1511 WARN( win, "Invalid offset %d\n", offset );
1512 return 0;
1514 retval = *ptr;
1515 *ptr = newval;
1516 return retval;
1520 /**********************************************************************
1521 * WIN_GetWindowLong
1523 * Helper function for GetWindowLong().
1525 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1527 LONG retval;
1528 WND * wndPtr = WIN_FindWndPtr( hwnd );
1529 if (!wndPtr) return 0;
1530 if (offset >= 0)
1532 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1534 WARN( win, "Invalid offset %d\n", offset );
1535 return 0;
1537 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1538 /* Special case for dialog window procedure */
1539 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1540 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1541 return retval;
1543 switch(offset)
1545 case GWL_USERDATA: return wndPtr->userdata;
1546 case GWL_STYLE: return wndPtr->dwStyle;
1547 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1548 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1549 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1550 type );
1551 case GWL_HWNDPARENT: return wndPtr->parent ?
1552 (HWND32)wndPtr->parent->hwndSelf : 0;
1553 case GWL_HINSTANCE: return wndPtr->hInstance;
1554 default:
1555 WARN( win, "Unknown offset %d\n", offset );
1557 return 0;
1561 /**********************************************************************
1562 * WIN_SetWindowLong
1564 * Helper function for SetWindowLong().
1566 * 0 is the failure code. However, in the case of failure SetLastError
1567 * must be set to distinguish between a 0 return value and a failure.
1569 * FIXME: The error values for SetLastError may not be right. Can
1570 * someone check with the real thing?
1572 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1573 WINDOWPROCTYPE type )
1575 LONG *ptr, retval;
1576 WND * wndPtr = WIN_FindWndPtr( hwnd );
1577 STYLESTRUCT style;
1579 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1581 if (!wndPtr)
1583 /* Is this the right error? */
1584 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1585 return 0;
1588 if (offset >= 0)
1590 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1592 WARN( win, "Invalid offset %d\n", offset );
1594 /* Is this the right error? */
1595 SetLastError( ERROR_OUTOFMEMORY );
1597 return 0;
1599 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1600 /* Special case for dialog window procedure */
1601 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1603 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1604 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1605 type, WIN_PROC_WINDOW );
1606 return retval;
1609 else switch(offset)
1611 case GWL_ID:
1612 ptr = (DWORD*)&wndPtr->wIDmenu;
1613 break;
1614 case GWL_HINSTANCE:
1615 return SetWindowWord32( hwnd, offset, newval );
1616 case GWL_WNDPROC:
1617 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1618 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1619 type, WIN_PROC_WINDOW );
1620 return retval;
1621 case GWL_STYLE:
1622 style.styleOld = wndPtr->dwStyle;
1623 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1624 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1626 if (wndPtr->flags & WIN_ISWIN32)
1627 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1628 wndPtr->dwStyle = style.styleNew;
1629 if (wndPtr->flags & WIN_ISWIN32)
1630 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1631 return style.styleOld;
1633 case GWL_USERDATA:
1634 ptr = &wndPtr->userdata;
1635 break;
1636 case GWL_EXSTYLE:
1637 style.styleOld = wndPtr->dwExStyle;
1638 style.styleNew = newval;
1639 if (wndPtr->flags & WIN_ISWIN32)
1640 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1641 wndPtr->dwExStyle = newval;
1642 if (wndPtr->flags & WIN_ISWIN32)
1643 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1644 return style.styleOld;
1646 default:
1647 WARN( win, "Invalid offset %d\n", offset );
1649 /* Don't think this is right error but it should do */
1650 SetLastError( ERROR_OUTOFMEMORY );
1652 return 0;
1654 retval = *ptr;
1655 *ptr = newval;
1656 return retval;
1660 /**********************************************************************
1661 * GetWindowLong16 (USER.135)
1663 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1665 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1669 /**********************************************************************
1670 * GetWindowLong32A (USER32.305)
1672 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1674 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1678 /**********************************************************************
1679 * GetWindowLong32W (USER32.306)
1681 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1683 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1687 /**********************************************************************
1688 * SetWindowLong16 (USER.136)
1690 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1692 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1696 /**********************************************************************
1697 * SetWindowLong32A (USER32.517)
1699 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1701 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1705 /**********************************************************************
1706 * SetWindowLong32W (USER32.518) Set window attribute
1708 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1709 * value in a window's extra memory.
1711 * The _hwnd_ parameter specifies the window. is the handle to a
1712 * window that has extra memory. The _newval_ parameter contains the
1713 * new attribute or extra memory value. If positive, the _offset_
1714 * parameter is the byte-addressed location in the window's extra
1715 * memory to set. If negative, _offset_ specifies the window
1716 * attribute to set, and should be one of the following values:
1718 * GWL_EXSTYLE The window's extended window style
1720 * GWL_STYLE The window's window style.
1722 * GWL_WNDPROC Pointer to the window's window procedure.
1724 * GWL_HINSTANCE The window's pplication instance handle.
1726 * GWL_ID The window's identifier.
1728 * GWL_USERDATA The window's user-specified data.
1730 * If the window is a dialog box, the _offset_ parameter can be one of
1731 * the following values:
1733 * DWL_DLGPROC The address of the window's dialog box procedure.
1735 * DWL_MSGRESULT The return value of a message
1736 * that the dialog box procedure processed.
1738 * DWL_USER Application specific information.
1740 * RETURNS
1742 * If successful, returns the previous value located at _offset_. Otherwise,
1743 * returns 0.
1745 * NOTES
1747 * Extra memory for a window class is specified by a nonzero cbWndExtra
1748 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1749 * time of class creation.
1751 * Using GWL_WNDPROC to set a new window procedure effectively creates
1752 * a window subclass. Use CallWindowProc() in the new windows procedure
1753 * to pass messages to the superclass's window procedure.
1755 * The user data is reserved for use by the application which created
1756 * the window.
1758 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1759 * instead, call the EnableWindow() function to change the window's
1760 * disabled state.
1762 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1763 * SetParent() instead.
1765 * BUGS
1767 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1769 * CONFORMANCE
1771 * ECMA-234, Win32
1774 LONG WINAPI SetWindowLong32W(
1775 HWND32 hwnd, /* window to alter */
1776 INT32 offset, /* offset, in bytes, of location to alter */
1777 LONG newval /* new value of location */
1779 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1783 /*******************************************************************
1784 * GetWindowText16 (USER.36)
1786 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1788 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1792 /*******************************************************************
1793 * GetWindowText32A (USER32.309)
1795 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1797 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1798 (LPARAM)lpString );
1801 /*******************************************************************
1802 * InternalGetWindowText (USER32.326)
1804 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1806 FIXME(win,"(0x%08x,%p,0x%x),stub!\n",hwnd,lpString,nMaxCount);
1807 return GetWindowText32W(hwnd,lpString,nMaxCount);
1811 /*******************************************************************
1812 * GetWindowText32W (USER32.312)
1814 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1816 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1817 (LPARAM)lpString );
1821 /*******************************************************************
1822 * SetWindowText16 (USER.37)
1824 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1826 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1830 /*******************************************************************
1831 * SetWindowText32A (USER32.521)
1833 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1835 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1839 /*******************************************************************
1840 * SetWindowText32W (USER32.523)
1842 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1844 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1848 /*******************************************************************
1849 * GetWindowTextLength16 (USER.38)
1851 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1853 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1857 /*******************************************************************
1858 * GetWindowTextLength32A (USER32.310)
1860 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1862 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1865 /*******************************************************************
1866 * GetWindowTextLength32W (USER32.311)
1868 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1870 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1874 /*******************************************************************
1875 * IsWindow16 (USER.47)
1877 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1879 return IsWindow32( hwnd );
1882 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1884 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1885 HWND16 hwnd = (HWND16)stack[2];
1887 AX_reg(context) = IsWindow32( hwnd );
1888 ES_reg(context) = USER_HeapSel;
1892 /*******************************************************************
1893 * IsWindow32 (USER32.348)
1895 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1897 WND * wndPtr = WIN_FindWndPtr( hwnd );
1898 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1902 /*****************************************************************
1903 * GetParent16 (USER.46)
1905 HWND16 WINAPI GetParent16( HWND16 hwnd )
1907 return (HWND16)GetParent32( hwnd );
1911 /*****************************************************************
1912 * GetParent32 (USER32.278)
1914 HWND32 WINAPI GetParent32( HWND32 hwnd )
1916 WND *wndPtr = WIN_FindWndPtr(hwnd);
1917 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1918 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1919 return wndPtr ? wndPtr->hwndSelf : 0;
1922 /*****************************************************************
1923 * WIN_GetTopParent
1925 * Get the top-level parent for a child window.
1927 WND* WIN_GetTopParentPtr( WND* pWnd )
1929 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1930 return pWnd;
1933 /*****************************************************************
1934 * WIN_GetTopParent
1936 * Get the top-level parent for a child window.
1938 HWND32 WIN_GetTopParent( HWND32 hwnd )
1940 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1941 return wndPtr ? wndPtr->hwndSelf : 0;
1945 /*****************************************************************
1946 * SetParent16 (USER.233)
1948 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1950 return SetParent32( hwndChild, hwndNewParent );
1954 /*****************************************************************
1955 * SetParent32 (USER32.495)
1957 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1959 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1960 WND *pWndParent = (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent )
1961 : pWndDesktop;
1963 if( wndPtr && pWndParent && (wndPtr != pWndDesktop) )
1965 WND* pWndPrev = wndPtr->parent;
1967 if( pWndParent != pWndPrev )
1969 BOOL32 bFixupDCE = IsWindowVisible32(hwndChild);
1971 if ( wndPtr->window )
1973 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
1975 TSXDestroyWindow( display, wndPtr->window );
1976 wndPtr->window = None;
1978 else if( bFixupDCE )
1979 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1981 WIN_UnlinkWindow(hwndChild);
1982 wndPtr->parent = pWndParent;
1984 /* FIXME: Create an X counterpart for reparented top-level windows
1985 * when not in the desktop mode. */
1987 if ( pWndParent != pWndDesktop ) wndPtr->dwStyle |= WS_CHILD;
1988 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1990 if( bFixupDCE )
1992 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1993 UpdateWindow32(hwndChild);
1996 return pWndPrev->hwndSelf;
1997 } /* failure */
1998 return 0;
2002 /*******************************************************************
2003 * IsChild16 (USER.48)
2005 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2007 return IsChild32(parent,child);
2011 /*******************************************************************
2012 * IsChild32 (USER32.339)
2014 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
2016 WND * wndPtr = WIN_FindWndPtr( child );
2017 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2019 wndPtr = wndPtr->parent;
2020 if (wndPtr->hwndSelf == parent) return TRUE;
2022 return FALSE;
2026 /***********************************************************************
2027 * IsWindowVisible16 (USER.49)
2029 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2031 return IsWindowVisible32(hwnd);
2035 /***********************************************************************
2036 * IsWindowVisible32 (USER32.351)
2038 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
2040 WND *wndPtr = WIN_FindWndPtr( hwnd );
2041 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2043 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2044 wndPtr = wndPtr->parent;
2046 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2050 /***********************************************************************
2051 * WIN_IsWindowDrawable
2053 * hwnd is drawable when it is visible, all parents are not
2054 * minimized, and it is itself not minimized unless we are
2055 * trying to draw its default class icon.
2057 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2059 if( (wnd->dwStyle & WS_MINIMIZE &&
2060 icon && wnd->class->hIcon) ||
2061 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2062 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2063 if( wnd->dwStyle & WS_MINIMIZE ||
2064 !(wnd->dwStyle & WS_VISIBLE) ) break;
2065 return (wnd == NULL);
2069 /*******************************************************************
2070 * GetTopWindow16 (USER.229)
2072 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2074 return GetTopWindow32(hwnd);
2078 /*******************************************************************
2079 * GetTopWindow32 (USER.229)
2081 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2083 WND * wndPtr = WIN_FindWndPtr( hwnd );
2084 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2085 else return 0;
2089 /*******************************************************************
2090 * GetWindow16 (USER.262)
2092 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2094 return GetWindow32( hwnd,rel );
2098 /*******************************************************************
2099 * GetWindow32 (USER32.302)
2101 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2103 WND * wndPtr = WIN_FindWndPtr( hwnd );
2104 if (!wndPtr) return 0;
2105 switch(rel)
2107 case GW_HWNDFIRST:
2108 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2109 else return 0;
2111 case GW_HWNDLAST:
2112 if (!wndPtr->parent) return 0; /* Desktop window */
2113 while (wndPtr->next) wndPtr = wndPtr->next;
2114 return wndPtr->hwndSelf;
2116 case GW_HWNDNEXT:
2117 if (!wndPtr->next) return 0;
2118 return wndPtr->next->hwndSelf;
2120 case GW_HWNDPREV:
2121 if (!wndPtr->parent) return 0; /* Desktop window */
2122 wndPtr = wndPtr->parent->child; /* First sibling */
2123 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2124 while (wndPtr->next)
2126 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2127 wndPtr = wndPtr->next;
2129 return 0;
2131 case GW_OWNER:
2132 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2134 case GW_CHILD:
2135 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2137 return 0;
2141 /*******************************************************************
2142 * GetNextWindow16 (USER.230)
2144 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2146 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2147 return GetWindow16( hwnd, flag );
2150 /*******************************************************************
2151 * ShowOwnedPopups16 (USER.265)
2153 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2155 ShowOwnedPopups32( owner, fShow );
2159 /*******************************************************************
2160 * ShowOwnedPopups32 (USER32.531)
2162 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2164 WND *pWnd = pWndDesktop->child;
2165 while (pWnd)
2167 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2168 (pWnd->dwStyle & WS_POPUP))
2169 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2170 pWnd = pWnd->next;
2172 return TRUE;
2176 /*******************************************************************
2177 * GetLastActivePopup16 (USER.287)
2179 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2181 return GetLastActivePopup32( hwnd );
2184 /*******************************************************************
2185 * GetLastActivePopup32 (USER32.256)
2187 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2189 WND *wndPtr;
2190 wndPtr = WIN_FindWndPtr(hwnd);
2191 if (wndPtr == NULL) return hwnd;
2192 return wndPtr->hwndLastActive;
2196 /*******************************************************************
2197 * WIN_BuildWinArray
2199 * Build an array of pointers to the children of a given window.
2200 * The array must be freed with HeapFree(SystemHeap). Return NULL
2201 * when no windows are found.
2203 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2205 WND **list, **ppWnd;
2206 WND *pWnd;
2207 UINT32 count, skipOwned, skipHidden;
2208 DWORD skipFlags;
2210 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2211 skipOwned = bwaFlags & BWA_SKIPOWNED;
2212 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2213 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2215 /* First count the windows */
2217 if (!wndPtr) wndPtr = pWndDesktop;
2218 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2220 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2221 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2224 if( count )
2226 /* Now build the list of all windows */
2228 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2230 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2232 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2233 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2235 *ppWnd++ = pWnd;
2236 count++;
2239 *ppWnd = NULL;
2241 else count = 0;
2242 } else list = NULL;
2244 if( pTotal ) *pTotal = count;
2245 return list;
2249 /*******************************************************************
2250 * EnumWindows16 (USER.54)
2252 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2254 WND **list, **ppWnd;
2256 /* We have to build a list of all windows first, to avoid */
2257 /* unpleasant side-effects, for instance if the callback */
2258 /* function changes the Z-order of the windows. */
2260 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2262 /* Now call the callback function for every window */
2264 for (ppWnd = list; *ppWnd; ppWnd++)
2266 /* Make sure that the window still exists */
2267 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2268 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2270 HeapFree( SystemHeap, 0, list );
2271 return TRUE;
2275 /*******************************************************************
2276 * EnumWindows32 (USER32.193)
2278 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2280 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2284 /**********************************************************************
2285 * EnumTaskWindows16 (USER.225)
2287 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2288 LPARAM lParam )
2290 WND **list, **ppWnd;
2291 HQUEUE16 hQueue = GetTaskQueue( hTask );
2293 /* This function is the same as EnumWindows(), */
2294 /* except for an added check on the window queue. */
2296 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2298 /* Now call the callback function for every window */
2300 for (ppWnd = list; *ppWnd; ppWnd++)
2302 /* Make sure that the window still exists */
2303 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2304 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2305 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2307 HeapFree( SystemHeap, 0, list );
2308 return TRUE;
2312 /**********************************************************************
2313 * EnumThreadWindows (USER32.190)
2315 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2317 THDB *tdb = THREAD_ID_TO_THDB(id);
2319 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2323 /**********************************************************************
2324 * WIN_EnumChildWindows
2326 * Helper function for EnumChildWindows().
2328 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2329 LPARAM lParam )
2331 WND **childList;
2332 BOOL16 ret = FALSE;
2334 for ( ; *ppWnd; ppWnd++)
2336 /* Make sure that the window still exists */
2337 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2338 /* Build children list first */
2339 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2340 ret = func( (*ppWnd)->hwndSelf, lParam );
2341 if (childList)
2343 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2344 HeapFree( SystemHeap, 0, childList );
2346 if (!ret) return FALSE;
2348 return TRUE;
2352 /**********************************************************************
2353 * EnumChildWindows16 (USER.55)
2355 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2356 LPARAM lParam )
2358 WND **list, *pParent;
2360 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2361 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2362 WIN_EnumChildWindows( list, func, lParam );
2363 HeapFree( SystemHeap, 0, list );
2364 return TRUE;
2368 /**********************************************************************
2369 * EnumChildWindows32 (USER32.178)
2371 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2372 LPARAM lParam )
2374 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2375 lParam );
2379 /*******************************************************************
2380 * AnyPopup16 (USER.52)
2382 BOOL16 WINAPI AnyPopup16(void)
2384 return AnyPopup32();
2388 /*******************************************************************
2389 * AnyPopup32 (USER32.4)
2391 BOOL32 WINAPI AnyPopup32(void)
2393 WND *wndPtr;
2394 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2395 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2396 return FALSE;
2400 /*******************************************************************
2401 * FlashWindow16 (USER.105)
2403 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2405 return FlashWindow32( hWnd, bInvert );
2409 /*******************************************************************
2410 * FlashWindow32 (USER32.202)
2412 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2414 WND *wndPtr = WIN_FindWndPtr(hWnd);
2416 TRACE(win,"%04x\n", hWnd);
2418 if (!wndPtr) return FALSE;
2420 if (wndPtr->dwStyle & WS_MINIMIZE)
2422 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2424 HDC32 hDC = GetDC32(hWnd);
2426 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2427 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2429 ReleaseDC32( hWnd, hDC );
2430 wndPtr->flags |= WIN_NCACTIVATED;
2432 else
2434 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2435 RDW_UPDATENOW | RDW_FRAME, 0 );
2436 wndPtr->flags &= ~WIN_NCACTIVATED;
2438 return TRUE;
2440 else
2442 WPARAM16 wparam;
2443 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2444 else wparam = (hWnd == GetActiveWindow32());
2446 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2447 return wparam;
2452 /*******************************************************************
2453 * SetSysModalWindow16 (USER.188)
2455 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2457 HWND32 hWndOldModal = hwndSysModal;
2458 hwndSysModal = hWnd;
2459 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2460 return hWndOldModal;
2464 /*******************************************************************
2465 * GetSysModalWindow16 (USER.52)
2467 HWND16 WINAPI GetSysModalWindow16(void)
2469 return hwndSysModal;
2473 /*******************************************************************
2474 * GetWindowContextHelpId (USER32.303)
2476 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2478 WND *wnd = WIN_FindWndPtr( hwnd );
2479 if (!wnd) return 0;
2480 return wnd->helpContext;
2484 /*******************************************************************
2485 * SetWindowContextHelpId (USER32.515)
2487 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2489 WND *wnd = WIN_FindWndPtr( hwnd );
2490 if (!wnd) return FALSE;
2491 wnd->helpContext = id;
2492 return TRUE;
2496 /*******************************************************************
2497 * DRAG_QueryUpdate
2499 * recursively find a child that contains spDragInfo->pt point
2500 * and send WM_QUERYDROPOBJECT
2502 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2504 BOOL16 wParam,bResult = 0;
2505 POINT32 pt;
2506 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2507 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2508 RECT32 tempRect;
2510 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2512 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2514 GetWindowRect32(hQueryWnd,&tempRect);
2516 if( !PtInRect32(&tempRect,pt) ||
2517 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2518 return 0;
2520 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2522 tempRect = ptrQueryWnd->rectClient;
2523 if(ptrQueryWnd->dwStyle & WS_CHILD)
2524 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2525 (LPPOINT32)&tempRect, 2 );
2527 if (PtInRect32( &tempRect, pt))
2529 wParam = 0;
2531 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2532 if( ptrWnd->dwStyle & WS_VISIBLE )
2534 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2535 if (PtInRect32( &tempRect, pt )) break;
2538 if(ptrWnd)
2540 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2541 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2542 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2543 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2544 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2547 if(bResult) return bResult;
2549 else wParam = 1;
2551 else wParam = 1;
2553 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2555 ptrDragInfo->hScope = hQueryWnd;
2557 bResult = ( bNoSend )
2558 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2559 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2560 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2561 if( !bResult )
2562 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2564 return bResult;
2568 /*******************************************************************
2569 * DragDetect (USER.465)
2571 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2573 POINT32 pt32;
2574 CONV_POINT16TO32( &pt, &pt32 );
2575 return DragDetect32( hWnd, pt32 );
2578 /*******************************************************************
2579 * DragDetect32 (USER32.151)
2581 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2583 MSG16 msg;
2584 RECT16 rect;
2586 rect.left = pt.x - wDragWidth;
2587 rect.right = pt.x + wDragWidth;
2589 rect.top = pt.y - wDragHeight;
2590 rect.bottom = pt.y + wDragHeight;
2592 SetCapture32(hWnd);
2594 while(1)
2596 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2598 if( msg.message == WM_LBUTTONUP )
2600 ReleaseCapture();
2601 return 0;
2603 if( msg.message == WM_MOUSEMOVE )
2605 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2607 ReleaseCapture();
2608 return 1;
2612 WaitMessage();
2614 return 0;
2617 /******************************************************************************
2618 * DragObject16 (USER.464)
2620 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2621 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2623 MSG16 msg;
2624 LPDRAGINFO lpDragInfo;
2625 SEGPTR spDragInfo;
2626 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2627 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2628 WND *wndPtr = WIN_FindWndPtr(hWnd);
2629 HCURSOR16 hCurrentCursor = 0;
2630 HWND16 hCurrentWnd = 0;
2632 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2633 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2635 if( !lpDragInfo || !spDragInfo ) return 0L;
2637 hBummer = LoadCursor16(0, IDC_BUMMER16);
2639 if( !hBummer || !wndPtr )
2641 GlobalFree16(hDragInfo);
2642 return 0L;
2645 if(hCursor)
2647 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2649 GlobalFree16(hDragInfo);
2650 return 0L;
2653 if( hDragCursor == hCursor ) hDragCursor = 0;
2654 else hCursor = hDragCursor;
2656 hOldCursor = SetCursor32(hDragCursor);
2659 lpDragInfo->hWnd = hWnd;
2660 lpDragInfo->hScope = 0;
2661 lpDragInfo->wFlags = wObj;
2662 lpDragInfo->hList = szList; /* near pointer! */
2663 lpDragInfo->hOfStruct = hOfStruct;
2664 lpDragInfo->l = 0L;
2666 SetCapture32(hWnd);
2667 ShowCursor32( TRUE );
2671 do{ WaitMessage(); }
2672 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2674 *(lpDragInfo+1) = *lpDragInfo;
2676 lpDragInfo->pt = msg.pt;
2678 /* update DRAGINFO struct */
2679 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2681 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2682 hCurrentCursor = hCursor;
2683 else
2685 hCurrentCursor = hBummer;
2686 lpDragInfo->hScope = 0;
2688 if( hCurrentCursor )
2689 SetCursor32(hCurrentCursor);
2691 /* send WM_DRAGLOOP */
2692 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2693 (LPARAM) spDragInfo );
2694 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2695 if( hCurrentWnd != lpDragInfo->hScope )
2697 if( hCurrentWnd )
2698 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2699 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2700 HIWORD(spDragInfo)) );
2701 hCurrentWnd = lpDragInfo->hScope;
2702 if( hCurrentWnd )
2703 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2705 else
2706 if( hCurrentWnd )
2707 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2709 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2711 ReleaseCapture();
2712 ShowCursor32( FALSE );
2714 if( hCursor )
2716 SetCursor32( hOldCursor );
2717 if (hDragCursor) DestroyCursor32( hDragCursor );
2720 if( hCurrentCursor != hBummer )
2721 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2722 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2723 else
2724 msg.lParam = 0;
2725 GlobalFree16(hDragInfo);
2727 return (DWORD)(msg.lParam);