Bugfix: memory overwrite bug.
[wine/multimedia.git] / windows / win.c
blob7a116dac7bc525447d7e75d526a964dc818bdbb5
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"
133 " Text");
135 while (ptr)
137 DUMP( "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
139 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
141 DUMP( "%08lx %-6.4x %-17.17s %08x %08x %.14s\n",
142 (DWORD)ptr, ptr->hmemTaskQ, className,
143 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc,
144 ptr->text?ptr->text:"<null>");
146 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
147 ptr = ptr->next;
152 /***********************************************************************
153 * WIN_GetXWindow
155 * Return the X window associated to a window.
157 Window WIN_GetXWindow( HWND32 hwnd )
159 WND *wndPtr = WIN_FindWndPtr( hwnd );
160 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
161 return wndPtr ? wndPtr->window : 0;
165 /***********************************************************************
166 * WIN_UnlinkWindow
168 * Remove a window from the siblings linked list.
170 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
172 WND *wndPtr, **ppWnd;
174 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
175 ppWnd = &wndPtr->parent->child;
176 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
177 *ppWnd = wndPtr->next;
178 return TRUE;
182 /***********************************************************************
183 * WIN_LinkWindow
185 * Insert a window into the siblings linked list.
186 * The window is inserted after the specified window, which can also
187 * be specified as HWND_TOP or HWND_BOTTOM.
189 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
191 WND *wndPtr, **ppWnd;
193 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
195 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
197 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
198 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
199 while (*ppWnd) ppWnd = &(*ppWnd)->next;
201 else /* Normal case */
203 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
204 if (!afterPtr) return FALSE;
205 ppWnd = &afterPtr->next;
207 wndPtr->next = *ppWnd;
208 *ppWnd = wndPtr;
209 return TRUE;
213 /***********************************************************************
214 * WIN_FindWinToRepaint
216 * Find a window that needs repaint.
218 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
220 HWND32 hwndRet;
221 WND *pWnd = pWndDesktop;
223 /* Note: the desktop window never gets WM_PAINT messages
224 * The real reason why is because Windows DesktopWndProc
225 * does ValidateRgn inside WM_ERASEBKGND handler.
228 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
230 for ( ; pWnd ; pWnd = pWnd->next )
232 if (!(pWnd->dwStyle & WS_VISIBLE))
234 TRACE(win, "skipping window %04x\n",
235 pWnd->hwndSelf );
236 continue;
238 if ((pWnd->hmemTaskQ == hQueue) &&
239 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
241 if (pWnd->child )
242 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
243 return hwndRet;
246 if (!pWnd) return 0;
248 hwndRet = pWnd->hwndSelf;
250 /* look among siblings if we got a transparent window */
251 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
252 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
254 pWnd = pWnd->next;
256 if (pWnd) hwndRet = pWnd->hwndSelf;
257 TRACE(win,"found %04x\n",hwndRet);
258 return hwndRet;
262 /***********************************************************************
263 * WIN_DestroyWindow
265 * Destroy storage associated to a window. "Internals" p.358
267 static WND* WIN_DestroyWindow( WND* wndPtr )
269 HWND32 hwnd = wndPtr->hwndSelf;
270 WND *pWnd;
272 TRACE(win, "%04x\n", wndPtr->hwndSelf );
274 #ifdef CONFIG_IPC
275 if (main_block)
276 DDE_DestroyWindow(wndPtr->hwndSelf);
277 #endif /* CONFIG_IPC */
279 /* free child windows */
281 while ((pWnd = wndPtr->child))
282 wndPtr->child = WIN_DestroyWindow( pWnd );
284 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
286 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
288 WINPOS_CheckInternalPos( hwnd );
289 if( hwnd == GetCapture32()) ReleaseCapture();
291 /* free resources associated with the window */
293 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
294 PROPERTY_RemoveWindowProps( wndPtr );
296 wndPtr->dwMagic = 0; /* Mark it as invalid */
298 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
300 if (wndPtr->hrgnUpdate > 1) DeleteObject32( wndPtr->hrgnUpdate );
301 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
304 /* toss stale messages from the queue */
306 if( wndPtr->hmemTaskQ )
308 int pos;
309 BOOL32 bPostQuit = FALSE;
310 WPARAM32 wQuitParam = 0;
311 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
313 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
315 if( msgQ->messages[pos].msg.message == WM_QUIT )
317 bPostQuit = TRUE;
318 wQuitParam = msgQ->messages[pos].msg.wParam;
320 QUEUE_RemoveMsg(msgQ, pos);
322 /* repost WM_QUIT to make sure this app exits its message loop */
323 if( bPostQuit ) PostQuitMessage32(wQuitParam);
324 wndPtr->hmemTaskQ = 0;
327 if (!(wndPtr->dwStyle & WS_CHILD))
328 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
329 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
330 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
331 DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */
332 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
333 wndPtr->hwndSelf = 0;
334 wndPtr->class->cWindows--;
335 wndPtr->class = NULL;
336 pWnd = wndPtr->next;
338 USER_HEAP_FREE( hwnd );
339 return pWnd;
342 /***********************************************************************
343 * WIN_ResetQueueWindows
345 * Reset the queue of all the children of a given window.
346 * Return TRUE if something was done.
348 BOOL32 WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
350 BOOL32 ret = FALSE;
352 if (hNew) /* Set a new queue */
354 for (wnd = wnd->child; (wnd); wnd = wnd->next)
356 if (wnd->hmemTaskQ == hQueue)
358 wnd->hmemTaskQ = hNew;
359 ret = TRUE;
361 if (wnd->child)
362 ret |= WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
365 else /* Queue is being destroyed */
367 while (wnd->child)
369 WND *tmp = wnd->child;
370 ret = FALSE;
371 while (tmp)
373 if (tmp->hmemTaskQ == hQueue)
375 DestroyWindow32( tmp->hwndSelf );
376 ret = TRUE;
377 break;
379 if (tmp->child && WIN_ResetQueueWindows(tmp->child,hQueue,0))
380 ret = TRUE;
381 else
382 tmp = tmp->next;
384 if (!ret) break;
387 return ret;
390 /***********************************************************************
391 * WIN_CreateDesktopWindow
393 * Create the desktop window.
395 BOOL32 WIN_CreateDesktopWindow(void)
397 CLASS *class;
398 HWND32 hwndDesktop;
400 TRACE(win,"Creating desktop window\n");
402 if (!ICONTITLE_Init() ||
403 !WINPOS_CreateInternalPosAtom() ||
404 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
405 return FALSE;
407 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
408 if (!hwndDesktop) return FALSE;
409 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
411 pWndDesktop->next = NULL;
412 pWndDesktop->child = NULL;
413 pWndDesktop->parent = NULL;
414 pWndDesktop->owner = NULL;
415 pWndDesktop->class = class;
416 pWndDesktop->dwMagic = WND_MAGIC;
417 pWndDesktop->hwndSelf = hwndDesktop;
418 pWndDesktop->hInstance = 0;
419 pWndDesktop->rectWindow.left = 0;
420 pWndDesktop->rectWindow.top = 0;
421 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
422 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
423 pWndDesktop->rectClient = pWndDesktop->rectWindow;
424 pWndDesktop->text = NULL;
425 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
426 pWndDesktop->hrgnUpdate = 0;
427 pWndDesktop->hwndLastActive = hwndDesktop;
428 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
429 WS_CLIPSIBLINGS;
430 pWndDesktop->dwExStyle = 0;
431 pWndDesktop->dce = NULL;
432 pWndDesktop->pVScroll = NULL;
433 pWndDesktop->pHScroll = NULL;
434 pWndDesktop->pProp = NULL;
435 pWndDesktop->wIDmenu = 0;
436 pWndDesktop->helpContext = 0;
437 pWndDesktop->flags = 0;
438 pWndDesktop->window = rootWindow;
439 pWndDesktop->hSysMenu = 0;
440 pWndDesktop->userdata = 0;
442 pWndDesktop->winproc = (WNDPROC16)class->winproc;
444 EVENT_RegisterWindow( pWndDesktop );
445 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
446 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
447 return TRUE;
451 /***********************************************************************
452 * WIN_CreateWindowEx
454 * Implementation of CreateWindowEx().
456 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
457 BOOL32 win32, BOOL32 unicode )
459 CLASS *classPtr;
460 WND *wndPtr;
461 HWND16 hwnd, hwndLinkAfter;
462 POINT32 maxSize, maxPos, minTrack, maxTrack;
463 LRESULT (CALLBACK *localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
465 TRACE(win, "%s %s %08lx %08lx %d,%d %dx%d %04x %04x %08x %p\n",
466 unicode ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
467 unicode ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
468 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
469 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
471 /* Find the parent window */
473 if (cs->hwndParent)
475 /* Make sure parent is valid */
476 if (!IsWindow32( cs->hwndParent ))
478 WARN( win, "Bad parent %04x\n", cs->hwndParent );
479 return 0;
481 } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) {
482 WARN( win, "No parent for child window\n" );
483 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
486 /* Find the window class */
487 if (!(classPtr = CLASS_FindClassByAtom( classAtom, win32?cs->hInstance:GetExePtr(cs->hInstance) )))
489 char buffer[256];
490 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
491 WARN( win, "Bad class '%s'\n", buffer );
492 return 0;
495 /* Fix the coordinates */
497 if (cs->x == CW_USEDEFAULT32)
499 PDB32 *pdb = PROCESS_Current();
500 if ( !(cs->style & (WS_CHILD | WS_POPUP))
501 && (pdb->env_db->startup_info->dwFlags & STARTF_USEPOSITION) )
503 cs->x = pdb->env_db->startup_info->dwX;
504 cs->y = pdb->env_db->startup_info->dwY;
506 else
508 cs->x = 0;
509 cs->y = 0;
512 if (cs->cx == CW_USEDEFAULT32)
514 PDB32 *pdb = PROCESS_Current();
515 if ( !(cs->style & (WS_CHILD | WS_POPUP))
516 && (pdb->env_db->startup_info->dwFlags & STARTF_USESIZE) )
518 cs->cx = pdb->env_db->startup_info->dwXSize;
519 cs->cy = pdb->env_db->startup_info->dwYSize;
521 else
523 cs->cx = 600; /* FIXME */
524 cs->cy = 400;
528 /* Create the window structure */
530 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
531 - sizeof(wndPtr->wExtra) )))
533 TRACE(win, "out of memory\n" );
534 return 0;
537 /* Fill the window structure */
539 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
540 wndPtr->next = NULL;
541 wndPtr->child = NULL;
543 if ((cs->style & WS_CHILD) && cs->hwndParent)
545 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
546 wndPtr->owner = NULL;
548 else
550 wndPtr->parent = pWndDesktop;
551 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
552 wndPtr->owner = NULL;
553 else
554 wndPtr->owner = WIN_GetTopParentPtr(WIN_FindWndPtr(cs->hwndParent));
557 wndPtr->window = 0;
558 wndPtr->class = classPtr;
559 wndPtr->winproc = classPtr->winproc;
560 wndPtr->dwMagic = WND_MAGIC;
561 wndPtr->hwndSelf = hwnd;
562 wndPtr->hInstance = cs->hInstance;
563 wndPtr->text = NULL;
564 wndPtr->hmemTaskQ = GetTaskQueue(0);
565 wndPtr->hrgnUpdate = 0;
566 wndPtr->hwndLastActive = hwnd;
567 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
568 wndPtr->dwExStyle = cs->dwExStyle;
569 wndPtr->wIDmenu = 0;
570 wndPtr->helpContext = 0;
571 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
572 wndPtr->pVScroll = NULL;
573 wndPtr->pHScroll = NULL;
574 wndPtr->pProp = NULL;
575 wndPtr->userdata = 0;
576 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
577 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
579 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
581 /* Call the WH_CBT hook */
583 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
585 if (HOOK_IsHooked( WH_CBT ))
587 CBT_CREATEWND32A cbtc;
588 LRESULT ret;
590 cbtc.lpcs = cs;
591 cbtc.hwndInsertAfter = hwndLinkAfter;
592 ret = unicode ? HOOK_CallHooks32W(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc)
593 : HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc);
594 if (ret)
596 TRACE(win, "CBT-hook returned 0\n");
597 USER_HEAP_FREE( hwnd );
598 return 0;
602 /* Increment class window counter */
604 classPtr->cWindows++;
606 /* Correct the window style */
608 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
610 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
611 wndPtr->flags |= WIN_NEED_SIZE;
613 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
615 /* Get class or window DC if needed */
617 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
618 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
619 else wndPtr->dce = NULL;
621 /* Insert the window in the linked list */
623 WIN_LinkWindow( hwnd, hwndLinkAfter );
625 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
627 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
629 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
630 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
631 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
632 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
633 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
636 if(cs->style & WS_CHILD)
638 if(cs->cx < 0) cs->cx = 0;
639 if(cs->cy < 0) cs->cy = 0;
641 else
643 if (cs->cx <= 0) cs->cx = 1;
644 if (cs->cy <= 0) cs->cy = 1;
647 wndPtr->rectWindow.left = cs->x;
648 wndPtr->rectWindow.top = cs->y;
649 wndPtr->rectWindow.right = cs->x + cs->cx;
650 wndPtr->rectWindow.bottom = cs->y + cs->cy;
651 wndPtr->rectClient = wndPtr->rectWindow;
653 /* Create the X window (only for top-level windows, and then only */
654 /* when there's no desktop window) */
656 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
658 XSetWindowAttributes win_attr;
660 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
661 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
663 win_attr.event_mask = ExposureMask | KeyPressMask |
664 KeyReleaseMask | PointerMotionMask |
665 ButtonPressMask | ButtonReleaseMask |
666 FocusChangeMask | StructureNotifyMask;
667 win_attr.override_redirect = FALSE;
668 wndPtr->flags |= WIN_MANAGED;
670 else
672 win_attr.event_mask = ExposureMask | KeyPressMask |
673 KeyReleaseMask | PointerMotionMask |
674 ButtonPressMask | ButtonReleaseMask |
675 FocusChangeMask;
676 win_attr.override_redirect = TRUE;
678 win_attr.colormap = COLOR_GetColormap();
679 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
680 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
681 win_attr.cursor = CURSORICON_XCursor;
682 wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y,
683 cs->cx, cs->cy, 0, CopyFromParent,
684 InputOutput, CopyFromParent,
685 CWEventMask | CWOverrideRedirect |
686 CWColormap | CWCursor | CWSaveUnder |
687 CWBackingStore, &win_attr );
689 if ((wndPtr->flags & WIN_MANAGED) &&
690 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
692 XSizeHints* size_hints = TSXAllocSizeHints();
694 if (size_hints)
696 size_hints->min_width = size_hints->max_width = cs->cx;
697 size_hints->min_height = size_hints->max_height = cs->cy;
698 size_hints->flags = (PSize | PMinSize | PMaxSize);
699 TSXSetWMSizeHints( display, wndPtr->window, size_hints,
700 XA_WM_NORMAL_HINTS );
701 TSXFree(size_hints);
705 if (cs->hwndParent) /* Get window owner */
707 Window win = WIN_GetXWindow( cs->hwndParent );
708 if (win) TSXSetTransientForHint( display, wndPtr->window, win );
710 EVENT_RegisterWindow( wndPtr );
713 /* Set the window menu */
715 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
717 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
718 else
720 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
721 if (classPtr->menuNameA)
722 cs->hMenu = HIWORD(classPtr->menuNameA) ?
723 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
724 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
725 #else
726 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
727 if (menuName)
729 /* hInstance is still 16-bit in 980215 winelib */
730 if (HIWORD(cs->hInstance) || __winelib)
731 cs->hMenu = LoadMenu32A(cs->hInstance,PTR_SEG_TO_LIN(menuName));
732 else
733 /* doesn't work for winelib, since resources are unicode */
734 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
736 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
738 #endif
741 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
743 /* Send the WM_CREATE message
744 * Perhaps we shouldn't allow width/height changes as well.
745 * See p327 in "Internals".
748 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
750 localSend32 = unicode ? SendMessage32W : SendMessage32A;
751 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
753 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
754 NULL, NULL, 0, &wndPtr->rectClient );
755 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
756 maxPos.y - wndPtr->rectWindow.top);
757 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
759 /* Send the size messages */
761 if (!(wndPtr->flags & WIN_NEED_SIZE))
763 /* send it anyway */
764 if (((wndPtr->rectClient.right-wndPtr->rectClient.left) <0)
765 ||((wndPtr->rectClient.bottom-wndPtr->rectClient.top)<0))
766 WARN(win,"sending bogus WM_SIZE message 0x%08lx\n",
767 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
768 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
769 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
770 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
771 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
772 SendMessage32A( hwnd, WM_MOVE, 0,
773 MAKELONG( wndPtr->rectClient.left,
774 wndPtr->rectClient.top ) );
777 /* Show the window, maximizing or minimizing if needed */
779 if (wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE))
781 RECT16 newPos;
782 UINT16 swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
783 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
784 WINPOS_MinMaximize( wndPtr, swFlag, &newPos );
785 swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow32()) ? SWP_NOACTIVATE : 0;
786 SetWindowPos32( hwnd, 0, newPos.left, newPos.top,
787 newPos.right, newPos.bottom, SWP_FRAMECHANGED | swFlag );
790 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
792 /* Notify the parent window only */
794 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
795 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
796 if( !IsWindow32(hwnd) ) return 0;
799 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
801 /* Call WH_SHELL hook */
803 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
804 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
806 TRACE(win, "created window %04x\n", hwnd);
807 return hwnd;
811 /* Abort window creation */
813 WARN(win, "aborted by WM_xxCREATE!\n");
814 WIN_UnlinkWindow( hwnd );
815 WIN_DestroyWindow( wndPtr );
816 return 0;
820 /***********************************************************************
821 * CreateWindow16 (USER.41)
823 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
824 DWORD style, INT16 x, INT16 y, INT16 width,
825 INT16 height, HWND16 parent, HMENU16 menu,
826 HINSTANCE16 instance, LPVOID data )
828 return CreateWindowEx16( 0, className, windowName, style,
829 x, y, width, height, parent, menu, instance, data );
833 /***********************************************************************
834 * CreateWindowEx16 (USER.452)
836 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
837 LPCSTR windowName, DWORD style, INT16 x,
838 INT16 y, INT16 width, INT16 height,
839 HWND16 parent, HMENU16 menu,
840 HINSTANCE16 instance, LPVOID data )
842 ATOM classAtom;
843 CREATESTRUCT32A cs;
845 /* Find the class atom */
847 if (!(classAtom = GlobalFindAtom32A( className )))
849 fprintf( stderr, "CreateWindowEx16: bad class name " );
850 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
851 else fprintf( stderr, "'%s'\n", className );
852 return 0;
855 /* Fix the coordinates */
857 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
858 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
859 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
860 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
862 /* Create the window */
864 cs.lpCreateParams = data;
865 cs.hInstance = (HINSTANCE32)instance;
866 cs.hMenu = (HMENU32)menu;
867 cs.hwndParent = (HWND32)parent;
868 cs.style = style;
869 cs.lpszName = windowName;
870 cs.lpszClass = className;
871 cs.dwExStyle = exStyle;
872 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
876 /***********************************************************************
877 * CreateWindowEx32A (USER32.83)
879 HWND32 WINAPI CreateWindowEx32A( DWORD exStyle, LPCSTR className,
880 LPCSTR windowName, DWORD style, INT32 x,
881 INT32 y, INT32 width, INT32 height,
882 HWND32 parent, HMENU32 menu,
883 HINSTANCE32 instance, LPVOID data )
885 ATOM classAtom;
886 CREATESTRUCT32A cs;
888 /* Find the class atom */
890 if (!(classAtom = GlobalFindAtom32A( className )))
892 fprintf( stderr, "CreateWindowEx32A: bad class name " );
893 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
894 else fprintf( stderr, "'%s'\n", className );
895 return 0;
898 /* Create the window */
900 cs.lpCreateParams = data;
901 cs.hInstance = instance;
902 cs.hMenu = menu;
903 cs.hwndParent = parent;
904 cs.x = x;
905 cs.y = y;
906 cs.cx = width;
907 cs.cy = height;
908 cs.style = style;
909 cs.lpszName = windowName;
910 cs.lpszClass = className;
911 cs.dwExStyle = exStyle;
912 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
916 /***********************************************************************
917 * CreateWindowEx32W (USER32.84)
919 HWND32 WINAPI CreateWindowEx32W( DWORD exStyle, LPCWSTR className,
920 LPCWSTR windowName, DWORD style, INT32 x,
921 INT32 y, INT32 width, INT32 height,
922 HWND32 parent, HMENU32 menu,
923 HINSTANCE32 instance, LPVOID data )
925 ATOM classAtom;
926 CREATESTRUCT32W cs;
928 /* Find the class atom */
930 if (!(classAtom = GlobalFindAtom32W( className )))
932 if (HIWORD(className))
934 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
935 WARN( win, "Bad class name '%s'\n",cn);
936 HeapFree( GetProcessHeap(), 0, cn );
938 else
939 WARN( win, "Bad class name %p\n", className );
940 return 0;
943 /* Create the window */
945 cs.lpCreateParams = data;
946 cs.hInstance = instance;
947 cs.hMenu = menu;
948 cs.hwndParent = parent;
949 cs.x = x;
950 cs.y = y;
951 cs.cx = width;
952 cs.cy = height;
953 cs.style = style;
954 cs.lpszName = windowName;
955 cs.lpszClass = className;
956 cs.dwExStyle = exStyle;
957 /* Note: we rely on the fact that CREATESTRUCT32A and */
958 /* CREATESTRUCT32W have the same layout. */
959 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
963 /***********************************************************************
964 * WIN_CheckFocus
966 static void WIN_CheckFocus( WND* pWnd )
968 if( GetFocus16() == pWnd->hwndSelf )
969 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
972 /***********************************************************************
973 * WIN_SendDestroyMsg
975 static void WIN_SendDestroyMsg( WND* pWnd )
977 WIN_CheckFocus(pWnd);
979 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
980 if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd );
982 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
984 if( IsWindow32(pWnd->hwndSelf) )
986 WND* pChild = pWnd->child;
987 while( pChild )
989 WIN_SendDestroyMsg( pChild );
990 pChild = pChild->next;
992 WIN_CheckFocus(pWnd);
994 else
995 WARN(win, "\tdestroyed itself while in WM_DESTROY!\n");
999 /***********************************************************************
1000 * DestroyWindow16 (USER.53)
1002 BOOL16 WINAPI DestroyWindow16( HWND16 hwnd )
1004 return DestroyWindow32(hwnd);
1008 /***********************************************************************
1009 * DestroyWindow32 (USER32.135)
1011 BOOL32 WINAPI DestroyWindow32( HWND32 hwnd )
1013 WND * wndPtr;
1015 TRACE(win, "(%04x)\n", hwnd);
1017 /* Initialization */
1019 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1020 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1022 /* Call hooks */
1024 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1025 return FALSE;
1027 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1029 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1030 /* FIXME: clean up palette - see "Internals" p.352 */
1033 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1034 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1036 /* Notify the parent window only */
1037 SendMessage32A( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1038 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1039 if( !IsWindow32(hwnd) ) return TRUE;
1042 if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */
1044 /* Hide the window */
1046 if (wndPtr->dwStyle & WS_VISIBLE)
1048 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1049 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1050 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1051 if (!IsWindow32(hwnd)) return TRUE;
1054 /* Recursively destroy owned windows */
1056 if( !(wndPtr->dwStyle & WS_CHILD) )
1058 /* make sure top menu popup doesn't get destroyed */
1059 MENU_PatchResidentPopup( (HQUEUE16)0xFFFF, wndPtr );
1061 for (;;)
1063 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1064 while (siblingPtr)
1066 if (siblingPtr->owner == wndPtr)
1067 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1068 break;
1069 else
1070 siblingPtr->owner = NULL;
1071 siblingPtr = siblingPtr->next;
1073 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1074 else break;
1077 if( !Options.managed || EVENT_CheckFocus() )
1078 WINPOS_ActivateOtherWindow(wndPtr);
1080 if( wndPtr->owner &&
1081 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1082 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1085 /* Send destroy messages */
1087 WIN_SendDestroyMsg( wndPtr );
1088 if (!IsWindow32(hwnd)) return TRUE;
1090 /* Unlink now so we won't bother with the children later on */
1092 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1094 /* Destroy the window storage */
1096 WIN_DestroyWindow( wndPtr );
1097 return TRUE;
1101 /***********************************************************************
1102 * CloseWindow16 (USER.43)
1104 BOOL16 WINAPI CloseWindow16( HWND16 hwnd )
1106 return CloseWindow32( hwnd );
1110 /***********************************************************************
1111 * CloseWindow32 (USER32.56)
1113 BOOL32 WINAPI CloseWindow32( HWND32 hwnd )
1115 WND * wndPtr = WIN_FindWndPtr( hwnd );
1116 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1117 ShowWindow32( hwnd, SW_MINIMIZE );
1118 return TRUE;
1122 /***********************************************************************
1123 * OpenIcon16 (USER.44)
1125 BOOL16 WINAPI OpenIcon16( HWND16 hwnd )
1127 return OpenIcon32( hwnd );
1131 /***********************************************************************
1132 * OpenIcon32 (USER32.410)
1134 BOOL32 WINAPI OpenIcon32( HWND32 hwnd )
1136 if (!IsIconic32( hwnd )) return FALSE;
1137 ShowWindow32( hwnd, SW_SHOWNORMAL );
1138 return TRUE;
1142 /***********************************************************************
1143 * WIN_FindWindow
1145 * Implementation of FindWindow() and FindWindowEx().
1147 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1148 LPCSTR title )
1150 WND *pWnd;
1151 CLASS *pClass = NULL;
1153 if (child)
1155 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1156 if (parent)
1158 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1160 else if (pWnd->parent != pWndDesktop) return 0;
1161 pWnd = pWnd->next;
1163 else
1165 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1166 pWnd = pWnd->child;
1168 if (!pWnd) return 0;
1170 /* For a child window, all siblings will have the same hInstance, */
1171 /* so we can look for the class once and for all. */
1173 if (className && (pWnd->dwStyle & WS_CHILD))
1175 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1176 return 0;
1180 for ( ; pWnd; pWnd = pWnd->next)
1182 if (className && !(pWnd->dwStyle & WS_CHILD))
1184 if (!(pClass = CLASS_FindClassByAtom( className, GetExePtr(pWnd->hInstance))))
1185 continue; /* Skip this window */
1188 if (pClass && (pWnd->class != pClass))
1189 continue; /* Not the right class */
1191 /* Now check the title */
1193 if (!title) return pWnd->hwndSelf;
1194 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1196 return 0;
1201 /***********************************************************************
1202 * FindWindow16 (USER.50)
1204 HWND16 WINAPI FindWindow16( SEGPTR className, LPCSTR title )
1206 return FindWindowEx16( 0, 0, className, title );
1210 /***********************************************************************
1211 * FindWindowEx16 (USER.427)
1213 HWND16 WINAPI FindWindowEx16( HWND16 parent, HWND16 child,
1214 SEGPTR className, LPCSTR title )
1216 ATOM atom = 0;
1218 TRACE(win, "%04x %04x '%s' '%s'\n", parent,
1219 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1220 title ? title : "");
1222 if (className)
1224 /* If the atom doesn't exist, then no class */
1225 /* with this name exists either. */
1226 if (!(atom = GlobalFindAtom16( className ))) return 0;
1228 return WIN_FindWindow( parent, child, atom, title );
1232 /***********************************************************************
1233 * FindWindow32A (USER32.198)
1235 HWND32 WINAPI FindWindow32A( LPCSTR className, LPCSTR title )
1237 HWND32 ret = FindWindowEx32A( 0, 0, className, title );
1238 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1239 return ret;
1243 /***********************************************************************
1244 * FindWindowEx32A (USER32.199)
1246 HWND32 WINAPI FindWindowEx32A( HWND32 parent, HWND32 child,
1247 LPCSTR className, LPCSTR title )
1249 ATOM atom = 0;
1251 if (className)
1253 /* If the atom doesn't exist, then no class */
1254 /* with this name exists either. */
1255 if (!(atom = GlobalFindAtom32A( className )))
1257 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1258 return 0;
1261 return WIN_FindWindow( parent, child, atom, title );
1265 /***********************************************************************
1266 * FindWindowEx32W (USER32.200)
1268 HWND32 WINAPI FindWindowEx32W( HWND32 parent, HWND32 child,
1269 LPCWSTR className, LPCWSTR title )
1271 ATOM atom = 0;
1272 char *buffer;
1273 HWND32 hwnd;
1275 if (className)
1277 /* If the atom doesn't exist, then no class */
1278 /* with this name exists either. */
1279 if (!(atom = GlobalFindAtom32W( className )))
1281 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1282 return 0;
1285 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1286 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1287 HeapFree( GetProcessHeap(), 0, buffer );
1288 return hwnd;
1292 /***********************************************************************
1293 * FindWindow32W (USER32.201)
1295 HWND32 WINAPI FindWindow32W( LPCWSTR className, LPCWSTR title )
1297 return FindWindowEx32W( 0, 0, className, title );
1301 /**********************************************************************
1302 * WIN_GetDesktop
1304 WND *WIN_GetDesktop(void)
1306 return pWndDesktop;
1310 /**********************************************************************
1311 * GetDesktopWindow16 (USER.286)
1313 HWND16 WINAPI GetDesktopWindow16(void)
1315 return (HWND16)pWndDesktop->hwndSelf;
1319 /**********************************************************************
1320 * GetDesktopWindow32 (USER32.232)
1322 HWND32 WINAPI GetDesktopWindow32(void)
1324 return pWndDesktop->hwndSelf;
1328 /**********************************************************************
1329 * GetDesktopHwnd (USER.278)
1331 * Exactly the same thing as GetDesktopWindow(), but not documented.
1332 * Don't ask me why...
1334 HWND16 WINAPI GetDesktopHwnd(void)
1336 return (HWND16)pWndDesktop->hwndSelf;
1340 /*******************************************************************
1341 * EnableWindow16 (USER.34)
1343 BOOL16 WINAPI EnableWindow16( HWND16 hwnd, BOOL16 enable )
1345 return EnableWindow32( hwnd, enable );
1349 /*******************************************************************
1350 * EnableWindow32 (USER32.172)
1352 BOOL32 WINAPI EnableWindow32( HWND32 hwnd, BOOL32 enable )
1354 WND *wndPtr;
1356 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1357 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1359 /* Enable window */
1360 wndPtr->dwStyle &= ~WS_DISABLED;
1361 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1362 return TRUE;
1364 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1366 /* Disable window */
1367 wndPtr->dwStyle |= WS_DISABLED;
1368 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1369 SetFocus32( 0 ); /* A disabled window can't have the focus */
1370 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1371 ReleaseCapture(); /* A disabled window can't capture the mouse */
1372 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1373 return FALSE;
1375 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1379 /***********************************************************************
1380 * IsWindowEnabled16 (USER.35)
1382 BOOL16 WINAPI IsWindowEnabled16(HWND16 hWnd)
1384 return IsWindowEnabled32(hWnd);
1388 /***********************************************************************
1389 * IsWindowEnabled32 (USER32.349)
1391 BOOL32 WINAPI IsWindowEnabled32(HWND32 hWnd)
1393 WND * wndPtr;
1395 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1396 return !(wndPtr->dwStyle & WS_DISABLED);
1400 /***********************************************************************
1401 * IsWindowUnicode (USER32.350)
1403 BOOL32 WINAPI IsWindowUnicode( HWND32 hwnd )
1405 WND * wndPtr;
1407 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1408 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1412 /**********************************************************************
1413 * GetWindowWord16 (USER.133)
1415 WORD WINAPI GetWindowWord16( HWND16 hwnd, INT16 offset )
1417 return GetWindowWord32( hwnd, offset );
1421 /**********************************************************************
1422 * GetWindowWord32 (USER32.314)
1424 WORD WINAPI GetWindowWord32( HWND32 hwnd, INT32 offset )
1426 WND * wndPtr = WIN_FindWndPtr( hwnd );
1427 if (!wndPtr) return 0;
1428 if (offset >= 0)
1430 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1432 WARN( win, "Invalid offset %d\n", offset );
1433 return 0;
1435 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1437 switch(offset)
1439 case GWW_ID:
1440 if (HIWORD(wndPtr->wIDmenu))
1441 WARN( win,"GWW_ID: discards high bits of 0x%08x!\n",
1442 wndPtr->wIDmenu);
1443 return (WORD)wndPtr->wIDmenu;
1444 case GWW_HWNDPARENT:
1445 return wndPtr->parent ?
1446 wndPtr->parent->hwndSelf : (
1447 wndPtr->owner ?
1448 wndPtr->owner->hwndSelf :
1450 case GWW_HINSTANCE:
1451 if (HIWORD(wndPtr->hInstance))
1452 WARN(win,"GWW_HINSTANCE: discards high bits of 0x%08x!\n",
1453 wndPtr->hInstance);
1454 return (WORD)wndPtr->hInstance;
1455 default:
1456 WARN( win, "Invalid offset %d\n", offset );
1457 return 0;
1462 /**********************************************************************
1463 * WIN_GetWindowInstance
1465 HINSTANCE32 WIN_GetWindowInstance( HWND32 hwnd )
1467 WND * wndPtr = WIN_FindWndPtr( hwnd );
1468 if (!wndPtr) return (HINSTANCE32)0;
1469 return wndPtr->hInstance;
1473 /**********************************************************************
1474 * SetWindowWord16 (USER.134)
1476 WORD WINAPI SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1478 return SetWindowWord32( hwnd, offset, newval );
1482 /**********************************************************************
1483 * SetWindowWord32 (USER32.524)
1485 WORD WINAPI SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1487 WORD *ptr, retval;
1488 WND * wndPtr = WIN_FindWndPtr( hwnd );
1489 if (!wndPtr) return 0;
1490 if (offset >= 0)
1492 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1494 WARN( win, "Invalid offset %d\n", offset );
1495 return 0;
1497 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1499 else switch(offset)
1501 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1502 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1503 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1504 default:
1505 WARN( win, "Invalid offset %d\n", offset );
1506 return 0;
1508 retval = *ptr;
1509 *ptr = newval;
1510 return retval;
1514 /**********************************************************************
1515 * WIN_GetWindowLong
1517 * Helper function for GetWindowLong().
1519 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1521 LONG retval;
1522 WND * wndPtr = WIN_FindWndPtr( hwnd );
1523 if (!wndPtr) return 0;
1524 if (offset >= 0)
1526 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1528 WARN( win, "Invalid offset %d\n", offset );
1529 return 0;
1531 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1532 /* Special case for dialog window procedure */
1533 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1534 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1535 return retval;
1537 switch(offset)
1539 case GWL_USERDATA: return wndPtr->userdata;
1540 case GWL_STYLE: return wndPtr->dwStyle;
1541 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1542 case GWL_ID: return (LONG)wndPtr->wIDmenu;
1543 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1544 type );
1545 case GWL_HWNDPARENT: return wndPtr->parent ?
1546 (HWND32)wndPtr->parent->hwndSelf : 0;
1547 case GWL_HINSTANCE: return wndPtr->hInstance;
1548 default:
1549 WARN( win, "Unknown offset %d\n", offset );
1551 return 0;
1555 /**********************************************************************
1556 * WIN_SetWindowLong
1558 * Helper function for SetWindowLong().
1560 * 0 is the failure code. However, in the case of failure SetLastError
1561 * must be set to distinguish between a 0 return value and a failure.
1563 * FIXME: The error values for SetLastError may not be right. Can
1564 * someone check with the real thing?
1566 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1567 WINDOWPROCTYPE type )
1569 LONG *ptr, retval;
1570 WND * wndPtr = WIN_FindWndPtr( hwnd );
1571 STYLESTRUCT style;
1573 TRACE(win,"%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1575 if (!wndPtr)
1577 /* Is this the right error? */
1578 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1579 return 0;
1582 if (offset >= 0)
1584 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1586 WARN( win, "Invalid offset %d\n", offset );
1588 /* Is this the right error? */
1589 SetLastError( ERROR_OUTOFMEMORY );
1591 return 0;
1593 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1594 /* Special case for dialog window procedure */
1595 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1597 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1598 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1599 type, WIN_PROC_WINDOW );
1600 return retval;
1603 else switch(offset)
1605 case GWL_ID:
1606 ptr = (DWORD*)&wndPtr->wIDmenu;
1607 break;
1608 case GWL_HINSTANCE:
1609 return SetWindowWord32( hwnd, offset, newval );
1610 case GWL_WNDPROC:
1611 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1612 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1613 type, WIN_PROC_WINDOW );
1614 return retval;
1615 case GWL_STYLE:
1616 style.styleOld = wndPtr->dwStyle;
1617 newval &= ~(WS_VISIBLE | WS_CHILD); /* Some bits can't be changed this way */
1618 style.styleNew = newval | (style.styleOld & (WS_VISIBLE | WS_CHILD));
1620 if (wndPtr->flags & WIN_ISWIN32)
1621 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1622 wndPtr->dwStyle = style.styleNew;
1623 if (wndPtr->flags & WIN_ISWIN32)
1624 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1625 return style.styleOld;
1627 case GWL_USERDATA:
1628 ptr = &wndPtr->userdata;
1629 break;
1630 case GWL_EXSTYLE:
1631 style.styleOld = wndPtr->dwExStyle;
1632 style.styleNew = newval;
1633 if (wndPtr->flags & WIN_ISWIN32)
1634 SendMessage32A(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1635 wndPtr->dwExStyle = newval;
1636 if (wndPtr->flags & WIN_ISWIN32)
1637 SendMessage32A(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1638 return style.styleOld;
1640 default:
1641 WARN( win, "Invalid offset %d\n", offset );
1643 /* Don't think this is right error but it should do */
1644 SetLastError( ERROR_OUTOFMEMORY );
1646 return 0;
1648 retval = *ptr;
1649 *ptr = newval;
1650 return retval;
1654 /**********************************************************************
1655 * GetWindowLong16 (USER.135)
1657 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1659 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1663 /**********************************************************************
1664 * GetWindowLong32A (USER32.305)
1666 LONG WINAPI GetWindowLong32A( HWND32 hwnd, INT32 offset )
1668 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1672 /**********************************************************************
1673 * GetWindowLong32W (USER32.306)
1675 LONG WINAPI GetWindowLong32W( HWND32 hwnd, INT32 offset )
1677 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1681 /**********************************************************************
1682 * SetWindowLong16 (USER.136)
1684 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1686 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1690 /**********************************************************************
1691 * SetWindowLong32A (USER32.517)
1693 LONG WINAPI SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1695 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1699 /**********************************************************************
1700 * SetWindowLong32W (USER32.518) Set window attribute
1702 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1703 * value in a window's extra memory.
1705 * The _hwnd_ parameter specifies the window. is the handle to a
1706 * window that has extra memory. The _newval_ parameter contains the
1707 * new attribute or extra memory value. If positive, the _offset_
1708 * parameter is the byte-addressed location in the window's extra
1709 * memory to set. If negative, _offset_ specifies the window
1710 * attribute to set, and should be one of the following values:
1712 * GWL_EXSTYLE The window's extended window style
1714 * GWL_STYLE The window's window style.
1716 * GWL_WNDPROC Pointer to the window's window procedure.
1718 * GWL_HINSTANCE The window's pplication instance handle.
1720 * GWL_ID The window's identifier.
1722 * GWL_USERDATA The window's user-specified data.
1724 * If the window is a dialog box, the _offset_ parameter can be one of
1725 * the following values:
1727 * DWL_DLGPROC The address of the window's dialog box procedure.
1729 * DWL_MSGRESULT The return value of a message
1730 * that the dialog box procedure processed.
1732 * DWL_USER Application specific information.
1734 * RETURNS
1736 * If successful, returns the previous value located at _offset_. Otherwise,
1737 * returns 0.
1739 * NOTES
1741 * Extra memory for a window class is specified by a nonzero cbWndExtra
1742 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1743 * time of class creation.
1745 * Using GWL_WNDPROC to set a new window procedure effectively creates
1746 * a window subclass. Use CallWindowProc() in the new windows procedure
1747 * to pass messages to the superclass's window procedure.
1749 * The user data is reserved for use by the application which created
1750 * the window.
1752 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1753 * instead, call the EnableWindow() function to change the window's
1754 * disabled state.
1756 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1757 * SetParent() instead.
1759 * BUGS
1761 * GWL_STYLE does not dispatch WM_STYLE_... messages.
1763 * CONFORMANCE
1765 * ECMA-234, Win32
1768 LONG WINAPI SetWindowLong32W(
1769 HWND32 hwnd, /* window to alter */
1770 INT32 offset, /* offset, in bytes, of location to alter */
1771 LONG newval /* new value of location */
1773 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1777 /*******************************************************************
1778 * GetWindowText16 (USER.36)
1780 INT16 WINAPI GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1782 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1786 /*******************************************************************
1787 * GetWindowText32A (USER32.309)
1789 INT32 WINAPI GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1791 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1792 (LPARAM)lpString );
1795 /*******************************************************************
1796 * InternalGetWindowText (USER32.326)
1798 INT32 WINAPI InternalGetWindowText(HWND32 hwnd,LPWSTR lpString,INT32 nMaxCount )
1800 FIXME(win,"(0x%08x,%s,0x%x),stub!\n",hwnd,debugstr_w(lpString),nMaxCount);
1801 return GetWindowText32W(hwnd,lpString,nMaxCount);
1805 /*******************************************************************
1806 * GetWindowText32W (USER32.312)
1808 INT32 WINAPI GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1810 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1811 (LPARAM)lpString );
1815 /*******************************************************************
1816 * SetWindowText16 (USER.37)
1818 void WINAPI SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1820 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1824 /*******************************************************************
1825 * SetWindowText32A (USER32.521)
1827 void WINAPI SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1829 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1833 /*******************************************************************
1834 * SetWindowText32W (USER32.523)
1836 void WINAPI SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1838 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1842 /*******************************************************************
1843 * GetWindowTextLength16 (USER.38)
1845 INT16 WINAPI GetWindowTextLength16( HWND16 hwnd )
1847 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1851 /*******************************************************************
1852 * GetWindowTextLength32A (USER32.310)
1854 INT32 WINAPI GetWindowTextLength32A( HWND32 hwnd )
1856 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1859 /*******************************************************************
1860 * GetWindowTextLength32W (USER32.311)
1862 INT32 WINAPI GetWindowTextLength32W( HWND32 hwnd )
1864 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1868 /*******************************************************************
1869 * IsWindow16 (USER.47)
1871 BOOL16 WINAPI IsWindow16( HWND16 hwnd )
1873 return IsWindow32( hwnd );
1876 void WINAPI WIN16_IsWindow16( CONTEXT *context )
1878 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1879 HWND16 hwnd = (HWND16)stack[2];
1881 AX_reg(context) = IsWindow32( hwnd );
1882 ES_reg(context) = USER_HeapSel;
1886 /*******************************************************************
1887 * IsWindow32 (USER32.348)
1889 BOOL32 WINAPI IsWindow32( HWND32 hwnd )
1891 WND * wndPtr = WIN_FindWndPtr( hwnd );
1892 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1896 /*****************************************************************
1897 * GetParent16 (USER.46)
1899 HWND16 WINAPI GetParent16( HWND16 hwnd )
1901 return (HWND16)GetParent32( hwnd );
1905 /*****************************************************************
1906 * GetParent32 (USER32.278)
1908 HWND32 WINAPI GetParent32( HWND32 hwnd )
1910 WND *wndPtr = WIN_FindWndPtr(hwnd);
1911 if ((!wndPtr) || (!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD)))) return 0;
1912 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1913 return wndPtr ? wndPtr->hwndSelf : 0;
1916 /*****************************************************************
1917 * WIN_GetTopParent
1919 * Get the top-level parent for a child window.
1921 WND* WIN_GetTopParentPtr( WND* pWnd )
1923 while( pWnd && (pWnd->dwStyle & WS_CHILD)) pWnd = pWnd->parent;
1924 return pWnd;
1927 /*****************************************************************
1928 * WIN_GetTopParent
1930 * Get the top-level parent for a child window.
1932 HWND32 WIN_GetTopParent( HWND32 hwnd )
1934 WND *wndPtr = WIN_GetTopParentPtr ( WIN_FindWndPtr( hwnd ) );
1935 return wndPtr ? wndPtr->hwndSelf : 0;
1939 /*****************************************************************
1940 * SetParent16 (USER.233)
1942 HWND16 WINAPI SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1944 return SetParent32( hwndChild, hwndNewParent );
1948 /*****************************************************************
1949 * SetParent32 (USER32.495)
1951 HWND32 WINAPI SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1953 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1954 WND *pWndParent = (hwndNewParent) ? WIN_FindWndPtr( hwndNewParent )
1955 : pWndDesktop;
1957 if( wndPtr && pWndParent && (wndPtr != pWndDesktop) )
1959 WND* pWndPrev = wndPtr->parent;
1961 if( pWndParent != pWndPrev )
1963 BOOL32 bFixupDCE = IsWindowVisible32(hwndChild);
1965 if ( wndPtr->window )
1967 /* Toplevel window needs to be reparented. Used by Tk 8.0 */
1969 TSXDestroyWindow( display, wndPtr->window );
1970 wndPtr->window = None;
1972 else if( bFixupDCE )
1973 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1975 WIN_UnlinkWindow(hwndChild);
1976 wndPtr->parent = pWndParent;
1978 /* FIXME: Create an X counterpart for reparented top-level windows
1979 * when not in the desktop mode. */
1981 if ( pWndParent != pWndDesktop ) wndPtr->dwStyle |= WS_CHILD;
1982 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1984 if( bFixupDCE )
1986 DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
1987 UpdateWindow32(hwndChild);
1990 return pWndPrev->hwndSelf;
1991 } /* failure */
1992 return 0;
1996 /*******************************************************************
1997 * IsChild16 (USER.48)
1999 BOOL16 WINAPI IsChild16( HWND16 parent, HWND16 child )
2001 return IsChild32(parent,child);
2005 /*******************************************************************
2006 * IsChild32 (USER32.339)
2008 BOOL32 WINAPI IsChild32( HWND32 parent, HWND32 child )
2010 WND * wndPtr = WIN_FindWndPtr( child );
2011 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2013 wndPtr = wndPtr->parent;
2014 if (wndPtr->hwndSelf == parent) return TRUE;
2016 return FALSE;
2020 /***********************************************************************
2021 * IsWindowVisible16 (USER.49)
2023 BOOL16 WINAPI IsWindowVisible16( HWND16 hwnd )
2025 return IsWindowVisible32(hwnd);
2029 /***********************************************************************
2030 * IsWindowVisible32 (USER32.351)
2032 BOOL32 WINAPI IsWindowVisible32( HWND32 hwnd )
2034 WND *wndPtr = WIN_FindWndPtr( hwnd );
2035 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
2037 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
2038 wndPtr = wndPtr->parent;
2040 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
2044 /***********************************************************************
2045 * WIN_IsWindowDrawable
2047 * hwnd is drawable when it is visible, all parents are not
2048 * minimized, and it is itself not minimized unless we are
2049 * trying to draw its default class icon.
2051 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
2053 if( (wnd->dwStyle & WS_MINIMIZE &&
2054 icon && wnd->class->hIcon) ||
2055 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
2056 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
2057 if( wnd->dwStyle & WS_MINIMIZE ||
2058 !(wnd->dwStyle & WS_VISIBLE) ) break;
2059 return (wnd == NULL);
2063 /*******************************************************************
2064 * GetTopWindow16 (USER.229)
2066 HWND16 WINAPI GetTopWindow16( HWND16 hwnd )
2068 return GetTopWindow32(hwnd);
2072 /*******************************************************************
2073 * GetTopWindow32 (USER.229)
2075 HWND32 WINAPI GetTopWindow32( HWND32 hwnd )
2077 WND * wndPtr = WIN_FindWndPtr( hwnd );
2078 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
2079 else return 0;
2083 /*******************************************************************
2084 * GetWindow16 (USER.262)
2086 HWND16 WINAPI GetWindow16( HWND16 hwnd, WORD rel )
2088 return GetWindow32( hwnd,rel );
2092 /*******************************************************************
2093 * GetWindow32 (USER32.302)
2095 HWND32 WINAPI GetWindow32( HWND32 hwnd, WORD rel )
2097 WND * wndPtr = WIN_FindWndPtr( hwnd );
2098 if (!wndPtr) return 0;
2099 switch(rel)
2101 case GW_HWNDFIRST:
2102 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
2103 else return 0;
2105 case GW_HWNDLAST:
2106 if (!wndPtr->parent) return 0; /* Desktop window */
2107 while (wndPtr->next) wndPtr = wndPtr->next;
2108 return wndPtr->hwndSelf;
2110 case GW_HWNDNEXT:
2111 if (!wndPtr->next) return 0;
2112 return wndPtr->next->hwndSelf;
2114 case GW_HWNDPREV:
2115 if (!wndPtr->parent) return 0; /* Desktop window */
2116 wndPtr = wndPtr->parent->child; /* First sibling */
2117 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
2118 while (wndPtr->next)
2120 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
2121 wndPtr = wndPtr->next;
2123 return 0;
2125 case GW_OWNER:
2126 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
2128 case GW_CHILD:
2129 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
2131 return 0;
2135 /*******************************************************************
2136 * GetNextWindow16 (USER.230)
2138 HWND16 WINAPI GetNextWindow16( HWND16 hwnd, WORD flag )
2140 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
2141 return GetWindow16( hwnd, flag );
2144 /*******************************************************************
2145 * ShowOwnedPopups16 (USER.265)
2147 void WINAPI ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
2149 ShowOwnedPopups32( owner, fShow );
2153 /*******************************************************************
2154 * ShowOwnedPopups32 (USER32.531)
2156 BOOL32 WINAPI ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
2158 WND *pWnd = pWndDesktop->child;
2159 while (pWnd)
2161 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
2162 (pWnd->dwStyle & WS_POPUP))
2163 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
2164 pWnd = pWnd->next;
2166 return TRUE;
2170 /*******************************************************************
2171 * GetLastActivePopup16 (USER.287)
2173 HWND16 WINAPI GetLastActivePopup16( HWND16 hwnd )
2175 return GetLastActivePopup32( hwnd );
2178 /*******************************************************************
2179 * GetLastActivePopup32 (USER32.256)
2181 HWND32 WINAPI GetLastActivePopup32( HWND32 hwnd )
2183 WND *wndPtr;
2184 wndPtr = WIN_FindWndPtr(hwnd);
2185 if (wndPtr == NULL) return hwnd;
2186 return wndPtr->hwndLastActive;
2190 /*******************************************************************
2191 * WIN_BuildWinArray
2193 * Build an array of pointers to the children of a given window.
2194 * The array must be freed with HeapFree(SystemHeap). Return NULL
2195 * when no windows are found.
2197 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
2199 WND **list, **ppWnd;
2200 WND *pWnd;
2201 UINT32 count, skipOwned, skipHidden;
2202 DWORD skipFlags;
2204 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
2205 skipOwned = bwaFlags & BWA_SKIPOWNED;
2206 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
2207 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
2209 /* First count the windows */
2211 if (!wndPtr) wndPtr = pWndDesktop;
2212 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
2214 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2215 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
2218 if( count )
2220 /* Now build the list of all windows */
2222 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
2224 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
2226 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2227 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2229 *ppWnd++ = pWnd;
2230 count++;
2233 *ppWnd = NULL;
2235 else count = 0;
2236 } else list = NULL;
2238 if( pTotal ) *pTotal = count;
2239 return list;
2243 /*******************************************************************
2244 * EnumWindows16 (USER.54)
2246 BOOL16 WINAPI EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2248 WND **list, **ppWnd;
2250 /* We have to build a list of all windows first, to avoid */
2251 /* unpleasant side-effects, for instance if the callback */
2252 /* function changes the Z-order of the windows. */
2254 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2256 /* Now call the callback function for every window */
2258 for (ppWnd = list; *ppWnd; ppWnd++)
2260 /* Make sure that the window still exists */
2261 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2262 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2264 HeapFree( SystemHeap, 0, list );
2265 return TRUE;
2269 /*******************************************************************
2270 * EnumWindows32 (USER32.193)
2272 BOOL32 WINAPI EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2274 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2278 /**********************************************************************
2279 * EnumTaskWindows16 (USER.225)
2281 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2282 LPARAM lParam )
2284 WND **list, **ppWnd;
2285 HQUEUE16 hQueue = GetTaskQueue( hTask );
2287 /* This function is the same as EnumWindows(), */
2288 /* except for an added check on the window queue. */
2290 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2292 /* Now call the callback function for every window */
2294 for (ppWnd = list; *ppWnd; ppWnd++)
2296 /* Make sure that the window still exists */
2297 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2298 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2299 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2301 HeapFree( SystemHeap, 0, list );
2302 return TRUE;
2306 /**********************************************************************
2307 * EnumThreadWindows (USER32.190)
2309 BOOL32 WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2311 THDB *tdb = THREAD_ID_TO_THDB(id);
2313 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2317 /**********************************************************************
2318 * WIN_EnumChildWindows
2320 * Helper function for EnumChildWindows().
2322 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2323 LPARAM lParam )
2325 WND **childList;
2326 BOOL16 ret = FALSE;
2328 for ( ; *ppWnd; ppWnd++)
2330 /* Make sure that the window still exists */
2331 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2332 /* Build children list first */
2333 childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL );
2334 ret = func( (*ppWnd)->hwndSelf, lParam );
2335 if (childList)
2337 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2338 HeapFree( SystemHeap, 0, childList );
2340 if (!ret) return FALSE;
2342 return TRUE;
2346 /**********************************************************************
2347 * EnumChildWindows16 (USER.55)
2349 BOOL16 WINAPI EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func,
2350 LPARAM lParam )
2352 WND **list, *pParent;
2354 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2355 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2356 WIN_EnumChildWindows( list, func, lParam );
2357 HeapFree( SystemHeap, 0, list );
2358 return TRUE;
2362 /**********************************************************************
2363 * EnumChildWindows32 (USER32.178)
2365 BOOL32 WINAPI EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func,
2366 LPARAM lParam )
2368 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2369 lParam );
2373 /*******************************************************************
2374 * AnyPopup16 (USER.52)
2376 BOOL16 WINAPI AnyPopup16(void)
2378 return AnyPopup32();
2382 /*******************************************************************
2383 * AnyPopup32 (USER32.4)
2385 BOOL32 WINAPI AnyPopup32(void)
2387 WND *wndPtr;
2388 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2389 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2390 return FALSE;
2394 /*******************************************************************
2395 * FlashWindow16 (USER.105)
2397 BOOL16 WINAPI FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2399 return FlashWindow32( hWnd, bInvert );
2403 /*******************************************************************
2404 * FlashWindow32 (USER32.202)
2406 BOOL32 WINAPI FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2408 WND *wndPtr = WIN_FindWndPtr(hWnd);
2410 TRACE(win,"%04x\n", hWnd);
2412 if (!wndPtr) return FALSE;
2414 if (wndPtr->dwStyle & WS_MINIMIZE)
2416 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2418 HDC32 hDC = GetDC32(hWnd);
2420 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2421 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2423 ReleaseDC32( hWnd, hDC );
2424 wndPtr->flags |= WIN_NCACTIVATED;
2426 else
2428 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2429 RDW_UPDATENOW | RDW_FRAME, 0 );
2430 wndPtr->flags &= ~WIN_NCACTIVATED;
2432 return TRUE;
2434 else
2436 WPARAM16 wparam;
2437 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2438 else wparam = (hWnd == GetActiveWindow32());
2440 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2441 return wparam;
2446 /*******************************************************************
2447 * SetSysModalWindow16 (USER.188)
2449 HWND16 WINAPI SetSysModalWindow16( HWND16 hWnd )
2451 HWND32 hWndOldModal = hwndSysModal;
2452 hwndSysModal = hWnd;
2453 FIXME(win, "EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2454 return hWndOldModal;
2458 /*******************************************************************
2459 * GetSysModalWindow16 (USER.52)
2461 HWND16 WINAPI GetSysModalWindow16(void)
2463 return hwndSysModal;
2467 /*******************************************************************
2468 * GetWindowContextHelpId (USER32.303)
2470 DWORD WINAPI GetWindowContextHelpId( HWND32 hwnd )
2472 WND *wnd = WIN_FindWndPtr( hwnd );
2473 if (!wnd) return 0;
2474 return wnd->helpContext;
2478 /*******************************************************************
2479 * SetWindowContextHelpId (USER32.515)
2481 BOOL32 WINAPI SetWindowContextHelpId( HWND32 hwnd, DWORD id )
2483 WND *wnd = WIN_FindWndPtr( hwnd );
2484 if (!wnd) return FALSE;
2485 wnd->helpContext = id;
2486 return TRUE;
2490 /*******************************************************************
2491 * DRAG_QueryUpdate
2493 * recursively find a child that contains spDragInfo->pt point
2494 * and send WM_QUERYDROPOBJECT
2496 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2498 BOOL16 wParam,bResult = 0;
2499 POINT32 pt;
2500 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2501 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2502 RECT32 tempRect;
2504 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2506 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2508 GetWindowRect32(hQueryWnd,&tempRect);
2510 if( !PtInRect32(&tempRect,pt) ||
2511 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2512 return 0;
2514 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2516 tempRect = ptrQueryWnd->rectClient;
2517 if(ptrQueryWnd->dwStyle & WS_CHILD)
2518 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2519 (LPPOINT32)&tempRect, 2 );
2521 if (PtInRect32( &tempRect, pt))
2523 wParam = 0;
2525 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2526 if( ptrWnd->dwStyle & WS_VISIBLE )
2528 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2529 if (PtInRect32( &tempRect, pt )) break;
2532 if(ptrWnd)
2534 TRACE(msg,"hwnd = %04x, %d %d - %d %d\n",
2535 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2536 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2537 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2538 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2541 if(bResult) return bResult;
2543 else wParam = 1;
2545 else wParam = 1;
2547 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2549 ptrDragInfo->hScope = hQueryWnd;
2551 bResult = ( bNoSend )
2552 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2553 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2554 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2555 if( !bResult )
2556 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2558 return bResult;
2562 /*******************************************************************
2563 * DragDetect (USER.465)
2565 BOOL16 WINAPI DragDetect16( HWND16 hWnd, POINT16 pt )
2567 POINT32 pt32;
2568 CONV_POINT16TO32( &pt, &pt32 );
2569 return DragDetect32( hWnd, pt32 );
2572 /*******************************************************************
2573 * DragDetect32 (USER32.151)
2575 BOOL32 WINAPI DragDetect32( HWND32 hWnd, POINT32 pt )
2577 MSG16 msg;
2578 RECT16 rect;
2580 rect.left = pt.x - wDragWidth;
2581 rect.right = pt.x + wDragWidth;
2583 rect.top = pt.y - wDragHeight;
2584 rect.bottom = pt.y + wDragHeight;
2586 SetCapture32(hWnd);
2588 while(1)
2590 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2592 if( msg.message == WM_LBUTTONUP )
2594 ReleaseCapture();
2595 return 0;
2597 if( msg.message == WM_MOUSEMOVE )
2599 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2601 ReleaseCapture();
2602 return 1;
2606 WaitMessage();
2608 return 0;
2611 /******************************************************************************
2612 * DragObject16 (USER.464)
2614 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2615 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2617 MSG16 msg;
2618 LPDRAGINFO lpDragInfo;
2619 SEGPTR spDragInfo;
2620 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2621 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2622 WND *wndPtr = WIN_FindWndPtr(hWnd);
2623 HCURSOR16 hCurrentCursor = 0;
2624 HWND16 hCurrentWnd = 0;
2626 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2627 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2629 if( !lpDragInfo || !spDragInfo ) return 0L;
2631 hBummer = LoadCursor16(0, IDC_BUMMER16);
2633 if( !hBummer || !wndPtr )
2635 GlobalFree16(hDragInfo);
2636 return 0L;
2639 if(hCursor)
2641 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2643 GlobalFree16(hDragInfo);
2644 return 0L;
2647 if( hDragCursor == hCursor ) hDragCursor = 0;
2648 else hCursor = hDragCursor;
2650 hOldCursor = SetCursor32(hDragCursor);
2653 lpDragInfo->hWnd = hWnd;
2654 lpDragInfo->hScope = 0;
2655 lpDragInfo->wFlags = wObj;
2656 lpDragInfo->hList = szList; /* near pointer! */
2657 lpDragInfo->hOfStruct = hOfStruct;
2658 lpDragInfo->l = 0L;
2660 SetCapture32(hWnd);
2661 ShowCursor32( TRUE );
2665 do{ WaitMessage(); }
2666 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2668 *(lpDragInfo+1) = *lpDragInfo;
2670 lpDragInfo->pt = msg.pt;
2672 /* update DRAGINFO struct */
2673 TRACE(msg,"lpDI->hScope = %04x\n",lpDragInfo->hScope);
2675 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2676 hCurrentCursor = hCursor;
2677 else
2679 hCurrentCursor = hBummer;
2680 lpDragInfo->hScope = 0;
2682 if( hCurrentCursor )
2683 SetCursor32(hCurrentCursor);
2685 /* send WM_DRAGLOOP */
2686 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2687 (LPARAM) spDragInfo );
2688 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2689 if( hCurrentWnd != lpDragInfo->hScope )
2691 if( hCurrentWnd )
2692 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2693 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2694 HIWORD(spDragInfo)) );
2695 hCurrentWnd = lpDragInfo->hScope;
2696 if( hCurrentWnd )
2697 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2699 else
2700 if( hCurrentWnd )
2701 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2703 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2705 ReleaseCapture();
2706 ShowCursor32( FALSE );
2708 if( hCursor )
2710 SetCursor32( hOldCursor );
2711 if (hDragCursor) DestroyCursor32( hDragCursor );
2714 if( hCurrentCursor != hBummer )
2715 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2716 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2717 else
2718 msg.lParam = 0;
2719 GlobalFree16(hDragInfo);
2721 return (DWORD)(msg.lParam);