Release 970804
[wine/multimedia.git] / windows / win.c
blob3200d5a2095ddf8dcfcd9b4ced87a9f6fd10f49e
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <X11/Xatom.h>
12 #include "options.h"
13 #include "class.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "sysmetrics.h"
19 #include "cursoricon.h"
20 #include "heap.h"
21 #include "hook.h"
22 #include "menu.h"
23 #include "message.h"
24 #include "nonclient.h"
25 #include "queue.h"
26 #include "winpos.h"
27 #include "color.h"
28 #include "shm_main_blk.h"
29 #include "dde_proc.h"
30 #include "clipboard.h"
31 #include "winproc.h"
32 #include "thread.h"
33 #include "stddebug.h"
34 /* #define DEBUG_WIN */
35 /* #define DEBUG_MENU */
36 #include "debug.h"
38 /* Desktop window */
39 static WND *pWndDesktop = NULL;
41 static HWND32 hwndSysModal = 0;
43 static WORD wDragWidth = 4;
44 static WORD wDragHeight= 3;
46 extern BOOL32 ICONTITLE_Init(void);
47 extern BOOL32 MENU_PatchResidentPopup( HQUEUE16, WND* );
48 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
49 extern HWND32 CARET_GetHwnd(void);
50 extern BOOL32 WINPOS_CreateInternalPosAtom(void);
51 extern void WINPOS_CheckInternalPos(HWND32);
52 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
53 extern BOOL32 EVENT_CheckFocus(void);
55 /***********************************************************************
56 * WIN_FindWndPtr
58 * Return a pointer to the WND structure corresponding to a HWND.
60 WND * WIN_FindWndPtr( HWND32 hwnd )
62 WND * ptr;
64 if (!hwnd || HIWORD(hwnd)) return NULL;
65 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
66 if (ptr->dwMagic != WND_MAGIC) return NULL;
67 if (ptr->hwndSelf != hwnd)
69 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
70 hwnd, ptr->hwndSelf );
71 return NULL;
73 return ptr;
77 /***********************************************************************
78 * WIN_DumpWindow
80 * Dump the content of a window structure to stderr.
82 void WIN_DumpWindow( HWND32 hwnd )
84 WND *ptr;
85 char className[80];
86 int i;
88 if (!(ptr = WIN_FindWndPtr( hwnd )))
90 fprintf( stderr, "%04x is not a window handle\n", hwnd );
91 return;
94 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
95 strcpy( className, "#NULL#" );
97 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
98 fprintf( stderr,
99 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
100 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
101 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
102 "client=%d,%d-%d,%d window=%d,%d-%d,%d"
103 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
104 ptr->next, ptr->child, ptr->parent, ptr->owner,
105 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
106 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
107 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
108 ptr->text ? ptr->text : "",
109 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
110 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
111 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
112 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
114 if (ptr->class->cbWndExtra)
116 fprintf( stderr, "extra bytes:" );
117 for (i = 0; i < ptr->class->cbWndExtra; i++)
118 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
119 fprintf( stderr, "\n" );
121 fprintf( stderr, "\n" );
125 /***********************************************************************
126 * WIN_WalkWindows
128 * Walk the windows tree and print each window on stderr.
130 void WIN_WalkWindows( HWND32 hwnd, int indent )
132 WND *ptr;
133 char className[80];
135 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
136 if (!ptr)
138 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
139 return;
142 if (!indent) /* first time around */
143 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
144 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
146 while (ptr)
148 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
150 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
152 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
153 (DWORD)ptr, ptr->hmemTaskQ, className,
154 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
156 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
157 ptr = ptr->next;
162 /***********************************************************************
163 * WIN_GetXWindow
165 * Return the X window associated to a window.
167 Window WIN_GetXWindow( HWND32 hwnd )
169 WND *wndPtr = WIN_FindWndPtr( hwnd );
170 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
171 return wndPtr ? wndPtr->window : 0;
175 /***********************************************************************
176 * WIN_UnlinkWindow
178 * Remove a window from the siblings linked list.
180 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
182 WND *wndPtr, **ppWnd;
184 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
185 ppWnd = &wndPtr->parent->child;
186 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
187 *ppWnd = wndPtr->next;
188 return TRUE;
192 /***********************************************************************
193 * WIN_LinkWindow
195 * Insert a window into the siblings linked list.
196 * The window is inserted after the specified window, which can also
197 * be specified as HWND_TOP or HWND_BOTTOM.
199 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
201 WND *wndPtr, **ppWnd;
203 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
205 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
207 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
208 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
209 while (*ppWnd) ppWnd = &(*ppWnd)->next;
211 else /* Normal case */
213 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
214 if (!afterPtr) return FALSE;
215 ppWnd = &afterPtr->next;
217 wndPtr->next = *ppWnd;
218 *ppWnd = wndPtr;
219 return TRUE;
223 /***********************************************************************
224 * WIN_FindWinToRepaint
226 * Find a window that needs repaint.
228 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
230 HWND32 hwndRet;
231 WND *pWnd = pWndDesktop;
233 /* Note: the desktop window never gets WM_PAINT messages
234 * The real reason why is because Windows DesktopWndProc
235 * does ValidateRgn inside WM_ERASEBKGND handler.
238 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
240 for ( ; pWnd ; pWnd = pWnd->next )
242 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
244 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
245 pWnd->hwndSelf );
246 continue;
248 if ((pWnd->hmemTaskQ == hQueue) &&
249 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
251 if (pWnd->child )
252 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
253 return hwndRet;
256 if (!pWnd) return 0;
258 hwndRet = pWnd->hwndSelf;
260 /* look among siblings if we got a transparent window */
261 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
262 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
264 pWnd = pWnd->next;
266 if (pWnd) hwndRet = pWnd->hwndSelf;
267 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
268 return hwndRet;
272 /***********************************************************************
273 * WIN_SendParentNotify
275 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
276 * the window has the WS_EX_NOPARENTNOTIFY style.
278 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
280 LPPOINT16 lppt = (LPPOINT16)&lValue;
281 WND *wndPtr = WIN_FindWndPtr( hwnd );
282 BOOL32 bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
284 /* if lValue contains cursor coordinates they have to be
285 * mapped to the client area of parent window */
287 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
289 while (wndPtr)
291 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
292 !(wndPtr->dwStyle & WS_CHILD)) break;
294 if (bMouse)
296 lppt->x += wndPtr->rectClient.left;
297 lppt->y += wndPtr->rectClient.top;
300 wndPtr = wndPtr->parent;
301 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
302 MAKEWPARAM( event, idChild ), lValue );
307 /***********************************************************************
308 * WIN_DestroyWindow
310 * Destroy storage associated to a window. "Internals" p.358
312 static WND* WIN_DestroyWindow( WND* wndPtr )
314 HWND32 hwnd = wndPtr->hwndSelf;
315 WND *pWnd;
317 dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
319 #ifdef CONFIG_IPC
320 if (main_block)
321 DDE_DestroyWindow(wndPtr->hwndSelf);
322 #endif /* CONFIG_IPC */
324 /* free child windows */
326 while ((pWnd = wndPtr->child))
327 wndPtr->child = WIN_DestroyWindow( pWnd );
329 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
331 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
333 WINPOS_CheckInternalPos( hwnd );
334 if( hwnd == GetCapture32()) ReleaseCapture();
336 /* free resources associated with the window */
338 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
339 PROPERTY_RemoveWindowProps( wndPtr );
341 wndPtr->dwMagic = 0; /* Mark it as invalid */
342 wndPtr->hwndSelf = 0;
344 if ((wndPtr->hrgnUpdate) || (wndPtr->flags & WIN_INTERNAL_PAINT))
346 if (wndPtr->hrgnUpdate) DeleteObject32( wndPtr->hrgnUpdate );
347 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
350 /* toss stale messages from the queue */
352 if( wndPtr->hmemTaskQ )
354 int pos;
355 MESSAGEQUEUE* msgQ = (MESSAGEQUEUE*) GlobalLock16(wndPtr->hmemTaskQ);
357 while( (pos = QUEUE_FindMsg(msgQ, hwnd, 0, 0)) != -1 )
358 QUEUE_RemoveMsg(msgQ, pos);
359 wndPtr->hmemTaskQ = 0;
362 if (!(wndPtr->dwStyle & WS_CHILD))
363 if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
364 if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
365 if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
366 if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
368 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
370 wndPtr->class->cWindows--;
371 wndPtr->class = NULL;
372 pWnd = wndPtr->next;
374 USER_HEAP_FREE( hwnd );
375 return pWnd;
378 /***********************************************************************
379 * WIN_ResetQueueWindows
381 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
383 WND* next;
385 while (wnd)
387 next = wnd->next;
388 if (wnd->hmemTaskQ == hQueue)
389 if( hNew ) wnd->hmemTaskQ = hNew;
390 else DestroyWindow32( wnd->hwndSelf );
391 else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
392 wnd = next;
396 /***********************************************************************
397 * WIN_CreateDesktopWindow
399 * Create the desktop window.
401 BOOL32 WIN_CreateDesktopWindow(void)
403 CLASS *class;
404 HWND32 hwndDesktop;
406 dprintf_win(stddeb,"Creating desktop window\n");
408 if (!ICONTITLE_Init() ||
409 !WINPOS_CreateInternalPosAtom() ||
410 !(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
411 return FALSE;
413 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
414 if (!hwndDesktop) return FALSE;
415 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
417 pWndDesktop->next = NULL;
418 pWndDesktop->child = NULL;
419 pWndDesktop->parent = NULL;
420 pWndDesktop->owner = NULL;
421 pWndDesktop->class = class;
422 pWndDesktop->dwMagic = WND_MAGIC;
423 pWndDesktop->hwndSelf = hwndDesktop;
424 pWndDesktop->hInstance = 0;
425 pWndDesktop->rectWindow.left = 0;
426 pWndDesktop->rectWindow.top = 0;
427 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
428 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
429 pWndDesktop->rectClient = pWndDesktop->rectWindow;
430 pWndDesktop->text = NULL;
431 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
432 pWndDesktop->hrgnUpdate = 0;
433 pWndDesktop->hwndLastActive = hwndDesktop;
434 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
435 WS_CLIPSIBLINGS;
436 pWndDesktop->dwExStyle = 0;
437 pWndDesktop->dce = NULL;
438 pWndDesktop->pVScroll = NULL;
439 pWndDesktop->pHScroll = NULL;
440 pWndDesktop->pProp = NULL;
441 pWndDesktop->wIDmenu = 0;
442 pWndDesktop->flags = 0;
443 pWndDesktop->window = rootWindow;
444 pWndDesktop->hSysMenu = 0;
445 pWndDesktop->userdata = 0;
447 pWndDesktop->winproc = (WNDPROC16)class->winproc;
449 EVENT_RegisterWindow( pWndDesktop );
450 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
451 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
452 return TRUE;
456 /***********************************************************************
457 * WIN_CreateWindowEx
459 * Implementation of CreateWindowEx().
461 static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
462 BOOL32 win32, BOOL32 unicode )
464 CLASS *classPtr;
465 WND *wndPtr;
466 HWND16 hwnd, hwndLinkAfter;
467 POINT32 maxSize, maxPos, minTrack, maxTrack;
468 LRESULT (*localSend32)(HWND32, UINT32, WPARAM32, LPARAM);
470 dprintf_win( stddeb, "CreateWindowEx: " );
471 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
472 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
473 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
474 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
476 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
477 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
478 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
480 /* Find the parent window */
482 if (cs->hwndParent)
484 /* Make sure parent is valid */
485 if (!IsWindow32( cs->hwndParent ))
487 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
488 return 0;
491 else if (cs->style & WS_CHILD)
493 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
494 return 0; /* WS_CHILD needs a parent */
497 /* Find the window class */
499 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
500 GetExePtr(cs->hInstance) )))
502 char buffer[256];
503 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
504 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
505 return 0;
508 /* Fix the coordinates */
510 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
511 if (cs->cx == CW_USEDEFAULT32)
513 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
514 else */
516 cs->cx = 600;
517 cs->cy = 400;
521 /* Create the window structure */
523 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
524 - sizeof(wndPtr->wExtra) )))
526 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
527 return 0;
530 /* Fill the window structure */
532 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
533 wndPtr->next = NULL;
534 wndPtr->child = NULL;
536 if (cs->style & WS_CHILD)
538 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
539 wndPtr->owner = NULL;
541 else
543 wndPtr->parent = pWndDesktop;
544 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
545 wndPtr->owner = NULL;
546 else
547 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
550 wndPtr->window = 0;
551 wndPtr->class = classPtr;
552 wndPtr->winproc = classPtr->winproc;
553 wndPtr->dwMagic = WND_MAGIC;
554 wndPtr->hwndSelf = hwnd;
555 wndPtr->hInstance = cs->hInstance;
556 wndPtr->text = NULL;
557 wndPtr->hmemTaskQ = GetTaskQueue(0);
558 wndPtr->hrgnUpdate = 0;
559 wndPtr->hwndLastActive = hwnd;
560 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
561 wndPtr->dwExStyle = cs->dwExStyle;
562 wndPtr->wIDmenu = 0;
563 wndPtr->flags = win32 ? WIN_ISWIN32 : 0;
564 wndPtr->pVScroll = NULL;
565 wndPtr->pHScroll = NULL;
566 wndPtr->pProp = NULL;
567 wndPtr->userdata = 0;
568 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
569 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
571 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
573 /* Call the WH_CBT hook */
575 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
577 if (HOOK_IsHooked( WH_CBT ))
579 CBT_CREATEWND32A cbtc;
581 cbtc.lpcs = cs;
582 cbtc.hwndInsertAfter = hwndLinkAfter;
583 if ( HOOK_CallHooks32A(WH_CBT, HCBT_CREATEWND, hwnd, (LPARAM)&cbtc) )
585 dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
586 USER_HEAP_FREE( hwnd );
587 return 0;
591 /* Increment class window counter */
593 classPtr->cWindows++;
595 /* Correct the window style */
597 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
599 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
600 wndPtr->flags |= WIN_NEED_SIZE;
602 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
604 /* Get class or window DC if needed */
606 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
607 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
608 else wndPtr->dce = NULL;
610 /* Insert the window in the linked list */
612 WIN_LinkWindow( hwnd, hwndLinkAfter );
614 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
616 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
618 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack);
619 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
620 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
621 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
622 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
624 if (cs->cx <= 0) cs->cx = 1;
625 if (cs->cy <= 0) cs->cy = 1;
627 wndPtr->rectWindow.left = cs->x;
628 wndPtr->rectWindow.top = cs->y;
629 wndPtr->rectWindow.right = cs->x + cs->cx;
630 wndPtr->rectWindow.bottom = cs->y + cs->cy;
631 wndPtr->rectClient = wndPtr->rectWindow;
633 /* Create the X window (only for top-level windows, and then only */
634 /* when there's no desktop window) */
636 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
638 XSetWindowAttributes win_attr;
640 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
641 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
643 win_attr.event_mask = ExposureMask | KeyPressMask |
644 KeyReleaseMask | PointerMotionMask |
645 ButtonPressMask | ButtonReleaseMask |
646 FocusChangeMask | StructureNotifyMask;
647 win_attr.override_redirect = FALSE;
648 wndPtr->flags |= WIN_MANAGED;
650 else
652 win_attr.event_mask = ExposureMask | KeyPressMask |
653 KeyReleaseMask | PointerMotionMask |
654 ButtonPressMask | ButtonReleaseMask |
655 FocusChangeMask | StructureNotifyMask;
656 win_attr.override_redirect = TRUE;
658 win_attr.colormap = COLOR_GetColormap();
659 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
660 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
661 win_attr.cursor = CURSORICON_XCursor;
662 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
663 cs->cx, cs->cy, 0, CopyFromParent,
664 InputOutput, CopyFromParent,
665 CWEventMask | CWOverrideRedirect |
666 CWColormap | CWCursor | CWSaveUnder |
667 CWBackingStore, &win_attr );
669 if ((wndPtr->flags & WIN_MANAGED) &&
670 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
672 XSizeHints* size_hints = XAllocSizeHints();
674 if (size_hints)
676 size_hints->min_width = size_hints->max_width = cs->cx;
677 size_hints->min_height = size_hints->max_height = cs->cy;
678 size_hints->flags = (PSize | PMinSize | PMaxSize);
679 XSetWMSizeHints( display, wndPtr->window, size_hints,
680 XA_WM_NORMAL_HINTS );
681 XFree(size_hints);
685 if (cs->hwndParent) /* Get window owner */
687 Window win = WIN_GetXWindow( cs->hwndParent );
688 if (win) XSetTransientForHint( display, wndPtr->window, win );
690 EVENT_RegisterWindow( wndPtr );
693 /* Set the window menu */
695 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
697 if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
698 else
700 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
701 if (classPtr->menuNameA)
702 cs->hMenu = HIWORD(classPtr->menuNameA) ?
703 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
704 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
705 #else
706 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
707 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
708 #endif
710 if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
712 else wndPtr->wIDmenu = (UINT32)cs->hMenu;
714 /* Send the WM_CREATE message
715 * Perhaps we shouldn't allow width/height changes as well.
716 * See p327 in "Internals".
719 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
721 localSend32 = unicode ? SendMessage32W : SendMessage32A;
722 if( (*localSend32)( hwnd, WM_NCCREATE, 0, (LPARAM)cs) )
724 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
725 NULL, NULL, 0, &wndPtr->rectClient );
726 OffsetRect32(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
727 maxPos.y - wndPtr->rectWindow.top);
728 if( ((*localSend32)( hwnd, WM_CREATE, 0, (LPARAM)cs )) != -1 )
730 /* Send the size messages */
732 if (!(wndPtr->flags & WIN_NEED_SIZE))
734 /* send it anyway */
735 SendMessage32A( hwnd, WM_SIZE, SIZE_RESTORED,
736 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
737 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
738 SendMessage32A( hwnd, WM_MOVE, 0,
739 MAKELONG( wndPtr->rectClient.left,
740 wndPtr->rectClient.top ) );
743 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
744 if (!IsWindow32(hwnd)) return 0;
746 /* Show the window, maximizing or minimizing if needed */
748 if (wndPtr->dwStyle & WS_MINIMIZE)
750 RECT16 newPos;
751 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
752 WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
753 SetWindowPos32( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom,
754 SWP_FRAMECHANGED | ((GetActiveWindow32())? SWP_NOACTIVATE : 0));
756 else if (wndPtr->dwStyle & WS_MAXIMIZE)
758 RECT16 newPos;
759 wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
760 WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
761 SetWindowPos32( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom,
762 ((GetActiveWindow32())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
765 if (cs->style & WS_VISIBLE) ShowWindow32( hwnd, SW_SHOW );
767 /* Call WH_SHELL hook */
769 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
770 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
772 dprintf_win(stddeb, "CreateWindowEx: created window %04x\n", hwnd);
773 return hwnd;
777 /* Abort window creation */
779 dprintf_win(stddeb,"CreateWindowEx: aborted by WM_xxCREATE!\n");
780 WIN_UnlinkWindow( hwnd );
781 WIN_DestroyWindow( wndPtr );
782 return 0;
786 /***********************************************************************
787 * CreateWindow16 (USER.41)
789 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
790 DWORD style, INT16 x, INT16 y, INT16 width,
791 INT16 height, HWND16 parent, HMENU16 menu,
792 HINSTANCE16 instance, LPVOID data )
794 return CreateWindowEx16( 0, className, windowName, style,
795 x, y, width, height, parent, menu, instance, data );
799 /***********************************************************************
800 * CreateWindowEx16 (USER.452)
802 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
803 DWORD style, INT16 x, INT16 y, INT16 width,
804 INT16 height, HWND16 parent, HMENU16 menu,
805 HINSTANCE16 instance, LPVOID data )
807 ATOM classAtom;
808 CREATESTRUCT32A cs;
810 /* Find the class atom */
812 if (!(classAtom = GlobalFindAtom32A( className )))
814 fprintf( stderr, "CreateWindowEx16: bad class name " );
815 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
816 else fprintf( stderr, "'%s'\n", className );
817 return 0;
820 /* Fix the coordinates */
822 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
823 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
824 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
825 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
827 /* Create the window */
829 cs.lpCreateParams = data;
830 cs.hInstance = (HINSTANCE32)instance;
831 cs.hMenu = (HMENU32)menu;
832 cs.hwndParent = (HWND32)parent;
833 cs.style = style;
834 cs.lpszName = windowName;
835 cs.lpszClass = className;
836 cs.dwExStyle = exStyle;
837 return WIN_CreateWindowEx( &cs, classAtom, FALSE, FALSE );
841 /***********************************************************************
842 * CreateWindowEx32A (USER32.82)
844 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
845 DWORD style, INT32 x, INT32 y, INT32 width,
846 INT32 height, HWND32 parent, HMENU32 menu,
847 HINSTANCE32 instance, LPVOID data )
849 ATOM classAtom;
850 CREATESTRUCT32A cs;
852 /* Find the class atom */
854 if (!(classAtom = GlobalFindAtom32A( className )))
856 fprintf( stderr, "CreateWindowEx32A: bad class name " );
857 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
858 else fprintf( stderr, "'%s'\n", className );
859 return 0;
862 /* Create the window */
864 cs.lpCreateParams = data;
865 cs.hInstance = instance;
866 cs.hMenu = menu;
867 cs.hwndParent = parent;
868 cs.x = x;
869 cs.y = y;
870 cs.cx = width;
871 cs.cy = height;
872 cs.style = style;
873 cs.lpszName = windowName;
874 cs.lpszClass = className;
875 cs.dwExStyle = exStyle;
876 return WIN_CreateWindowEx( &cs, classAtom, TRUE, FALSE );
880 /***********************************************************************
881 * CreateWindowEx32W (USER32.83)
883 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
884 DWORD style, INT32 x, INT32 y, INT32 width,
885 INT32 height, HWND32 parent, HMENU32 menu,
886 HINSTANCE32 instance, LPVOID data )
888 ATOM classAtom;
889 CREATESTRUCT32W cs;
891 /* Find the class atom */
893 if (!(classAtom = GlobalFindAtom32W( className )))
895 if (HIWORD(className))
897 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
898 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
899 HeapFree( GetProcessHeap(), 0, cn );
901 else
902 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
903 return 0;
906 /* Create the window */
908 cs.lpCreateParams = data;
909 cs.hInstance = instance;
910 cs.hMenu = menu;
911 cs.hwndParent = parent;
912 cs.x = x;
913 cs.y = y;
914 cs.cx = width;
915 cs.cy = height;
916 cs.style = style;
917 cs.lpszName = windowName;
918 cs.lpszClass = className;
919 cs.dwExStyle = exStyle;
920 /* Note: we rely on the fact that CREATESTRUCT32A and */
921 /* CREATESTRUCT32W have the same layout. */
922 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE, TRUE );
926 /***********************************************************************
927 * WIN_CheckFocus
929 static void WIN_CheckFocus( WND* pWnd )
931 if( GetFocus16() == pWnd->hwndSelf )
932 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
935 /***********************************************************************
936 * WIN_SendDestroyMsg
938 static void WIN_SendDestroyMsg( WND* pWnd )
940 WND* pChild;
942 WIN_CheckFocus(pWnd);
944 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32();
945 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
947 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
949 if( !IsWindow32(pWnd->hwndSelf) )
951 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
952 return;
955 pChild = pWnd->child;
956 while( pChild )
958 WIN_SendDestroyMsg( pChild );
959 pChild = pChild->next;
961 WIN_CheckFocus(pWnd);
965 /***********************************************************************
966 * DestroyWindow (USER.53)
968 BOOL16 DestroyWindow16( HWND16 hwnd )
970 return DestroyWindow32(hwnd);
972 /***********************************************************************
973 * DestroyWindow (USER32.134)
975 BOOL32 DestroyWindow32( HWND32 hwnd )
977 WND * wndPtr;
979 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
981 /* Initialization */
983 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
984 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
986 /* Call hooks */
988 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
989 return FALSE;
991 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
993 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
994 /* FIXME: clean up palette - see "Internals" p.352 */
997 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
998 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
999 if (!IsWindow32(hwnd)) return TRUE;
1001 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1003 /* Hide the window */
1005 if (wndPtr->dwStyle & WS_VISIBLE)
1007 SetWindowPos32( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1008 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|
1009 ((QUEUE_IsExitingQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1010 if (!IsWindow32(hwnd)) return TRUE;
1013 /* Recursively destroy owned windows */
1015 if( !(wndPtr->dwStyle & WS_CHILD) )
1017 /* make sure top menu popup doesn't get destroyed */
1018 MENU_PatchResidentPopup( TRUE, wndPtr );
1020 for (;;)
1022 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1023 while (siblingPtr)
1025 if (siblingPtr->owner == wndPtr)
1026 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1027 break;
1028 else
1029 siblingPtr->owner = NULL;
1030 siblingPtr = siblingPtr->next;
1032 if (siblingPtr) DestroyWindow32( siblingPtr->hwndSelf );
1033 else break;
1036 if( !Options.managed || EVENT_CheckFocus() )
1037 WINPOS_ActivateOtherWindow(wndPtr);
1039 if( wndPtr->owner &&
1040 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1041 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1044 /* Send destroy messages */
1046 WIN_SendDestroyMsg( wndPtr );
1047 if (!IsWindow32(hwnd)) return TRUE;
1049 /* Unlink now so we won't bother with the children later on */
1051 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1053 /* Destroy the window storage */
1055 WIN_DestroyWindow( wndPtr );
1056 return TRUE;
1060 /***********************************************************************
1061 * CloseWindow16 (USER.43)
1063 BOOL16 CloseWindow16( HWND16 hwnd )
1065 return CloseWindow32( hwnd );
1069 /***********************************************************************
1070 * CloseWindow32 (USER32.55)
1072 BOOL32 CloseWindow32( HWND32 hwnd )
1074 WND * wndPtr = WIN_FindWndPtr( hwnd );
1075 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return FALSE;
1076 ShowWindow32( hwnd, SW_MINIMIZE );
1077 return TRUE;
1081 /***********************************************************************
1082 * OpenIcon16 (USER.44)
1084 BOOL16 OpenIcon16( HWND16 hwnd )
1086 return OpenIcon32( hwnd );
1090 /***********************************************************************
1091 * OpenIcon32 (USER32.409)
1093 BOOL32 OpenIcon32( HWND32 hwnd )
1095 if (!IsIconic32( hwnd )) return FALSE;
1096 ShowWindow32( hwnd, SW_SHOWNORMAL );
1097 return TRUE;
1101 /***********************************************************************
1102 * WIN_FindWindow
1104 * Implementation of FindWindow() and FindWindowEx().
1106 static HWND32 WIN_FindWindow( HWND32 parent, HWND32 child, ATOM className,
1107 LPCSTR title )
1109 WND *pWnd;
1110 CLASS *pClass = NULL;
1112 if (child)
1114 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1115 if (parent)
1117 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1119 else if (pWnd->parent != pWndDesktop) return 0;
1120 pWnd = pWnd->next;
1122 else
1124 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1125 pWnd = pWnd->child;
1127 if (!pWnd) return 0;
1129 /* For a child window, all siblings will have the same hInstance, */
1130 /* so we can look for the class once and for all. */
1132 if (className && (pWnd->dwStyle & WS_CHILD))
1134 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1135 return 0;
1138 for ( ; pWnd; pWnd = pWnd->next)
1140 if (className && !(pWnd->dwStyle & WS_CHILD))
1142 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1143 continue; /* Skip this window */
1145 if (pClass && (pWnd->class != pClass))
1146 continue; /* Not the right class */
1148 /* Now check the title */
1150 if (!title) return pWnd->hwndSelf;
1151 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1153 return 0;
1158 /***********************************************************************
1159 * FindWindow16 (USER.50)
1161 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1163 return FindWindowEx16( 0, 0, className, title );
1167 /***********************************************************************
1168 * FindWindowEx16 (USER.427)
1170 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1171 SEGPTR className, LPCSTR title )
1173 ATOM atom = 0;
1175 dprintf_win(stddeb, "FindWindowEx16: %04x %04x '%s' '%s'\n", parent,
1176 child, HIWORD(className)?(char *)PTR_SEG_TO_LIN(className):"",
1177 title ? title : "");
1179 if (className)
1181 /* If the atom doesn't exist, then no class */
1182 /* with this name exists either. */
1183 if (!(atom = GlobalFindAtom16( className ))) return 0;
1185 return WIN_FindWindow( parent, child, atom, title );
1189 /***********************************************************************
1190 * FindWindow32A (USER32.197)
1192 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1194 return FindWindowEx32A( 0, 0, className, title );
1198 /***********************************************************************
1199 * FindWindowEx32A (USER32.198)
1201 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1202 LPCSTR className, LPCSTR title )
1204 ATOM atom = 0;
1206 if (className)
1208 /* If the atom doesn't exist, then no class */
1209 /* with this name exists either. */
1210 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1212 return WIN_FindWindow( 0, 0, atom, title );
1216 /***********************************************************************
1217 * FindWindowEx32W (USER32.199)
1219 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1220 LPCWSTR className, LPCWSTR title )
1222 ATOM atom = 0;
1223 char *buffer;
1224 HWND32 hwnd;
1226 if (className)
1228 /* If the atom doesn't exist, then no class */
1229 /* with this name exists either. */
1230 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1232 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1233 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1234 HeapFree( GetProcessHeap(), 0, buffer );
1235 return hwnd;
1239 /***********************************************************************
1240 * FindWindow32W (USER32.200)
1242 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1244 return FindWindowEx32W( 0, 0, className, title );
1248 /**********************************************************************
1249 * WIN_GetDesktop
1251 WND *WIN_GetDesktop(void)
1253 return pWndDesktop;
1257 /**********************************************************************
1258 * GetDesktopWindow16 (USER.286)
1260 HWND16 GetDesktopWindow16(void)
1262 return (HWND16)pWndDesktop->hwndSelf;
1266 /**********************************************************************
1267 * GetDesktopWindow32 (USER32.231)
1269 HWND32 GetDesktopWindow32(void)
1271 return pWndDesktop->hwndSelf;
1275 /**********************************************************************
1276 * GetDesktopHwnd (USER.278)
1278 * Exactly the same thing as GetDesktopWindow(), but not documented.
1279 * Don't ask me why...
1281 HWND16 GetDesktopHwnd(void)
1283 return (HWND16)pWndDesktop->hwndSelf;
1287 /*******************************************************************
1288 * EnableWindow16 (USER.34)
1290 BOOL16 EnableWindow16( HWND16 hwnd, BOOL16 enable )
1292 return EnableWindow32( hwnd, enable );
1296 /*******************************************************************
1297 * EnableWindow32 (USER32.171)
1299 BOOL32 EnableWindow32( HWND32 hwnd, BOOL32 enable )
1301 WND *wndPtr;
1303 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1304 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1306 /* Enable window */
1307 wndPtr->dwStyle &= ~WS_DISABLED;
1308 SendMessage32A( hwnd, WM_ENABLE, TRUE, 0 );
1309 return TRUE;
1311 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1313 /* Disable window */
1314 wndPtr->dwStyle |= WS_DISABLED;
1315 if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32() ))
1316 SetFocus32( 0 ); /* A disabled window can't have the focus */
1317 if ((hwnd == GetCapture32()) || IsChild32( hwnd, GetCapture32() ))
1318 ReleaseCapture(); /* A disabled window can't capture the mouse */
1319 SendMessage32A( hwnd, WM_ENABLE, FALSE, 0 );
1320 return FALSE;
1322 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1326 /***********************************************************************
1327 * IsWindowEnabled16 (USER.35)
1329 BOOL16 IsWindowEnabled16(HWND16 hWnd)
1331 return IsWindowEnabled32(hWnd);
1335 /***********************************************************************
1336 * IsWindowEnabled32 (USER32.348)
1338 BOOL32 IsWindowEnabled32(HWND32 hWnd)
1340 WND * wndPtr;
1342 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1343 return !(wndPtr->dwStyle & WS_DISABLED);
1347 /***********************************************************************
1348 * IsWindowUnicode (USER32.349)
1350 BOOL32 IsWindowUnicode( HWND32 hwnd )
1352 WND * wndPtr;
1354 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1355 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1359 /**********************************************************************
1360 * GetWindowWord16 (USER.133)
1362 WORD GetWindowWord16( HWND16 hwnd, INT16 offset )
1364 return GetWindowWord32( hwnd, offset );
1368 /**********************************************************************
1369 * GetWindowWord32 (USER32.313)
1371 WORD GetWindowWord32( HWND32 hwnd, INT32 offset )
1373 WND * wndPtr = WIN_FindWndPtr( hwnd );
1374 if (!wndPtr) return 0;
1375 if (offset >= 0)
1377 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1379 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1380 return 0;
1382 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1384 switch(offset)
1386 case GWW_ID: return wndPtr->wIDmenu;
1387 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1388 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1389 default:
1390 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1391 return 0;
1396 /**********************************************************************
1397 * WIN_GetWindowInstance
1399 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1401 WND * wndPtr = WIN_FindWndPtr( hwnd );
1402 if (!wndPtr) return (HINSTANCE16)0;
1403 return wndPtr->hInstance;
1407 /**********************************************************************
1408 * SetWindowWord16 (USER.134)
1410 WORD SetWindowWord16( HWND16 hwnd, INT16 offset, WORD newval )
1412 return SetWindowWord32( hwnd, offset, newval );
1416 /**********************************************************************
1417 * SetWindowWord32 (USER32.523)
1419 WORD SetWindowWord32( HWND32 hwnd, INT32 offset, WORD newval )
1421 WORD *ptr, retval;
1422 WND * wndPtr = WIN_FindWndPtr( hwnd );
1423 if (!wndPtr) return 0;
1424 if (offset >= 0)
1426 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1428 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1429 return 0;
1431 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1433 else switch(offset)
1435 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1436 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1437 case GWW_HWNDPARENT: return SetParent32( hwnd, newval );
1438 default:
1439 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1440 return 0;
1442 retval = *ptr;
1443 *ptr = newval;
1444 return retval;
1448 /**********************************************************************
1449 * WIN_GetWindowLong
1451 * Helper function for GetWindowLong().
1453 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1455 LONG retval;
1456 WND * wndPtr = WIN_FindWndPtr( hwnd );
1457 if (!wndPtr) return 0;
1458 if (offset >= 0)
1460 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1462 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1463 return 0;
1465 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1466 /* Special case for dialog window procedure */
1467 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1468 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1469 return retval;
1471 switch(offset)
1473 case GWL_USERDATA: return wndPtr->userdata;
1474 case GWL_STYLE: return wndPtr->dwStyle;
1475 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1476 case GWL_ID: return wndPtr->wIDmenu;
1477 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1478 type );
1479 case GWL_HWNDPARENT: return wndPtr->parent ?
1480 (HWND32)wndPtr->parent->hwndSelf : 0;
1481 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1482 default:
1483 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1485 return 0;
1489 /**********************************************************************
1490 * WIN_SetWindowLong
1492 * Helper function for SetWindowLong().
1494 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1495 WINDOWPROCTYPE type )
1497 LONG *ptr, retval;
1498 WND * wndPtr = WIN_FindWndPtr( hwnd );
1499 if (!wndPtr) return 0;
1500 if (offset >= 0)
1502 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1504 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1505 return 0;
1507 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1508 /* Special case for dialog window procedure */
1509 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1511 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1512 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1513 type, WIN_PROC_WINDOW );
1514 return retval;
1517 else switch(offset)
1519 case GWL_ID:
1520 case GWL_HINSTANCE:
1521 return SetWindowWord32( hwnd, offset, (WORD)newval );
1522 case GWL_WNDPROC:
1523 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1524 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1525 type, WIN_PROC_WINDOW );
1526 return retval;
1527 case GWL_STYLE:
1529 /* FIXME: WM_STYLE... messages for WIN_ISWIN32 windows */
1531 ptr = &wndPtr->dwStyle;
1532 /* Some bits can't be changed this way */
1533 newval &= ~(WS_VISIBLE | WS_CHILD);
1534 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1535 break;
1536 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1537 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1538 default:
1539 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1540 return 0;
1542 retval = *ptr;
1543 *ptr = newval;
1544 return retval;
1548 /**********************************************************************
1549 * GetWindowLong16 (USER.135)
1551 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1553 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1557 /**********************************************************************
1558 * GetWindowLong32A (USER32.304)
1560 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1562 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1566 /**********************************************************************
1567 * GetWindowLong32W (USER32.305)
1569 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1571 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1575 /**********************************************************************
1576 * SetWindowLong16 (USER.136)
1578 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1580 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1584 /**********************************************************************
1585 * SetWindowLong32A (USER32.516)
1587 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1589 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1593 /**********************************************************************
1594 * SetWindowLong32W (USER32.517)
1596 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1598 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1602 /*******************************************************************
1603 * GetWindowText16 (USER.36)
1605 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1607 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1611 /*******************************************************************
1612 * GetWindowText32A (USER32.308)
1614 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1616 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1617 (LPARAM)lpString );
1621 /*******************************************************************
1622 * GetWindowText32W (USER32.311)
1624 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1626 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1627 (LPARAM)lpString );
1631 /*******************************************************************
1632 * SetWindowText16 (USER.37)
1634 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1636 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1640 /*******************************************************************
1641 * SetWindowText32A (USER32.)
1643 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1645 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1649 /*******************************************************************
1650 * SetWindowText32W (USER32.)
1652 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1654 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1658 /*******************************************************************
1659 * GetWindowTextLength16 (USER.38)
1661 INT16 GetWindowTextLength16( HWND16 hwnd )
1663 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1667 /*******************************************************************
1668 * GetWindowTextLength32A (USER32.309)
1670 INT32 GetWindowTextLength32A( HWND32 hwnd )
1672 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1675 /*******************************************************************
1676 * GetWindowTextLength32W (USER32.309)
1678 INT32 GetWindowTextLength32W( HWND32 hwnd )
1680 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1684 /*******************************************************************
1685 * IsWindow16 (USER.47)
1687 BOOL16 IsWindow16( HWND16 hwnd )
1689 return IsWindow32( hwnd );
1693 /*******************************************************************
1694 * IsWindow32 (USER32.347)
1696 BOOL32 IsWindow32( HWND32 hwnd )
1698 WND * wndPtr = WIN_FindWndPtr( hwnd );
1699 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1703 /*****************************************************************
1704 * GetParent16 (USER.46)
1706 HWND16 GetParent16( HWND16 hwnd )
1708 return (HWND16)GetParent32( hwnd );
1712 /*****************************************************************
1713 * GetParent32 (USER32.277)
1715 HWND32 GetParent32( HWND32 hwnd )
1717 WND *wndPtr = WIN_FindWndPtr(hwnd);
1718 if (!wndPtr) return 0;
1719 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1720 return wndPtr ? wndPtr->hwndSelf : 0;
1724 /*****************************************************************
1725 * WIN_GetTopParent
1727 * Get the top-level parent for a child window.
1729 HWND32 WIN_GetTopParent( HWND32 hwnd )
1731 WND *wndPtr = WIN_FindWndPtr( hwnd );
1732 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1733 return wndPtr ? wndPtr->hwndSelf : 0;
1737 /*****************************************************************
1738 * SetParent16 (USER.233)
1740 HWND16 SetParent16( HWND16 hwndChild, HWND16 hwndNewParent )
1742 return SetParent32( hwndChild, hwndNewParent );
1746 /*****************************************************************
1747 * SetParent32 (USER32.494)
1749 HWND32 SetParent32( HWND32 hwndChild, HWND32 hwndNewParent )
1751 HWND32 oldParent;
1753 WND *wndPtr = WIN_FindWndPtr( hwndChild );
1754 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1755 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1757 oldParent = wndPtr->parent->hwndSelf;
1759 WIN_UnlinkWindow(hwndChild);
1760 if (hwndNewParent) wndPtr->parent = pWndParent;
1761 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1763 if (IsWindowVisible32(hwndChild)) UpdateWindow32(hwndChild);
1765 return oldParent;
1769 /*******************************************************************
1770 * IsChild16 (USER.48)
1772 BOOL16 IsChild16( HWND16 parent, HWND16 child )
1774 return IsChild32(parent,child);
1778 /*******************************************************************
1779 * IsChild32 (USER32.338)
1781 BOOL32 IsChild32( HWND32 parent, HWND32 child )
1783 WND * wndPtr = WIN_FindWndPtr( child );
1784 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1786 wndPtr = wndPtr->parent;
1787 if (wndPtr->hwndSelf == parent) return TRUE;
1789 return FALSE;
1793 /***********************************************************************
1794 * IsWindowVisible16 (USER.49)
1796 BOOL16 IsWindowVisible16( HWND16 hwnd )
1798 return IsWindowVisible32(hwnd);
1802 /***********************************************************************
1803 * IsWindowVisible32 (USER32.350)
1805 BOOL32 IsWindowVisible32( HWND32 hwnd )
1807 WND *wndPtr = WIN_FindWndPtr( hwnd );
1808 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1810 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1811 wndPtr = wndPtr->parent;
1813 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1817 /***********************************************************************
1818 * WIN_IsWindowDrawable
1820 * hwnd is drawable when it is visible, all parents are not
1821 * minimized, and it is itself not minimized unless we are
1822 * trying to draw its default class icon.
1824 BOOL32 WIN_IsWindowDrawable( WND* wnd, BOOL32 icon )
1826 if( (wnd->dwStyle & WS_MINIMIZE &&
1827 icon && wnd->class->hIcon) ||
1828 !(wnd->dwStyle & WS_VISIBLE) ) return FALSE;
1829 for(wnd = wnd->parent; wnd; wnd = wnd->parent)
1830 if( wnd->dwStyle & WS_MINIMIZE ||
1831 !(wnd->dwStyle & WS_VISIBLE) ) break;
1832 return (wnd == NULL);
1836 /*******************************************************************
1837 * GetTopWindow16 (USER.229)
1839 HWND16 GetTopWindow16( HWND16 hwnd )
1841 return GetTopWindow32(hwnd);
1845 /*******************************************************************
1846 * GetTopWindow32 (USER.229)
1848 HWND32 GetTopWindow32( HWND32 hwnd )
1850 WND * wndPtr = WIN_FindWndPtr( hwnd );
1851 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1852 else return 0;
1856 /*******************************************************************
1857 * GetWindow16 (USER.262)
1859 HWND16 GetWindow16( HWND16 hwnd, WORD rel )
1861 return GetWindow32( hwnd,rel );
1865 /*******************************************************************
1866 * GetWindow32 (USER32.301)
1868 HWND32 GetWindow32( HWND32 hwnd, WORD rel )
1870 WND * wndPtr = WIN_FindWndPtr( hwnd );
1871 if (!wndPtr) return 0;
1872 switch(rel)
1874 case GW_HWNDFIRST:
1875 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1876 else return 0;
1878 case GW_HWNDLAST:
1879 if (!wndPtr->parent) return 0; /* Desktop window */
1880 while (wndPtr->next) wndPtr = wndPtr->next;
1881 return wndPtr->hwndSelf;
1883 case GW_HWNDNEXT:
1884 if (!wndPtr->next) return 0;
1885 return wndPtr->next->hwndSelf;
1887 case GW_HWNDPREV:
1888 if (!wndPtr->parent) return 0; /* Desktop window */
1889 wndPtr = wndPtr->parent->child; /* First sibling */
1890 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1891 while (wndPtr->next)
1893 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1894 wndPtr = wndPtr->next;
1896 return 0;
1898 case GW_OWNER:
1899 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1901 case GW_CHILD:
1902 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1904 return 0;
1908 /*******************************************************************
1909 * GetNextWindow16 (USER.230)
1911 HWND16 GetNextWindow16( HWND16 hwnd, WORD flag )
1913 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1914 return GetWindow16( hwnd, flag );
1917 /*******************************************************************
1918 * ShowOwnedPopups16 (USER.265)
1920 void ShowOwnedPopups16( HWND16 owner, BOOL16 fShow )
1922 ShowOwnedPopups32( owner, fShow );
1926 /*******************************************************************
1927 * ShowOwnedPopups32 (USER32.530)
1929 BOOL32 ShowOwnedPopups32( HWND32 owner, BOOL32 fShow )
1931 WND *pWnd = pWndDesktop->child;
1932 while (pWnd)
1934 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1935 (pWnd->dwStyle & WS_POPUP))
1936 ShowWindow32( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1937 pWnd = pWnd->next;
1939 return TRUE;
1943 /*******************************************************************
1944 * GetLastActivePopup16 (USER.287)
1946 HWND16 GetLastActivePopup16( HWND16 hwnd )
1948 return GetLastActivePopup32( hwnd );
1951 /*******************************************************************
1952 * GetLastActivePopup32 (USER32.255)
1954 HWND32 GetLastActivePopup32( HWND32 hwnd )
1956 WND *wndPtr;
1957 wndPtr = WIN_FindWndPtr(hwnd);
1958 if (wndPtr == NULL) return hwnd;
1959 return wndPtr->hwndLastActive;
1963 /*******************************************************************
1964 * WIN_BuildWinArray
1966 * Build an array of pointers to the children of a given window.
1967 * The array must be freed with HeapFree(SystemHeap). Return NULL
1968 * when no windows are found.
1970 WND **WIN_BuildWinArray( WND *wndPtr, UINT32 bwaFlags, UINT32* pTotal )
1972 WND **list, **ppWnd;
1973 WND *pWnd;
1974 UINT32 count, skipOwned, skipHidden;
1975 DWORD skipFlags;
1977 skipHidden = bwaFlags & BWA_SKIPHIDDEN;
1978 skipOwned = bwaFlags & BWA_SKIPOWNED;
1979 skipFlags = (bwaFlags & BWA_SKIPDISABLED) ? WS_DISABLED : 0;
1980 if( bwaFlags & BWA_SKIPICONIC ) skipFlags |= WS_MINIMIZE;
1982 /* First count the windows */
1984 if (!wndPtr) wndPtr = pWndDesktop;
1985 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next)
1987 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
1988 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE ) count++;
1991 if( count )
1993 /* Now build the list of all windows */
1995 if ((list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * (count + 1))))
1997 for (pWnd = wndPtr->child, ppWnd = list, count = 0; pWnd; pWnd = pWnd->next)
1999 if( (pWnd->dwStyle & skipFlags) || (skipOwned && pWnd->owner) ) continue;
2000 if( !skipHidden || pWnd->dwStyle & WS_VISIBLE )
2002 *ppWnd++ = pWnd;
2003 count++;
2006 *ppWnd = NULL;
2008 else count = 0;
2009 } else list = NULL;
2011 if( pTotal ) *pTotal = count;
2012 return list;
2016 /*******************************************************************
2017 * EnumWindows16 (USER.54)
2019 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
2021 WND **list, **ppWnd;
2023 /* We have to build a list of all windows first, to avoid */
2024 /* unpleasant side-effects, for instance if the callback */
2025 /* function changes the Z-order of the windows. */
2027 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2029 /* Now call the callback function for every window */
2031 for (ppWnd = list; *ppWnd; ppWnd++)
2033 /* Make sure that the window still exists */
2034 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2035 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
2037 HeapFree( SystemHeap, 0, list );
2038 return TRUE;
2042 /*******************************************************************
2043 * EnumWindows32 (USER32.192)
2045 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
2047 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
2051 /**********************************************************************
2052 * EnumTaskWindows16 (USER.225)
2054 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
2056 WND **list, **ppWnd;
2057 HQUEUE16 hQueue = GetTaskQueue( hTask );
2059 /* This function is the same as EnumWindows(), */
2060 /* except for an added check on the window queue. */
2062 if (!(list = WIN_BuildWinArray( pWndDesktop, 0, NULL ))) return FALSE;
2064 /* Now call the callback function for every window */
2066 for (ppWnd = list; *ppWnd; ppWnd++)
2068 /* Make sure that the window still exists */
2069 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2070 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
2071 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
2073 HeapFree( SystemHeap, 0, list );
2074 return TRUE;
2078 /**********************************************************************
2079 * EnumThreadWindows (USER32.189)
2081 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
2083 THDB *tdb = (THDB*)id;
2085 return (BOOL16)EnumTaskWindows16(tdb->teb.htask16, (WNDENUMPROC16)func, lParam);
2089 /**********************************************************************
2090 * WIN_EnumChildWindows
2092 * Helper function for EnumChildWindows().
2094 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
2095 LPARAM lParam )
2097 WND **childList;
2098 BOOL16 ret = FALSE;
2100 for ( ; *ppWnd; ppWnd++)
2102 /* Make sure that the window still exists */
2103 if (!IsWindow32((*ppWnd)->hwndSelf)) continue;
2104 /* Build children list first */
2105 if (!(childList = WIN_BuildWinArray( *ppWnd, BWA_SKIPOWNED, NULL )))
2106 return FALSE;
2107 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
2108 ret = WIN_EnumChildWindows( childList, func, lParam );
2109 HeapFree( SystemHeap, 0, childList );
2110 if (!ret) return FALSE;
2112 return TRUE;
2116 /**********************************************************************
2117 * EnumChildWindows16 (USER.55)
2119 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
2121 WND **list, *pParent;
2123 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
2124 if (!(list = WIN_BuildWinArray( pParent, BWA_SKIPOWNED, NULL ))) return FALSE;
2125 WIN_EnumChildWindows( list, func, lParam );
2126 HeapFree( SystemHeap, 0, list );
2127 return TRUE;
2131 /**********************************************************************
2132 * EnumChildWindows32 (USER32.177)
2134 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
2136 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
2137 lParam );
2141 /*******************************************************************
2142 * AnyPopup16 (USER.52)
2144 BOOL16 AnyPopup16(void)
2146 return AnyPopup32();
2150 /*******************************************************************
2151 * AnyPopup32 (USER32.3)
2153 BOOL32 AnyPopup32(void)
2155 WND *wndPtr;
2156 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2157 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2158 return FALSE;
2162 /*******************************************************************
2163 * FlashWindow16 (USER.105)
2165 BOOL16 FlashWindow16( HWND16 hWnd, BOOL16 bInvert )
2167 return FlashWindow32( hWnd, bInvert );
2171 /*******************************************************************
2172 * FlashWindow32 (USER32.201)
2174 BOOL32 FlashWindow32( HWND32 hWnd, BOOL32 bInvert )
2176 WND *wndPtr = WIN_FindWndPtr(hWnd);
2178 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2180 if (!wndPtr) return FALSE;
2182 if (wndPtr->dwStyle & WS_MINIMIZE)
2184 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2186 HDC32 hDC = GetDC32(hWnd);
2188 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2189 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2191 ReleaseDC32( hWnd, hDC );
2192 wndPtr->flags |= WIN_NCACTIVATED;
2194 else
2196 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2197 RDW_UPDATENOW | RDW_FRAME, 0 );
2198 wndPtr->flags &= ~WIN_NCACTIVATED;
2200 return TRUE;
2202 else
2204 WPARAM16 wparam;
2205 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2206 else wparam = (hWnd == GetActiveWindow32());
2208 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2209 return wparam;
2214 /*******************************************************************
2215 * SetSysModalWindow16 (USER.188)
2217 HWND16 SetSysModalWindow16( HWND16 hWnd )
2219 HWND32 hWndOldModal = hwndSysModal;
2220 hwndSysModal = hWnd;
2221 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2222 return hWndOldModal;
2226 /*******************************************************************
2227 * GetSysModalWindow16 (USER.52)
2229 HWND16 GetSysModalWindow16(void)
2231 return hwndSysModal;
2235 /*******************************************************************
2236 * DRAG_QueryUpdate
2238 * recursively find a child that contains spDragInfo->pt point
2239 * and send WM_QUERYDROPOBJECT
2241 BOOL16 DRAG_QueryUpdate( HWND32 hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2243 BOOL16 wParam,bResult = 0;
2244 POINT32 pt;
2245 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2246 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2247 RECT32 tempRect;
2249 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2251 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2253 GetWindowRect32(hQueryWnd,&tempRect);
2255 if( !PtInRect32(&tempRect,pt) ||
2256 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2257 return 0;
2259 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2261 tempRect = ptrQueryWnd->rectClient;
2262 if(ptrQueryWnd->dwStyle & WS_CHILD)
2263 MapWindowPoints32( ptrQueryWnd->parent->hwndSelf, 0,
2264 (LPPOINT32)&tempRect, 2 );
2266 if (PtInRect32( &tempRect, pt))
2268 wParam = 0;
2270 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2271 if( ptrWnd->dwStyle & WS_VISIBLE )
2273 GetWindowRect32( ptrWnd->hwndSelf, &tempRect );
2274 if (PtInRect32( &tempRect, pt )) break;
2277 if(ptrWnd)
2279 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2280 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2281 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2282 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2283 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2286 if(bResult) return bResult;
2288 else wParam = 1;
2290 else wParam = 1;
2292 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2294 ptrDragInfo->hScope = hQueryWnd;
2296 bResult = ( bNoSend )
2297 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2298 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2299 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2300 if( !bResult )
2301 CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2303 return bResult;
2307 /*******************************************************************
2308 * DragDetect (USER.465)
2310 BOOL16 DragDetect16( HWND16 hWnd, POINT16 pt )
2312 POINT32 pt32;
2313 CONV_POINT16TO32( &pt, &pt32 );
2314 return DragDetect32( hWnd, pt32 );
2317 /*******************************************************************
2318 * DragDetect32 (USER32.150)
2320 BOOL32 DragDetect32( HWND32 hWnd, POINT32 pt )
2322 MSG16 msg;
2323 RECT16 rect;
2325 rect.left = pt.x - wDragWidth;
2326 rect.right = pt.x + wDragWidth;
2328 rect.top = pt.y - wDragHeight;
2329 rect.bottom = pt.y + wDragHeight;
2331 SetCapture32(hWnd);
2333 while(1)
2335 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2337 if( msg.message == WM_LBUTTONUP )
2339 ReleaseCapture();
2340 return 0;
2342 if( msg.message == WM_MOUSEMOVE )
2344 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2346 ReleaseCapture();
2347 return 1;
2351 WaitMessage();
2353 return 0;
2356 /******************************************************************************
2357 * DragObject16 (USER.464)
2359 DWORD DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2360 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2362 MSG16 msg;
2363 LPDRAGINFO lpDragInfo;
2364 SEGPTR spDragInfo;
2365 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2366 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2367 WND *wndPtr = WIN_FindWndPtr(hWnd);
2368 HCURSOR16 hCurrentCursor = 0;
2369 HWND16 hCurrentWnd = 0;
2371 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2372 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2374 if( !lpDragInfo || !spDragInfo ) return 0L;
2376 hBummer = LoadCursor16(0, IDC_BUMMER);
2378 if( !hBummer || !wndPtr )
2380 GlobalFree16(hDragInfo);
2381 return 0L;
2384 if(hCursor)
2386 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2388 GlobalFree16(hDragInfo);
2389 return 0L;
2392 if( hDragCursor == hCursor ) hDragCursor = 0;
2393 else hCursor = hDragCursor;
2395 hOldCursor = SetCursor32(hDragCursor);
2398 lpDragInfo->hWnd = hWnd;
2399 lpDragInfo->hScope = 0;
2400 lpDragInfo->wFlags = wObj;
2401 lpDragInfo->hList = szList; /* near pointer! */
2402 lpDragInfo->hOfStruct = hOfStruct;
2403 lpDragInfo->l = 0L;
2405 SetCapture32(hWnd);
2406 ShowCursor32( TRUE );
2410 do{ WaitMessage(); }
2411 while( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) );
2413 *(lpDragInfo+1) = *lpDragInfo;
2415 lpDragInfo->pt = msg.pt;
2417 /* update DRAGINFO struct */
2418 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2420 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2421 hCurrentCursor = hCursor;
2422 else
2424 hCurrentCursor = hBummer;
2425 lpDragInfo->hScope = 0;
2427 if( hCurrentCursor )
2428 SetCursor32(hCurrentCursor);
2430 /* send WM_DRAGLOOP */
2431 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2432 (LPARAM) spDragInfo );
2433 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2434 if( hCurrentWnd != lpDragInfo->hScope )
2436 if( hCurrentWnd )
2437 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2438 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2439 HIWORD(spDragInfo)) );
2440 hCurrentWnd = lpDragInfo->hScope;
2441 if( hCurrentWnd )
2442 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2444 else
2445 if( hCurrentWnd )
2446 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2448 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2450 ReleaseCapture();
2451 ShowCursor32( FALSE );
2453 if( hCursor )
2455 SetCursor32( hOldCursor );
2456 if (hDragCursor) DestroyCursor32( hDragCursor );
2459 if( hCurrentCursor != hBummer )
2460 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2461 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2462 else
2463 msg.lParam = 0;
2464 GlobalFree16(hDragInfo);
2466 return (DWORD)(msg.lParam);