Release 980927
[wine/multimedia.git] / windows / win.c
bloba7dfa12febf4b15e1b8f80b053e7ceb80f1ce18b
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"
36 /* Desktop window */
37 static WND *pWndDesktop = NULL;
39 static HWND32 hwndSysModal = 0;
41 static WORD wDragWidth = 4;
42 static WORD wDragHeight= 3;
44 /***********************************************************************
45 * WIN_FindWndPtr
47 * Return a pointer to the WND structure corresponding to a HWND.
49 WND * WIN_FindWndPtr( HWND32 hwnd )
51 WND * ptr;
53 if (!hwnd || HIWORD(hwnd)) return NULL;
54 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
55 if (ptr->dwMagic != WND_MAGIC) return NULL;
56 if (ptr->hwndSelf != hwnd)
58 ERR( win, "Can't happen: hwnd %04x self pointer is %04x\n",
59 hwnd, ptr->hwndSelf );
60 return NULL;
62 return ptr;
66 /***********************************************************************
67 * WIN_DumpWindow
69 * Dump the content of a window structure to stderr.
71 void WIN_DumpWindow( HWND32 hwnd )
73 WND *ptr;
74 char className[80];
75 int i;
77 if (!(ptr = WIN_FindWndPtr( hwnd )))
79 WARN( win, "%04x is not a window handle\n", hwnd );
80 return;
83 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
84 strcpy( className, "#NULL#" );
86 TRACE( win, "Window %04x (%p):\n", hwnd, ptr );
87 DUMP( "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
88 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%08x\n"
89 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
90 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
91 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
92 ptr->next, ptr->child, ptr->parent, ptr->owner,
93 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
94 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
95 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
96 ptr->text ? ptr->text : "",
97 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
98 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
99 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
100 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
102 if (ptr->class->cbWndExtra)
104 DUMP( "extra bytes:" );
105 for (i = 0; i < ptr->class->cbWndExtra; i++)
106 DUMP( " %02x", *((BYTE*)ptr->wExtra+i) );
107 DUMP( "\n" );
109 DUMP( "\n" );
113 /***********************************************************************
114 * WIN_WalkWindows
116 * Walk the windows tree and print each window on stderr.
118 void WIN_WalkWindows( HWND32 hwnd, int indent )
120 WND *ptr;
121 char className[80];
123 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
124 if (!ptr)
126 WARN( win, "Invalid window handle %04x\n", hwnd );
127 return;
130 if (!indent) /* first time around */
131 DUMP( "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
132 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
134 while (ptr)
136 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
138 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
140 DUMP( "%08lx %-6.4x %-17.17s %08x %08x\n",
141 (DWORD)ptr, ptr->hmemTaskQ, className,
142 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
144 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
145 ptr = ptr->next;
150 /***********************************************************************
151 * WIN_GetXWindow
153 * Return the X window associated to a window.
155 Window WIN_GetXWindow( HWND32 hwnd )
157 WND *wndPtr = WIN_FindWndPtr( hwnd );
158 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
159 return wndPtr ? wndPtr->window : 0;
163 /***********************************************************************
164 * WIN_UnlinkWindow
166 * Remove a window from the siblings linked list.
168 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
170 WND *wndPtr, **ppWnd;
172 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
173 ppWnd = &wndPtr->parent->child;
174 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
175 *ppWnd = wndPtr->next;
176 return TRUE;
180 /***********************************************************************
181 * WIN_LinkWindow
183 * Insert a window into the siblings linked list.
184 * The window is inserted after the specified window, which can also
185 * be specified as HWND_TOP or HWND_BOTTOM.
187 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
189 WND *wndPtr, **ppWnd;
191 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
193 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
195 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
196 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
197 while (*ppWnd) ppWnd = &(*ppWnd)->next;
199 else /* Normal case */
201 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
202 if (!afterPtr) return FALSE;
203 ppWnd = &afterPtr->next;
205 wndPtr->next = *ppWnd;
206 *ppWnd = wndPtr;
207 return TRUE;
211 /***********************************************************************
212 * WIN_FindWinToRepaint
214 * Find a window that needs repaint.
216 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
218 HWND32 hwndRet;
219 WND *pWnd = pWndDesktop;
221 /* Note: the desktop window never gets WM_PAINT messages
222 * The real reason why is because Windows DesktopWndProc
223 * does ValidateRgn inside WM_ERASEBKGND handler.
226 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
228 for ( ; pWnd ; pWnd = pWnd->next )
230 if (!(pWnd->dwStyle & WS_VISIBLE))
232 TRACE(win, "skipping window %04x\n",
233 pWnd->hwndSelf );
234 continue;
236 if ((pWnd->hmemTaskQ == hQueue) &&
237 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
239 if (pWnd->child )
240 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
241 return hwndRet;
244 if (!pWnd) return 0;
246 hwndRet = pWnd->hwndSelf;
248 /* look among siblings if we got a transparent window */
249 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
250 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
252 pWnd = pWnd->next;
254 if (pWnd) hwndRet = pWnd->hwndSelf;
255 TRACE(win,"found %04x\n",hwndRet);
256 return hwndRet;
260 /***********************************************************************
261 * WIN_DestroyWindow
263 * Destroy storage associated to a window. "Internals" p.358
265 static WND* WIN_DestroyWindow( WND* wndPtr )
267 HWND32 hwnd = wndPtr->hwndSelf;
268 WND *pWnd;
270 TRACE(win, "%04x\n", wndPtr->hwndSelf );
272 #ifdef CONFIG_IPC
273 if (main_block)
274 DDE_DestroyWindow(wndPtr->hwndSelf);
275 #endif /* CONFIG_IPC */
277 /* free child windows */
279 while ((pWnd = wndPtr->child))
280 wndPtr->child = WIN_DestroyWindow( pWnd );
282 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
284 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
286 WINPOS_CheckInternalPos( hwnd );
287 if( hwnd == GetCapture32()) ReleaseCapture();
289 /* free resources associated with the window */
291 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
292 PROPERTY_RemoveWindowProps( wndPtr );
294 wndPtr->dwMagic = 0; /* Mark it as invalid */
296 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
298 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
299 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
302 /* toss stale messages from the queue */
304 if( wndPtr->hmemTaskQ )
306 int pos;
307 BOOL32 bPostQuit = FALSE;
308 WPARAM32 wQuitParam = 0;
309 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
311 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
313 if( msgQ->messages[pos].msg.message == WM_QUIT )
315 bPostQuit = TRUE;
316 wQuitParam = msgQ->messages[pos].msg.wParam;
318 QUEUE_RemoveMsg(msgQ, pos);
320 /* repost WM_QUIT to make sure this app exits its message loop */
321 if( bPostQuit ) PostQuitMessage32(wQuitParam);
322 wndPtr->hmemTaskQ = 0;
325 if (!(wndPtr->dwStyle & WS_CHILD))
326 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
327 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
328 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
329 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
330 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
331 wndPtr->hwndSelf = 0;
332 wndPtr->class->cWindows--;
333 wndPtr->class = NULL;
334 pWnd = wndPtr->next;
336 USER_HEAP_FREE( hwnd );
337 return pWnd;
340 /***********************************************************************
341 * WIN_ResetQueueWindows
343 * Reset the queue of all the children of a given window.
344 * Return TRUE if something was done.
346 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
348 BOOL32 ret = FALSE;
350 if (hNew) /* Set a new queue */
352 for (wnd = wnd->child; (wnd); wnd = wnd->next)
354 if (wnd->hmemTaskQ == hQueue)
356 wnd->hmemTaskQ = hNew;
357 ret = TRUE;
359 if (wnd->child)
360 ret |= WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
363 else /* Queue is being destroyed */
365 while (wnd->child)
367 WND *tmp = wnd->child;
368 ret = FALSE;
369 while (tmp)
371 if (tmp->hmemTaskQ == hQueue)
373 DestroyWindow32( tmp->hwndSelf );
374 ret = TRUE;
375 break;
377 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
378 ret = TRUE;
379 else
380 tmp = tmp->next;
382 if (!ret) break;
385 return ret;
388 /***********************************************************************
389 * WIN_CreateDesktopWindow
391 * Create the desktop window.
393 BOOL32 WIN_CreateDesktopWindow(void)
395 CLASS *class;
396 HWND32 hwndDesktop;
398 TRACE(win,"Creating desktop window\n");
400 if (!ICONTITLE_Init() ||
401 !WINPOS_CreateInternalPosAtom() ||
402 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
403 return FALSE;
405 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
406 if (!hwndDesktop) return FALSE;
407 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
409 pWndDesktop->next = NULL;
410 pWndDesktop->child = NULL;
411 pWndDesktop->parent = NULL;
412 pWndDesktop->owner = NULL;
413 pWndDesktop->class = class;
414 pWndDesktop->dwMagic = WND_MAGIC;
415 pWndDesktop->hwndSelf = hwndDesktop;
416 pWndDesktop->hInstance = 0;
417 pWndDesktop->rectWindow.left = 0;
418 pWndDesktop->rectWindow.top = 0;
419 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
420 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
421 pWndDesktop->rectClient = pWndDesktop->rectWindow;
422 pWndDesktop->text = NULL;
423 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
424 pWndDesktop->hrgnUpdate = 0;
425 pWndDesktop->hwndLastActive = hwndDesktop;
426 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
427 WS_CLIPSIBLINGS;
428 pWndDesktop->dwExStyle = 0;
429 pWndDesktop->dce = NULL;
430 pWndDesktop->pVScroll = NULL;
431 pWndDesktop->pHScroll = NULL;
432 pWndDesktop->pProp = NULL;
433 pWndDesktop->wIDmenu = 0;
434 pWndDesktop->helpContext = 0;
435 pWndDesktop->flags = 0;
436 pWndDesktop->window = rootWindow;
437 pWndDesktop->hSysMenu = 0;
438 pWndDesktop->userdata = 0;
440 pWndDesktop->winproc = (WNDPROC16)class->winproc;
442 EVENT_RegisterWindow( pWndDesktop );
443 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
444 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
445 return TRUE;
449 /***********************************************************************
450 * WIN_CreateWindowEx
452 * Implementation of CreateWindowEx().
454 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
455 BOOL32 win32, BOOL32 unicode )
457 CLASS *classPtr;
458 WND *wndPtr;
459 HWND16 hwnd, hwndLinkAfter;
460 POINT32 maxSize, maxPos, minTrack, maxTrack;
461 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
463 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
464 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
465 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
466 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
467 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
469 /* Find the parent window */
471 if (cs->hwndParent)
473 /* Make sure parent is valid */
474 if (!IsWindow32( cs->hwndParent ))
476 WARN( win, "Bad parent %04x\n", cs->hwndParent );
477 return 0;
479 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
480 WARN( win, "No parent for child window\n" );
481 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
484 /* Find the window class */
485 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
487 char buffer[256];
488 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
489 WARN( win, "Bad class '%s'\n", buffer );
490 return 0;
493 /* Fix the coordinates */
495 if (cs->x == CW_USEDEFAULT32)
497 PDB32 *pdb = PROCESS_Current();
498 if ( !(cs->style & (WS_CHILD | WS_POPUP))
499 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
501 cs->x = pdb->env_db->startup_info->dwX;
502 cs->y = pdb->env_db->startup_info->dwY;
504 else
506 cs->x = 0;
507 cs->y = 0;
510 if (cs->cx == CW_USEDEFAULT32)
512 PDB32 *pdb = PROCESS_Current();
513 if ( !(cs->style & (WS_CHILD | WS_POPUP))
514 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
516 cs->cx = pdb->env_db->startup_info->dwXSize;
517 cs->cy = pdb->env_db->startup_info->dwYSize;
519 else
521 cs->cx = 600; /* FIXME */
522 cs->cy = 400;
526 /* Create the window structure */
528 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
529 - sizeof(wndPtr->wExtra) )))
531 TRACE(win, "out of memory\n" );
532 return 0;
535 /* Fill the window structure */
537 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
538 wndPtr->next = NULL;
539 wndPtr->child = NULL;
541 if ((cs->style & WS_CHILD) && cs->hwndParent)
543 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
544 wndPtr->owner = NULL;
546 else
548 wndPtr->parent = pWndDesktop;
549 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
550 wndPtr->owner = NULL;
551 else
552 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
555 wndPtr->window = 0;
556 wndPtr->class = classPtr;
557 wndPtr->winproc = classPtr->winproc;
558 wndPtr->dwMagic = WND_MAGIC;
559 wndPtr->hwndSelf = hwnd;
560 wndPtr->hInstance = cs->hInstance;
561 wndPtr->text = NULL;
562 wndPtr->hmemTaskQ = GetTaskQueue(0);
563 wndPtr->hrgnUpdate = 0;
564 wndPtr->hwndLastActive = hwnd;
565 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
566 wndPtr->dwExStyle = cs->dwExStyle;
567 wndPtr->wIDmenu = 0;
568 wndPtr->helpContext = 0;
569 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
570 wndPtr->pVScroll = NULL;
571 wndPtr->pHScroll = NULL;
572 wndPtr->pProp = NULL;
573 wndPtr->userdata = 0;
574 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
575 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
577 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
579 /* Call the WH_CBT hook */
581 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
583 if (HOOK_IsHooked( WH_CBT ))
585 CBT_CREATEWND32A cbtc;
586 LRESULT ret;
588 cbtc.lpcs = cs;
589 cbtc.hwndInsertAfter = hwndLinkAfter;
590 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
591 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
592 if (ret)
594 TRACE(win, "CBT-hook returned 0\n");
595 USER_HEAP_FREE( hwnd );
596 return 0;
600 /* Increment class window counter */
602 classPtr->cWindows++;
604 /* Correct the window style */
606 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
608 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
609 wndPtr->flags |= WIN_NEED_SIZE;
611 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
613 /* Get class or window DC if needed */
615 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
616 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
617 else wndPtr->dce = NULL;
619 /* Insert the window in the linked list */
621 WIN_LinkWindow( hwnd, hwndLinkAfter );
623 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
625 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
627 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
628 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
629 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
630 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
631 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
634 if(cs->style & WS_CHILD)
636 if(cs->cx < 0) cs->cx = 0;
637 if(cs->cy < 0) cs->cy = 0;
639 else
641 if (cs->cx <= 0) cs->cx = 1;
642 if (cs->cy <= 0) cs->cy = 1;
645 wndPtr->rectWindow.left = cs->x;
646 wndPtr->rectWindow.top = cs->y;
647 wndPtr->rectWindow.right = cs->x + cs->cx;
648 wndPtr->rectWindow.bottom = cs->y + cs->cy;
649 wndPtr->rectClient = wndPtr->rectWindow;
651 /* Create the X window (only for top-level windows, and then only */
652 /* when there's no desktop window) */
654 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
656 XSetWindowAttributes win_attr;
658 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
659 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
661 win_attr.event_mask = ExposureMask | KeyPressMask |
662 KeyReleaseMask | PointerMotionMask |
663 ButtonPressMask | ButtonReleaseMask |
664 FocusChangeMask | StructureNotifyMask;
665 win_attr.override_redirect = FALSE;
666 wndPtr->flags |= WIN_MANAGED;
668 else
670 win_attr.event_mask = ExposureMask | KeyPressMask |
671 KeyReleaseMask | PointerMotionMask |
672 ButtonPressMask | ButtonReleaseMask |
673 FocusChangeMask;
674 win_attr.override_redirect = TRUE;
676 win_attr.colormap = COLOR_GetColormap();
677 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
678 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
679 win_attr.cursor = CURSORICON_XCursor;
680 wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
681 cs->cx, cs->cy, 0, CopyFromParent,
682 InputOutput, CopyFromParent,
683 CWEventMask | CWOverrideRedirect |
684 CWColormap | CWCursor | CWSaveUnder |
685 CWBackingStore, &win_attr );
687 if ((wndPtr->flags & WIN_MANAGED) &&
688 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
690 XSizeHints* size_hints = TSXAllocSizeHints();
692 if (size_hints)
694 size_hints->min_width = size_hints->max_width = cs->cx;
695 size_hints->min_height = size_hints->max_height = cs->cy;
696 size_hints->flags = (PSize | PMinSize | PMaxSize);
697 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
698 XA_WM_NORMAL_HINTS );
699 TSXFree(size_hints);
703 if (cs->hwndParent) /* Get window owner */
705 Window win = WIN_GetXWindow( cs->hwndParent );
706 if (win) TSXSetTransientForHint( display, wndPtr->window, win );
708 EVENT_RegisterWindow( wndPtr );
711 /* Set the window menu */
713 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
715 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
716 else
718 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
719 if (classPtr->menuNameA)
720 cs->hMenu = HIWORD(classPtr->menuNameA) ?
721 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
722 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
723 #else
724 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
725 if (menuName)
727 /* hInstance is still 16-bit in 980215 winelib */
728 if (HIWORD(cs->hInstance) || __winelib)
729 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
730 else
731 /* doesn't work for winelib, since resources are unicode */
732 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
734 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
736 #endif
739 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
741 /* Send the WM_CREATE message
742 * Perhaps we shouldn't allow width/height changes as well.
743 * See p327 in "Internals".
746 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
748 localSend32 = unicode ? SendMessage32W : SendMessage32A;
749 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
751 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
752 NULL, NULL, 0, &wndPtr->rectClient );
753 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
754 maxPos.y - wndPtr->rectWindow.top);
755 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
757 /* Send the size messages */
759 if (!(wndPtr->flags & WIN_NEED_SIZE))
761 /* send it anyway */
762 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
763 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
764 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
765 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
766 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
767 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
768 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
769 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
770 SendMessage32A( hwnd, WM_MOVE, 0,
771 MAKELONG( wndPtr->rectClient.left,
772 wndPtr->rectClient.top ) );
775 /* Show the window, maximizing or minimizing if needed */
777 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
779 RECT16 newPos;
780 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
781 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
782 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
783 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
784 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
785 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
788 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
790 /* Notify the parent window only */
792 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
793 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
794 if( !IsWindow32(hwnd) ) return 0;
797 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
799 /* Call WH_SHELL hook */
801 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
802 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
804 TRACE(win, "created window %04x\n", hwnd);
805 return hwnd;
809 /* Abort window creation */
811 WARN(win, "aborted by WM_xxCREATE!\n");
812 WIN_UnlinkWindow( hwnd );
813 WIN_DestroyWindow( wndPtr );
814 return 0;
818 /***********************************************************************
819 * CreateWindow16 (USER.41)
821 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
822 DWORD style, INT16 x, INT16 y, INT16 width,
823 INT16 height, HWND16 parent, HMENU16 menu,
824 HINSTANCE16 instance, LPVOID data )
826 return CreateWindowEx16( 0, className, windowName, style,
827 x, y, width, height, parent, menu, instance, data );
831 /***********************************************************************
832 * CreateWindowEx16 (USER.452)
834 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
835 LPCSTR windowName, DWORD style, INT16 x,
836 INT16 y, INT16 width, INT16 height,
837 HWND16 parent, HMENU16 menu,
838 HINSTANCE16 instance, LPVOID data )
840 ATOM classAtom;
841 CREATESTRUCT32A cs;
843 /* Find the class atom */
845 if (!(classAtom = GlobalFindAtom32A( className )))
847 fprintf( stderr, "CreateWindowEx16: bad class name " );
848 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
849 else fprintf( stderr, "'%s'\n", className );
850 return 0;
853 /* Fix the coordinates */
855 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
856 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
857 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
858 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
860 /* Create the window */
862 cs.lpCreateParams = data;
863 cs.hInstance = (HINSTANCE32)instance;
864 cs.hMenu = (HMENU32)menu;
865 cs.hwndParent = (HWND32)parent;
866 cs.style = style;
867 cs.lpszName = windowName;
868 cs.lpszClass = className;
869 cs.dwExStyle = exStyle;
870 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
874 /***********************************************************************
875 * CreateWindowEx32A (USER32.83)
877 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
878 LPCSTR windowName, DWORD style, INT32 x,
879 INT32 y, INT32 width, INT32 height,
880 HWND32 parent, HMENU32 menu,
881 HINSTANCE32 instance, LPVOID data )
883 ATOM classAtom;
884 CREATESTRUCT32A cs;
886 /* Find the class atom */
888 if (!(classAtom = GlobalFindAtom32A( className )))
890 fprintf( stderr, "CreateWindowEx32A: bad class name " );
891 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
892 else fprintf( stderr, "'%s'\n", className );
893 return 0;
896 /* Create the window */
898 cs.lpCreateParams = data;
899 cs.hInstance = instance;
900 cs.hMenu = menu;
901 cs.hwndParent = parent;
902 cs.x = x;
903 cs.y = y;
904 cs.cx = width;
905 cs.cy = height;
906 cs.style = style;
907 cs.lpszName = windowName;
908 cs.lpszClass = className;
909 cs.dwExStyle = exStyle;
910 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
914 /***********************************************************************
915 * CreateWindowEx32W (USER32.84)
917 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
918 LPCWSTR windowName, DWORD style, INT32 x,
919 INT32 y, INT32 width, INT32 height,
920 HWND32 parent, HMENU32 menu,
921 HINSTANCE32 instance, LPVOID data )
923 ATOM classAtom;
924 CREATESTRUCT32W cs;
926 /* Find the class atom */
928 if (!(classAtom = GlobalFindAtom32W( className )))
930 if (HIWORD(className))
932 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
933 WARN( win, "Bad class name '%s'\n",cn);
934 HeapFree( GetProcessHeap(), 0, cn );
936 else
937 WARN( win, "Bad class name %p\n", className );
938 return 0;
941 /* Create the window */
943 cs.lpCreateParams = data;
944 cs.hInstance = instance;
945 cs.hMenu = menu;
946 cs.hwndParent = parent;
947 cs.x = x;
948 cs.y = y;
949 cs.cx = width;
950 cs.cy = height;
951 cs.style = style;
952 cs.lpszName = windowName;
953 cs.lpszClass = className;
954 cs.dwExStyle = exStyle;
955 /* Note: we rely on the fact that CREATESTRUCT32A and */
956 /* CREATESTRUCT32W have the same layout. */
957 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
961 /***********************************************************************
962 * WIN_CheckFocus
964 static void WIN_CheckFocus( WND* pWnd )
966 if( GetFocus16() == pWnd->hwndSelf )
967 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
970 /***********************************************************************
971 * WIN_SendDestroyMsg
973 static void WIN_SendDestroyMsg( WND* pWnd )
975 WIN_CheckFocus(pWnd);
977 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
978 if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd );
980 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
982 if( IsWindow32(pWnd->hwndSelf) )
984 WND* pChild = pWnd->child;
985 while( pChild )
987 WIN_SendDestroyMsg( pChild );
988 pChild = pChild->next;
990 WIN_CheckFocus(pWnd);
992 else
993 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
997 /***********************************************************************
998 * DestroyWindow16 (USER.53)
1000 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1002 return DestroyWindow32(hwnd);
1006 /***********************************************************************
1007 * DestroyWindow32 (USER32.135)
1009 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
1011 WND * wndPtr;
1013 TRACE(win, "(%04x)\n", hwnd);
1015 /* Initialization */
1017 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1018 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1020 /* Call hooks */
1022 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1023 return FALSE;
1025 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1027 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1028 /* FIXME: clean up palette - see "Internals" p.352 */
1031 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1032 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1034 /* Notify the parent window only */
1035 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1036 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1037 if( !IsWindow32(hwnd) ) return TRUE;
1040 if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
1042 /* Hide the window */
1044 if (wndPtr->dwStyle & WS_VISIBLE)
1046 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1047 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1048 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1049 if (!IsWindow32(hwnd)) return TRUE;
1052 /* Recursively destroy owned windows */
1054 if( !(wndPtr->dwStyle & WS_CHILD) )
1056 /* make sure top menu popup doesn't get destroyed */
1057 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1059 for (;;)
1061 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1062 while (siblingPtr)
1064 if (siblingPtr->owner == wndPtr)
1065 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1066 break;
1067 else
1068 siblingPtr->owner = NULL;
1069 siblingPtr = siblingPtr->next;
1071 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1072 else break;
1075 if( !Options.managed || EVENT_CheckFocus() )
1076 WINPOS_ActivateOtherWindow(wndPtr);
1078 if( wndPtr->owner &&
1079 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1080 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1083 /* Send destroy messages */
1085 WIN_SendDestroyMsg( wndPtr );
1086 if (!IsWindow32(hwnd)) return TRUE;
1088 /* Unlink now so we won't bother with the children later on */
1090 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1092 /* Destroy the window storage */
1094 WIN_DestroyWindow( wndPtr );
1095 return TRUE;
1099 /***********************************************************************
1100 * CloseWindow16 (USER.43)
1102 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1104 return CloseWindow32( hwnd );
1108 /***********************************************************************
1109 * CloseWindow32 (USER32.56)
1111 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1113 WND * wndPtr = WIN_FindWndPtr( hwnd );
1114 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1115 ShowWindow32( hwnd, SW_MINIMIZE );
1116 return TRUE;
1120 /***********************************************************************
1121 * OpenIcon16 (USER.44)
1123 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1125 return OpenIcon32( hwnd );
1129 /***********************************************************************
1130 * OpenIcon32 (USER32.410)
1132 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1134 if (!IsIconic32( hwnd )) return FALSE;
1135 ShowWindow32( hwnd, SW_SHOWNORMAL );
1136 return TRUE;
1140 /***********************************************************************
1141 * WIN_FindWindow
1143 * Implementation of FindWindow() and FindWindowEx().
1145 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1146 LPCSTR title )
1148 WND *pWnd;
1149 CLASS *pClass = NULL;
1151 if (child)
1153 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1154 if (parent)
1156 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1158 else if (pWnd->parent != pWndDesktop) return 0;
1159 pWnd = pWnd->next;
1161 else
1163 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1164 pWnd = pWnd->child;
1166 if (!pWnd) return 0;
1168 /* For a child window, all siblings will have the same hInstance, */
1169 /* so we can look for the class once and for all. */
1171 if (className && (pWnd->dwStyle & WS_CHILD))
1173 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1174 return 0;
1178 for ( ; pWnd; pWnd = pWnd->next)
1180 if (className && !(pWnd->dwStyle & WS_CHILD))
1182 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1183 continue; /* Skip this window */
1186 if (pClass && (pWnd->class != pClass))
1187 continue; /* Not the right class */
1189 /* Now check the title */
1191 if (!title) return pWnd->hwndSelf;
1192 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1194 return 0;
1199 /***********************************************************************
1200 * FindWindow16 (USER.50)
1202 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1204 return FindWindowEx16( 0, 0, className, title );
1208 /***********************************************************************
1209 * FindWindowEx16 (USER.427)
1211 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1212 SEGPTR className, LPCSTR title )
1214 ATOM atom = 0;
1216 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1217 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1218 title ? title : "");
1220 if (className)
1222 /* If the atom doesn't exist, then no class */
1223 /* with this name exists either. */
1224 if (!(atom = GlobalFindAtom16( className ))) return 0;
1226 return WIN_FindWindow( parent, child, atom, title );
1230 /***********************************************************************
1231 * FindWindow32A (USER32.198)
1233 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1235 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1236 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1237 return ret;
1241 /***********************************************************************
1242 * FindWindowEx32A (USER32.199)
1244 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1245 LPCSTR className, LPCSTR title )
1247 ATOM atom = 0;
1249 if (className)
1251 /* If the atom doesn't exist, then no class */
1252 /* with this name exists either. */
1253 if (!(atom = GlobalFindAtom32A( className )))
1255 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1256 return 0;
1259 return WIN_FindWindow( parent, child, atom, title );
1263 /***********************************************************************
1264 * FindWindowEx32W (USER32.200)
1266 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1267 LPCWSTR className, LPCWSTR title )
1269 ATOM atom = 0;
1270 char *buffer;
1271 HWND32 hwnd;
1273 if (className)
1275 /* If the atom doesn't exist, then no class */
1276 /* with this name exists either. */
1277 if (!(atom = GlobalFindAtom32W( className )))
1279 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1280 return 0;
1283 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1284 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1285 HeapFree( GetProcessHeap(), 0, buffer );
1286 return hwnd;
1290 /***********************************************************************
1291 * FindWindow32W (USER32.201)
1293 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1295 return FindWindowEx32W( 0, 0, className, title );
1299 /**********************************************************************
1300 * WIN_GetDesktop
1302 WND *WIN_GetDesktop(void)
1304 return pWndDesktop;
1308 /**********************************************************************
1309 * GetDesktopWindow16 (USER.286)
1311 HWND16 WINAPI GetDesktopWindow16(void)
1313 return (HWND16)pWndDesktop->hwndSelf;
1317 /**********************************************************************
1318 * GetDesktopWindow32 (USER32.232)
1320 HWND32 WINAPI GetDesktopWindow32(void)
1322 return pWndDesktop->hwndSelf;
1326 /**********************************************************************
1327 * GetDesktopHwnd (USER.278)
1329 * Exactly the same thing as GetDesktopWindow(), but not documented.
1330 * Don't ask me why...
1332 HWND16 WINAPI GetDesktopHwnd(void)
1334 return (HWND16)pWndDesktop->hwndSelf;
1338 /*******************************************************************
1339 * EnableWindow16 (USER.34)
1341 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1343 return EnableWindow32( hwnd, enable );
1347 /*******************************************************************
1348 * EnableWindow32 (USER32.172)
1350 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1352 WND *wndPtr;
1354 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1355 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1357 /* Enable window */
1358 wndPtr->dwStyle &= ~WS_DISABLED;
1359 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1360 return TRUE;
1362 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1364 /* Disable window */
1365 wndPtr->dwStyle |= WS_DISABLED;
1366 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1367 SetFocus32( 0 ); /* A disabled window can't have the focus */
1368 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1369 ReleaseCapture(); /* A disabled window can't capture the mouse */
1370 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1371 return FALSE;
1373 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1377 /***********************************************************************
1378 * IsWindowEnabled16 (USER.35)
1380 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1382 return IsWindowEnabled32(hWnd);
1386 /***********************************************************************
1387 * IsWindowEnabled32 (USER32.349)
1389 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1391 WND * wndPtr;
1393 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1394 return !(wndPtr->dwStyle & WS_DISABLED);
1398 /***********************************************************************
1399 * IsWindowUnicode (USER32.350)
1401 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1403 WND * wndPtr;
1405 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1406 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1410 /**********************************************************************
1411 * GetWindowWord16 (USER.133)
1413 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1415 return GetWindowWord32( hwnd, offset );
1419 /**********************************************************************
1420 * GetWindowWord32 (USER32.314)
1422 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1424 WND * wndPtr = WIN_FindWndPtr( hwnd );
1425 if (!wndPtr) return 0;
1426 if (offset >= 0)
1428 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1430 WARN( win, "Invalid offset %d\n", offset );
1431 return 0;
1433 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1435 switch(offset)
1437 case GWW_ID:
1438 if (HIWORD(wndPtr->wIDmenu))
1439 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1440 wndPtr->wIDmenu);
1441 return (WORD)wndPtr->wIDmenu;
1442 case GWW_HWNDPARENT:
1443 return wndPtr->parent ?
1444 wndPtr->parent->hwndSelf : (
1445 wndPtr->owner ?
1446 wndPtr->owner->hwndSelf :
1448 case GWW_HINSTANCE:
1449 if (HIWORD(wndPtr->hInstance))
1450 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1451 wndPtr->hInstance);
1452 return (WORD)wndPtr->hInstance;
1453 default:
1454 WARN( win, "Invalid offset %d\n", offset );
1455 return 0;
1460 /**********************************************************************
1461 * WIN_GetWindowInstance
1463 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1465 WND * wndPtr = WIN_FindWndPtr( hwnd );
1466 if (!wndPtr) return (HINSTANCE32)0;
1467 return wndPtr->hInstance;
1471 /**********************************************************************
1472 * SetWindowWord16 (USER.134)
1474 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1476 return SetWindowWord32( hwnd, offset, newval );
1480 /**********************************************************************
1481 * SetWindowWord32 (USER32.524)
1483 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1485 WORD *ptr, retval;
1486 WND * wndPtr = WIN_FindWndPtr( hwnd );
1487 if (!wndPtr) return 0;
1488 if (offset >= 0)
1490 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1492 WARN( win, "Invalid offset %d\n", offset );
1493 return 0;
1495 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1497 else switch(offset)
1499 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1500 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1501 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1502 default:
1503 WARN( win, "Invalid offset %d\n", offset );
1504 return 0;
1506 retval = *ptr;
1507 *ptr = newval;
1508 return retval;
1512 /**********************************************************************
1513 * WIN_GetWindowLong
1515 * Helper function for GetWindowLong().
1517 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1519 LONG retval;
1520 WND * wndPtr = WIN_FindWndPtr( hwnd );
1521 if (!wndPtr) return 0;
1522 if (offset >= 0)
1524 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1526 WARN( win, "Invalid offset %d\n", offset );
1527 return 0;
1529 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1530 /* Special case for dialog window procedure */
1531 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1532 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1533 return retval;
1535 switch(offset)
1537 case GWL_USERDATA: return wndPtr->userdata;
1538 case GWL_STYLE: return wndPtr->dwStyle;
1539 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1540 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1541 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1542 type );
1543 case GWL_HWNDPARENT: return wndPtr->parent ?
1544 (HWND32)wndPtr->parent->hwndSelf : 0;
1545 case GWL_HINSTANCE: return wndPtr->hInstance;
1546 default:
1547 WARN( win, "Unknown offset %d\n", offset );
1549 return 0;
1553 /**********************************************************************
1554 * WIN_SetWindowLong
1556 * Helper function for SetWindowLong().
1558 * 0 is the failure code. However, in the case of failure SetLastError
1559 * must be set to distinguish between a 0 return value and a failure.
1561 * FIXME: The error values for SetLastError may not be right. Can
1562 * someone check with the real thing?
1564 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1565 WINDOWPROCTYPE type )
1567 LONG *ptr, retval;
1568 WND * wndPtr = WIN_FindWndPtr( hwnd );
1569 STYLESTRUCT style;
1571 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1573 if (!wndPtr)
1575 /* Is this the right error? */
1576 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1577 return 0;
1580 if (offset >= 0)
1582 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1584 WARN( win, "Invalid offset %d\n", offset );
1586 /* Is this the right error? */
1587 SetLastError( ERROR_OUTOFMEMORY );
1589 return 0;
1591 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1592 /* Special case for dialog window procedure */
1593 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1595 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1596 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1597 type, WIN_PROC_WINDOW );
1598 return retval;
1601 else switch(offset)
1603 case GWL_ID:
1604 ptr = (DWORD*)&wndPtr->wIDmenu;
1605 break;
1606 case GWL_HINSTANCE:
1607 return SetWindowWord32( hwnd, offset, newval );
1608 case GWL_WNDPROC:
1609 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1610 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1611 type, WIN_PROC_WINDOW );
1612 return retval;
1613 case GWL_STYLE:
1614 style.styleOld = wndPtr->dwStyle;
1615 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1616 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1618 if (wndPtr->flags & WIN_ISWIN32)
1619 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1620 wndPtr->dwStyle = style.styleNew;
1621 if (wndPtr->flags & WIN_ISWIN32)
1622 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1623 return style.styleOld;
1625 case GWL_USERDATA:
1626 ptr = &wndPtr->userdata;
1627 break;
1628 case GWL_EXSTYLE:
1629 style.styleOld = wndPtr->dwExStyle;
1630 style.styleNew = newval;
1631 if (wndPtr->flags & WIN_ISWIN32)
1632 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1633 wndPtr->dwExStyle = newval;
1634 if (wndPtr->flags & WIN_ISWIN32)
1635 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1636 return style.styleOld;
1638 default:
1639 WARN( win, "Invalid offset %d\n", offset );
1641 /* Don't think this is right error but it should do */
1642 SetLastError( ERROR_OUTOFMEMORY );
1644 return 0;
1646 retval = *ptr;
1647 *ptr = newval;
1648 return retval;
1652 /**********************************************************************
1653 * GetWindowLong16 (USER.135)
1655 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1657 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1661 /**********************************************************************
1662 * GetWindowLong32A (USER32.305)
1664 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1666 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1670 /**********************************************************************
1671 * GetWindowLong32W (USER32.306)
1673 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1675 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1679 /**********************************************************************
1680 * SetWindowLong16 (USER.136)
1682 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1684 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1688 /**********************************************************************
1689 * SetWindowLong32A (USER32.517)
1691 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1693 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1697 /**********************************************************************
1698 * SetWindowLong32W (USER32.518) Set window attribute
1700 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1701 * value in a window's extra memory.
1703 * The _hwnd_ parameter specifies the window. is the handle to a
1704 * window that has extra memory. The _newval_ parameter contains the
1705 * new attribute or extra memory value. If positive, the _offset_
1706 * parameter is the byte-addressed location in the window's extra
1707 * memory to set. If negative, _offset_ specifies the window
1708 * attribute to set, and should be one of the following values:
1710 * GWL_EXSTYLE The window's extended window style
1712 * GWL_STYLE The window's window style.
1714 * GWL_WNDPROC Pointer to the window's window procedure.
1716 * GWL_HINSTANCE The window's pplication instance handle.
1718 * GWL_ID The window's identifier.
1720 * GWL_USERDATA The window's user-specified data.
1722 * If the window is a dialog box, the _offset_ parameter can be one of
1723 * the following values:
1725 * DWL_DLGPROC The address of the window's dialog box procedure.
1727 * DWL_MSGRESULT The return value of a message
1728 * that the dialog box procedure processed.
1730 * DWL_USER Application specific information.
1732 * RETURNS
1734 * If successful, returns the previous value located at _offset_. Otherwise,
1735 * returns 0.
1737 * NOTES
1739 * Extra memory for a window class is specified by a nonzero cbWndExtra
1740 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1741 * time of class creation.
1743 * Using GWL_WNDPROC to set a new window procedure effectively creates
1744 * a window subclass. Use CallWindowProc() in the new windows procedure
1745 * to pass messages to the superclass's window procedure.
1747 * The user data is reserved for use by the application which created
1748 * the window.
1750 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1751 * instead, call the EnableWindow() function to change the window's
1752 * disabled state.
1754 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1755 * SetParent() instead.
1757 * BUGS
1759 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1761 * CONFORMANCE
1763 * ECMA-234, Win32
1766 LONG WINAPI SetWindowLong32W(
1767 HWND32 hwnd, /* window to alter */
1768 INT32 offset, /* offset, in bytes, of location to alter */
1769 LONG newval /* new value of location */
1771 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1775 /*******************************************************************
1776 * GetWindowText16 (USER.36)
1778 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1780 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1784 /*******************************************************************
1785 * GetWindowText32A (USER32.309)
1787 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1789 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1790 (LPARAM)lpString );
1793 /*******************************************************************
1794 * InternalGetWindowText (USER32.326)
1796 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1798 FIXME(win,"(0x%08x,%s,0x%x),stub!\n",hwnd,debugstr_w(lpString),nMaxCount);
1799 return GetWindowText32W(hwnd,lpString,nMaxCount);
1803 /*******************************************************************
1804 * GetWindowText32W (USER32.312)
1806 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1808 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1809 (LPARAM)lpString );
1813 /*******************************************************************
1814 * SetWindowText16 (USER.37)
1816 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1818 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1822 /*******************************************************************
1823 * SetWindowText32A (USER32.521)
1825 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1827 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1831 /*******************************************************************
1832 * SetWindowText32W (USER32.523)
1834 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1836 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1840 /*******************************************************************
1841 * GetWindowTextLength16 (USER.38)
1843 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1845 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1849 /*******************************************************************
1850 * GetWindowTextLength32A (USER32.310)
1852 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1854 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1857 /*******************************************************************
1858 * GetWindowTextLength32W (USER32.311)
1860 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1862 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1866 /*******************************************************************
1867 * IsWindow16 (USER.47)
1869 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1871 return IsWindow32( hwnd );
1874 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1876 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1877 HWND16 hwnd = (HWND16)stack[2];
1879 AX_reg(context) = IsWindow32( hwnd );
1880 ES_reg(context) = USER_HeapSel;
1884 /*******************************************************************
1885 * IsWindow32 (USER32.348)
1887 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1889 WND * wndPtr = WIN_FindWndPtr( hwnd );
1890 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1894 /*****************************************************************
1895 * GetParent16 (USER.46)
1897 HWND16 WINAPI GetParent16( HWND16 hwnd )
1899 return (HWND16)GetParent32( hwnd );
1903 /*****************************************************************
1904 * GetParent32 (USER32.278)
1906 HWND32 WINAPI GetParent32( HWND32 hwnd )
1908 WND *wndPtr = WIN_FindWndPtr(hwnd);
1909 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1910 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1911 return wndPtr ? wndPtr->hwndSelf : 0;
1914 /*****************************************************************
1915 * WIN_GetTopParent
1917 * Get the top-level parent for a child window.
1919 WND* WIN_GetTopParentPtr( WND* pWnd )
1921 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1922 return pWnd;
1925 /*****************************************************************
1926 * WIN_GetTopParent
1928 * Get the top-level parent for a child window.
1930 HWND32 WIN_GetTopParent( HWND32 hwnd )
1932 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1933 return wndPtr ? wndPtr->hwndSelf : 0;
1937 /*****************************************************************
1938 * SetParent16 (USER.233)
1940 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1942 return SetParent32( hwndChild, hwndNewParent );
1946 /*****************************************************************
1947 * SetParent32 (USER32.495)
1949 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1951 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1952 WND *pWndParent = (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent )
1953 : pWndDesktop;
1955 if( wndPtr && pWndParent && (wndPtr != pWndDesktop) )
1957 WND* pWndPrev = wndPtr->parent;
1959 if( pWndParent != pWndPrev )
1961 BOOL32 bFixupDCE = IsWindowVisible32(hwndChild);
1963 if ( wndPtr->window )
1965 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
1967 TSXDestroyWindow( display, wndPtr->window );
1968 wndPtr->window = None;
1970 else if( bFixupDCE )
1971 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1973 WIN_UnlinkWindow(hwndChild);
1974 wndPtr->parent = pWndParent;
1976 /* FIXME: Create an X counterpart for reparented top-level windows
1977 * when not in the desktop mode. */
1979 if ( pWndParent != pWndDesktop ) wndPtr->dwStyle |= WS_CHILD;
1980 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1982 if( bFixupDCE )
1984 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1985 UpdateWindow32(hwndChild);
1988 return pWndPrev->hwndSelf;
1989 } /* failure */
1990 return 0;
1994 /*******************************************************************
1995 * IsChild16 (USER.48)
1997 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
1999 return IsChild32(parent,child);
2003 /*******************************************************************
2004 * IsChild32 (USER32.339)
2006 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
2008 WND * wndPtr = WIN_FindWndPtr( child );
2009 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2011 wndPtr = wndPtr->parent;
2012 if (wndPtr->hwndSelf == parent) return TRUE;
2014 return FALSE;
2018 /***********************************************************************
2019 * IsWindowVisible16 (USER.49)
2021 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2023 return IsWindowVisible32(hwnd);
2027 /***********************************************************************
2028 * IsWindowVisible32 (USER32.351)
2030 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
2032 WND *wndPtr = WIN_FindWndPtr( hwnd );
2033 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2035 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2036 wndPtr = wndPtr->parent;
2038 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2042 /***********************************************************************
2043 * WIN_IsWindowDrawable
2045 * hwnd is drawable when it is visible, all parents are not
2046 * minimized, and it is itself not minimized unless we are
2047 * trying to draw its default class icon.
2049 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2051 if( (wnd->dwStyle & WS_MINIMIZE &&
2052 icon && wnd->class->hIcon) ||
2053 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2054 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2055 if( wnd->dwStyle & WS_MINIMIZE ||
2056 !(wnd->dwStyle & WS_VISIBLE) ) break;
2057 return (wnd == NULL);
2061 /*******************************************************************
2062 * GetTopWindow16 (USER.229)
2064 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2066 return GetTopWindow32(hwnd);
2070 /*******************************************************************
2071 * GetTopWindow32 (USER.229)
2073 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2075 WND * wndPtr = WIN_FindWndPtr( hwnd );
2076 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2077 else return 0;
2081 /*******************************************************************
2082 * GetWindow16 (USER.262)
2084 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2086 return GetWindow32( hwnd,rel );
2090 /*******************************************************************
2091 * GetWindow32 (USER32.302)
2093 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2095 WND * wndPtr = WIN_FindWndPtr( hwnd );
2096 if (!wndPtr) return 0;
2097 switch(rel)
2099 case GW_HWNDFIRST:
2100 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2101 else return 0;
2103 case GW_HWNDLAST:
2104 if (!wndPtr->parent) return 0; /* Desktop window */
2105 while (wndPtr->next) wndPtr = wndPtr->next;
2106 return wndPtr->hwndSelf;
2108 case GW_HWNDNEXT:
2109 if (!wndPtr->next) return 0;
2110 return wndPtr->next->hwndSelf;
2112 case GW_HWNDPREV:
2113 if (!wndPtr->parent) return 0; /* Desktop window */
2114 wndPtr = wndPtr->parent->child; /* First sibling */
2115 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2116 while (wndPtr->next)
2118 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2119 wndPtr = wndPtr->next;
2121 return 0;
2123 case GW_OWNER:
2124 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2126 case GW_CHILD:
2127 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2129 return 0;
2133 /*******************************************************************
2134 * GetNextWindow16 (USER.230)
2136 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2138 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2139 return GetWindow16( hwnd, flag );
2142 /*******************************************************************
2143 * ShowOwnedPopups16 (USER.265)
2145 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2147 ShowOwnedPopups32( owner, fShow );
2151 /*******************************************************************
2152 * ShowOwnedPopups32 (USER32.531)
2154 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2156 WND *pWnd = pWndDesktop->child;
2157 while (pWnd)
2159 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2160 (pWnd->dwStyle & WS_POPUP))
2161 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2162 pWnd = pWnd->next;
2164 return TRUE;
2168 /*******************************************************************
2169 * GetLastActivePopup16 (USER.287)
2171 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2173 return GetLastActivePopup32( hwnd );
2176 /*******************************************************************
2177 * GetLastActivePopup32 (USER32.256)
2179 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2181 WND *wndPtr;
2182 wndPtr = WIN_FindWndPtr(hwnd);
2183 if (wndPtr == NULL) return hwnd;
2184 return wndPtr->hwndLastActive;
2188 /*******************************************************************
2189 * WIN_BuildWinArray
2191 * Build an array of pointers to the children of a given window.
2192 * The array must be freed with HeapFree(SystemHeap). Return NULL
2193 * when no windows are found.
2195 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2197 WND **list, **ppWnd;
2198 WND *pWnd;
2199 UINT32 count, skipOwned, skipHidden;
2200 DWORD skipFlags;
2202 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2203 skipOwned = bwaFlags & BWA_SKIPOWNED;
2204 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2205 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2207 /* First count the windows */
2209 if (!wndPtr) wndPtr = pWndDesktop;
2210 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2212 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2213 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2216 if( count )
2218 /* Now build the list of all windows */
2220 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2222 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2224 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2225 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2227 *ppWnd++ = pWnd;
2228 count++;
2231 *ppWnd = NULL;
2233 else count = 0;
2234 } else list = NULL;
2236 if( pTotal ) *pTotal = count;
2237 return list;
2241 /*******************************************************************
2242 * EnumWindows16 (USER.54)
2244 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2246 WND **list, **ppWnd;
2248 /* We have to build a list of all windows first, to avoid */
2249 /* unpleasant side-effects, for instance if the callback */
2250 /* function changes the Z-order of the windows. */
2252 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2254 /* Now call the callback function for every window */
2256 for (ppWnd = list; *ppWnd; ppWnd++)
2258 /* Make sure that the window still exists */
2259 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2260 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2262 HeapFree( SystemHeap, 0, list );
2263 return TRUE;
2267 /*******************************************************************
2268 * EnumWindows32 (USER32.193)
2270 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2272 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2276 /**********************************************************************
2277 * EnumTaskWindows16 (USER.225)
2279 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2280 LPARAM lParam )
2282 WND **list, **ppWnd;
2283 HQUEUE16 hQueue = GetTaskQueue( hTask );
2285 /* This function is the same as EnumWindows(), */
2286 /* except for an added check on the window queue. */
2288 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2290 /* Now call the callback function for every window */
2292 for (ppWnd = list; *ppWnd; ppWnd++)
2294 /* Make sure that the window still exists */
2295 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2296 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2297 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2299 HeapFree( SystemHeap, 0, list );
2300 return TRUE;
2304 /**********************************************************************
2305 * EnumThreadWindows (USER32.190)
2307 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2309 THDB *tdb = THREAD_ID_TO_THDB(id);
2311 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2315 /**********************************************************************
2316 * WIN_EnumChildWindows
2318 * Helper function for EnumChildWindows().
2320 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2321 LPARAM lParam )
2323 WND **childList;
2324 BOOL16 ret = FALSE;
2326 for ( ; *ppWnd; ppWnd++)
2328 /* Make sure that the window still exists */
2329 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2330 /* Build children list first */
2331 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2332 ret = func( (*ppWnd)->hwndSelf, lParam );
2333 if (childList)
2335 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2336 HeapFree( SystemHeap, 0, childList );
2338 if (!ret) return FALSE;
2340 return TRUE;
2344 /**********************************************************************
2345 * EnumChildWindows16 (USER.55)
2347 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2348 LPARAM lParam )
2350 WND **list, *pParent;
2352 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2353 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2354 WIN_EnumChildWindows( list, func, lParam );
2355 HeapFree( SystemHeap, 0, list );
2356 return TRUE;
2360 /**********************************************************************
2361 * EnumChildWindows32 (USER32.178)
2363 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2364 LPARAM lParam )
2366 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2367 lParam );
2371 /*******************************************************************
2372 * AnyPopup16 (USER.52)
2374 BOOL16 WINAPI AnyPopup16(void)
2376 return AnyPopup32();
2380 /*******************************************************************
2381 * AnyPopup32 (USER32.4)
2383 BOOL32 WINAPI AnyPopup32(void)
2385 WND *wndPtr;
2386 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2387 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2388 return FALSE;
2392 /*******************************************************************
2393 * FlashWindow16 (USER.105)
2395 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2397 return FlashWindow32( hWnd, bInvert );
2401 /*******************************************************************
2402 * FlashWindow32 (USER32.202)
2404 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2406 WND *wndPtr = WIN_FindWndPtr(hWnd);
2408 TRACE(win,"%04x\n", hWnd);
2410 if (!wndPtr) return FALSE;
2412 if (wndPtr->dwStyle & WS_MINIMIZE)
2414 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2416 HDC32 hDC = GetDC32(hWnd);
2418 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2419 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2421 ReleaseDC32( hWnd, hDC );
2422 wndPtr->flags |= WIN_NCACTIVATED;
2424 else
2426 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2427 RDW_UPDATENOW | RDW_FRAME, 0 );
2428 wndPtr->flags &= ~WIN_NCACTIVATED;
2430 return TRUE;
2432 else
2434 WPARAM16 wparam;
2435 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2436 else wparam = (hWnd == GetActiveWindow32());
2438 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2439 return wparam;
2444 /*******************************************************************
2445 * SetSysModalWindow16 (USER.188)
2447 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2449 HWND32 hWndOldModal = hwndSysModal;
2450 hwndSysModal = hWnd;
2451 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2452 return hWndOldModal;
2456 /*******************************************************************
2457 * GetSysModalWindow16 (USER.52)
2459 HWND16 WINAPI GetSysModalWindow16(void)
2461 return hwndSysModal;
2465 /*******************************************************************
2466 * GetWindowContextHelpId (USER32.303)
2468 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2470 WND *wnd = WIN_FindWndPtr( hwnd );
2471 if (!wnd) return 0;
2472 return wnd->helpContext;
2476 /*******************************************************************
2477 * SetWindowContextHelpId (USER32.515)
2479 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2481 WND *wnd = WIN_FindWndPtr( hwnd );
2482 if (!wnd) return FALSE;
2483 wnd->helpContext = id;
2484 return TRUE;
2488 /*******************************************************************
2489 * DRAG_QueryUpdate
2491 * recursively find a child that contains spDragInfo->pt point
2492 * and send WM_QUERYDROPOBJECT
2494 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2496 BOOL16 wParam,bResult = 0;
2497 POINT32 pt;
2498 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2499 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2500 RECT32 tempRect;
2502 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2504 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2506 GetWindowRect32(hQueryWnd,&tempRect);
2508 if( !PtInRect32(&tempRect,pt) ||
2509 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2510 return 0;
2512 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2514 tempRect = ptrQueryWnd->rectClient;
2515 if(ptrQueryWnd->dwStyle & WS_CHILD)
2516 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2517 (LPPOINT32)&tempRect, 2 );
2519 if (PtInRect32( &tempRect, pt))
2521 wParam = 0;
2523 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2524 if( ptrWnd->dwStyle & WS_VISIBLE )
2526 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2527 if (PtInRect32( &tempRect, pt )) break;
2530 if(ptrWnd)
2532 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2533 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2534 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2535 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2536 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2539 if(bResult) return bResult;
2541 else wParam = 1;
2543 else wParam = 1;
2545 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2547 ptrDragInfo->hScope = hQueryWnd;
2549 bResult = ( bNoSend )
2550 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2551 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2552 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2553 if( !bResult )
2554 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2556 return bResult;
2560 /*******************************************************************
2561 * DragDetect (USER.465)
2563 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2565 POINT32 pt32;
2566 CONV_POINT16TO32( &pt, &pt32 );
2567 return DragDetect32( hWnd, pt32 );
2570 /*******************************************************************
2571 * DragDetect32 (USER32.151)
2573 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2575 MSG16 msg;
2576 RECT16 rect;
2578 rect.left = pt.x - wDragWidth;
2579 rect.right = pt.x + wDragWidth;
2581 rect.top = pt.y - wDragHeight;
2582 rect.bottom = pt.y + wDragHeight;
2584 SetCapture32(hWnd);
2586 while(1)
2588 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2590 if( msg.message == WM_LBUTTONUP )
2592 ReleaseCapture();
2593 return 0;
2595 if( msg.message == WM_MOUSEMOVE )
2597 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2599 ReleaseCapture();
2600 return 1;
2604 WaitMessage();
2606 return 0;
2609 /******************************************************************************
2610 * DragObject16 (USER.464)
2612 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2613 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2615 MSG16 msg;
2616 LPDRAGINFO lpDragInfo;
2617 SEGPTR spDragInfo;
2618 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2619 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2620 WND *wndPtr = WIN_FindWndPtr(hWnd);
2621 HCURSOR16 hCurrentCursor = 0;
2622 HWND16 hCurrentWnd = 0;
2624 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2625 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2627 if( !lpDragInfo || !spDragInfo ) return 0L;
2629 hBummer = LoadCursor16(0, IDC_BUMMER16);
2631 if( !hBummer || !wndPtr )
2633 GlobalFree16(hDragInfo);
2634 return 0L;
2637 if(hCursor)
2639 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2641 GlobalFree16(hDragInfo);
2642 return 0L;
2645 if( hDragCursor == hCursor ) hDragCursor = 0;
2646 else hCursor = hDragCursor;
2648 hOldCursor = SetCursor32(hDragCursor);
2651 lpDragInfo->hWnd = hWnd;
2652 lpDragInfo->hScope = 0;
2653 lpDragInfo->wFlags = wObj;
2654 lpDragInfo->hList = szList; /* near pointer! */
2655 lpDragInfo->hOfStruct = hOfStruct;
2656 lpDragInfo->l = 0L;
2658 SetCapture32(hWnd);
2659 ShowCursor32( TRUE );
2663 do{ WaitMessage(); }
2664 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2666 *(lpDragInfo+1) = *lpDragInfo;
2668 lpDragInfo->pt = msg.pt;
2670 /* update DRAGINFO struct */
2671 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2673 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2674 hCurrentCursor = hCursor;
2675 else
2677 hCurrentCursor = hBummer;
2678 lpDragInfo->hScope = 0;
2680 if( hCurrentCursor )
2681 SetCursor32(hCurrentCursor);
2683 /* send WM_DRAGLOOP */
2684 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2685 (LPARAM) spDragInfo );
2686 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2687 if( hCurrentWnd != lpDragInfo->hScope )
2689 if( hCurrentWnd )
2690 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2691 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2692 HIWORD(spDragInfo)) );
2693 hCurrentWnd = lpDragInfo->hScope;
2694 if( hCurrentWnd )
2695 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2697 else
2698 if( hCurrentWnd )
2699 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2701 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2703 ReleaseCapture();
2704 ShowCursor32( FALSE );
2706 if( hCursor )
2708 SetCursor32( hOldCursor );
2709 if (hDragCursor) DestroyCursor32( hDragCursor );
2712 if( hCurrentCursor != hBummer )
2713 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2714 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2715 else
2716 msg.lParam = 0;
2717 GlobalFree16(hDragInfo);
2719 return (DWORD)(msg.lParam);