Release 961222
[wine/multimedia.git] / windows / win.c
blobaae3d6d5392c4f17ebb9c4a8793ca6ed5d514218
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 "stddebug.h"
33 /* #define DEBUG_WIN */
34 /* #define DEBUG_MENU */
35 #include "debug.h"
37 /* Desktop window */
38 static WND *pWndDesktop = NULL;
40 static HWND hwndSysModal = 0;
42 static WORD wDragWidth = 4;
43 static WORD wDragHeight= 3;
45 extern HCURSOR16 CURSORICON_IconToCursor(HICON16, BOOL32);
46 extern HWND32 CARET_GetHwnd(void);
47 extern BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd);
48 extern void WINPOS_CheckActive(HWND32);
50 /***********************************************************************
51 * WIN_FindWndPtr
53 * Return a pointer to the WND structure corresponding to a HWND.
55 WND * WIN_FindWndPtr( HWND32 hwnd )
57 WND * ptr;
59 if (!hwnd || HIWORD(hwnd)) return NULL;
60 ptr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
61 if (ptr->dwMagic != WND_MAGIC) return NULL;
62 if (ptr->hwndSelf != hwnd)
64 fprintf( stderr, "Can't happen: hwnd %04x self pointer is %04x\n",
65 hwnd, ptr->hwndSelf );
66 return NULL;
68 return ptr;
72 /***********************************************************************
73 * WIN_DumpWindow
75 * Dump the content of a window structure to stderr.
77 void WIN_DumpWindow( HWND32 hwnd )
79 WND *ptr;
80 char className[80];
81 int i;
83 if (!(ptr = WIN_FindWndPtr( hwnd )))
85 fprintf( stderr, "%04x is not a window handle\n", hwnd );
86 return;
89 if (!GetClassName32A( hwnd, className, sizeof(className ) ))
90 strcpy( className, "#NULL#" );
92 fprintf( stderr, "Window %04x (%p):\n", hwnd, ptr );
93 fprintf( stderr,
94 "next=%p child=%p parent=%p owner=%p class=%p '%s'\n"
95 "inst=%04x taskQ=%04x updRgn=%04x active=%04x dce=%p idmenu=%04x\n"
96 "style=%08lx exstyle=%08lx wndproc=%08x text='%s'\n"
97 "client=%d,%d-%d,%d window=%d,%d-%d,%d iconpos=%d,%d maxpos=%d,%d\n"
98 "sysmenu=%04x flags=%04x props=%p vscroll=%p hscroll=%p\n",
99 ptr->next, ptr->child, ptr->parent, ptr->owner,
100 ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
101 ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
102 ptr->dwStyle, ptr->dwExStyle, (UINT32)ptr->winproc,
103 ptr->text ? ptr->text : "",
104 ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
105 ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
106 ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->ptIconPos.x,
107 ptr->ptIconPos.y, ptr->ptMaxPos.x, ptr->ptMaxPos.y, ptr->hSysMenu,
108 ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
110 if (ptr->class->cbWndExtra)
112 fprintf( stderr, "extra bytes:" );
113 for (i = 0; i < ptr->class->cbWndExtra; i++)
114 fprintf( stderr, " %02x", *((BYTE*)ptr->wExtra+i) );
115 fprintf( stderr, "\n" );
117 fprintf( stderr, "\n" );
121 /***********************************************************************
122 * WIN_WalkWindows
124 * Walk the windows tree and print each window on stderr.
126 void WIN_WalkWindows( HWND32 hwnd, int indent )
128 WND *ptr;
129 char className[80];
131 ptr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop;
132 if (!ptr)
134 fprintf( stderr, "*** Invalid window handle %04x\n", hwnd );
135 return;
138 if (!indent) /* first time around */
139 fprintf( stderr, "%-16.16s %-8.8s %-6.6s %-17.17s %-8.8s %s\n",
140 "hwnd", " wndPtr", "queue", "Class Name", " Style", " WndProc");
142 while (ptr)
144 fprintf(stderr, "%*s%04x%*s", indent, "", ptr->hwndSelf, 13-indent,"");
146 GlobalGetAtomName16(ptr->class->atomName,className,sizeof(className));
148 fprintf( stderr, "%08lx %-6.4x %-17.17s %08x %08x\n",
149 (DWORD)ptr, ptr->hmemTaskQ, className,
150 (UINT32)ptr->dwStyle, (UINT32)ptr->winproc );
152 if (ptr->child) WIN_WalkWindows( ptr->child->hwndSelf, indent+1 );
153 ptr = ptr->next;
158 /***********************************************************************
159 * WIN_GetXWindow
161 * Return the X window associated to a window.
163 Window WIN_GetXWindow( HWND32 hwnd )
165 WND *wndPtr = WIN_FindWndPtr( hwnd );
166 while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent;
167 return wndPtr ? wndPtr->window : 0;
171 /***********************************************************************
172 * WIN_UnlinkWindow
174 * Remove a window from the siblings linked list.
176 BOOL32 WIN_UnlinkWindow( HWND32 hwnd )
178 WND *wndPtr, **ppWnd;
180 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
181 ppWnd = &wndPtr->parent->child;
182 while (*ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
183 *ppWnd = wndPtr->next;
184 return TRUE;
188 /***********************************************************************
189 * WIN_LinkWindow
191 * Insert a window into the siblings linked list.
192 * The window is inserted after the specified window, which can also
193 * be specified as HWND_TOP or HWND_BOTTOM.
195 BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter )
197 WND *wndPtr, **ppWnd;
199 if (!(wndPtr = WIN_FindWndPtr( hwnd )) || !wndPtr->parent) return FALSE;
201 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
203 ppWnd = &wndPtr->parent->child; /* Point to first sibling hwnd */
204 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
205 while (*ppWnd) ppWnd = &(*ppWnd)->next;
207 else /* Normal case */
209 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
210 if (!afterPtr) return FALSE;
211 ppWnd = &afterPtr->next;
213 wndPtr->next = *ppWnd;
214 *ppWnd = wndPtr;
215 return TRUE;
219 /***********************************************************************
220 * WIN_FindWinToRepaint
222 * Find a window that needs repaint.
224 HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue )
226 HWND hwndRet;
227 WND *pWnd = pWndDesktop;
229 /* Note: the desktop window never gets WM_PAINT messages
230 * The real reason why is because Windows DesktopWndProc
231 * does ValidateRgn inside WM_ERASEBKGND handler.
234 pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
236 for ( ; pWnd ; pWnd = pWnd->next )
238 if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
240 dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
241 pWnd->hwndSelf );
242 continue;
244 if ((pWnd->hmemTaskQ == hQueue) &&
245 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
247 if (pWnd->child )
248 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
249 return hwndRet;
252 if (!pWnd) return 0;
254 hwndRet = pWnd->hwndSelf;
256 /* look among siblings if we got a transparent window */
257 while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
258 !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
260 pWnd = pWnd->next;
262 if (pWnd) hwndRet = pWnd->hwndSelf;
263 dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
264 return hwndRet;
268 /***********************************************************************
269 * WIN_SendParentNotify
271 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
272 * the window has the WS_EX_NOPARENTNOTIFY style.
274 void WIN_SendParentNotify(HWND32 hwnd, WORD event, WORD idChild, LPARAM lValue)
276 LPPOINT16 lppt = (LPPOINT16)&lValue;
277 WND *wndPtr = WIN_FindWndPtr( hwnd );
278 BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
280 /* if lValue contains cursor coordinates they have to be
281 * mapped to the client area of parent window */
283 if (bMouse) MapWindowPoints16( 0, hwnd, lppt, 1 );
285 while (wndPtr)
287 if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
288 !(wndPtr->dwStyle & WS_CHILD)) break;
290 if (bMouse)
292 lppt->x += wndPtr->rectClient.left;
293 lppt->y += wndPtr->rectClient.top;
296 wndPtr = wndPtr->parent;
297 SendMessage32A( wndPtr->hwndSelf, WM_PARENTNOTIFY,
298 MAKEWPARAM( event, idChild ), lValue );
303 /***********************************************************************
304 * WIN_DestroyWindow
306 * Destroy storage associated to a window. "Internals" p.358
308 static void WIN_DestroyWindow( WND* wndPtr )
310 HWND hwnd = wndPtr->hwndSelf;
311 WND* pWnd,*pNext;
313 dprintf_win( stddeb, "WIN_DestroyWindow: %04x\n", wndPtr->hwndSelf );
315 #ifdef CONFIG_IPC
316 if (main_block)
317 DDE_DestroyWindow(wndPtr->hwndSelf);
318 #endif /* CONFIG_IPC */
320 /* free child windows */
322 pNext = wndPtr->child;
323 while( (pWnd = pNext) )
325 pNext = pWnd->next;
326 WIN_DestroyWindow( pWnd );
329 SendMessage32A( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
331 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
333 WINPOS_CheckActive( 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) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
364 if (wndPtr->hSysMenu) DestroyMenu( 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 );
370 wndPtr->class->cWindows--;
371 wndPtr->class = NULL;
373 USER_HEAP_FREE( hwnd );
376 /***********************************************************************
377 * WIN_ResetQueueWindows
379 void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
381 WND* next;
383 while (wnd)
385 next = wnd->next;
386 if (wnd->hmemTaskQ == hQueue)
387 if( hNew ) wnd->hmemTaskQ = hNew;
388 else DestroyWindow( wnd->hwndSelf );
389 else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
390 wnd = next;
394 /***********************************************************************
395 * WIN_CreateDesktopWindow
397 * Create the desktop window.
399 BOOL32 WIN_CreateDesktopWindow(void)
401 CLASS *class;
402 HWND hwndDesktop;
404 dprintf_win(stddeb,"Creating desktop window\n");
406 if (!(class = CLASS_FindClassByAtom( DESKTOP_CLASS_ATOM, 0 )))
407 return FALSE;
409 hwndDesktop = USER_HEAP_ALLOC( sizeof(WND)+class->cbWndExtra );
410 if (!hwndDesktop) return FALSE;
411 pWndDesktop = (WND *) USER_HEAP_LIN_ADDR( hwndDesktop );
413 pWndDesktop->next = NULL;
414 pWndDesktop->child = NULL;
415 pWndDesktop->parent = NULL;
416 pWndDesktop->owner = NULL;
417 pWndDesktop->class = class;
418 pWndDesktop->winproc = NULL;
419 pWndDesktop->dwMagic = WND_MAGIC;
420 pWndDesktop->hwndSelf = hwndDesktop;
421 pWndDesktop->hInstance = 0;
422 pWndDesktop->rectWindow.left = 0;
423 pWndDesktop->rectWindow.top = 0;
424 pWndDesktop->rectWindow.right = SYSMETRICS_CXSCREEN;
425 pWndDesktop->rectWindow.bottom = SYSMETRICS_CYSCREEN;
426 pWndDesktop->rectClient = pWndDesktop->rectWindow;
427 pWndDesktop->rectNormal = pWndDesktop->rectWindow;
428 pWndDesktop->ptIconPos.x = -1;
429 pWndDesktop->ptIconPos.y = -1;
430 pWndDesktop->ptMaxPos.x = -1;
431 pWndDesktop->ptMaxPos.y = -1;
432 pWndDesktop->text = NULL;
433 pWndDesktop->hmemTaskQ = 0; /* Desktop does not belong to a task */
434 pWndDesktop->hrgnUpdate = 0;
435 pWndDesktop->hwndLastActive = hwndDesktop;
436 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
437 WS_CLIPSIBLINGS;
438 pWndDesktop->dwExStyle = 0;
439 pWndDesktop->dce = NULL;
440 pWndDesktop->pVScroll = NULL;
441 pWndDesktop->pHScroll = NULL;
442 pWndDesktop->pProp = NULL;
443 pWndDesktop->wIDmenu = 0;
444 pWndDesktop->flags = 0;
445 pWndDesktop->window = rootWindow;
446 pWndDesktop->hSysMenu = 0;
447 pWndDesktop->userdata = 0;
449 WINPROC_SetProc( &pWndDesktop->winproc, (WNDPROC16)class->winproc, 0 );
450 EVENT_RegisterWindow( pWndDesktop );
451 SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
452 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
453 return TRUE;
457 /***********************************************************************
458 * WIN_CreateWindowEx
460 * Implementation of CreateWindowEx().
462 static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
463 BOOL unicode )
465 CLASS *classPtr;
466 WND *wndPtr;
467 HWND16 hwnd, hwndLinkAfter;
468 POINT16 maxSize, maxPos, minTrack, maxTrack;
469 LRESULT wmcreate;
471 dprintf_win( stddeb, "CreateWindowEx: " );
472 if (HIWORD(cs->lpszName)) dprintf_win( stddeb, "'%s' ", cs->lpszName );
473 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszName) );
474 if (HIWORD(cs->lpszClass)) dprintf_win( stddeb, "'%s' ", cs->lpszClass );
475 else dprintf_win( stddeb, "#%04x ", LOWORD(cs->lpszClass) );
477 dprintf_win( stddeb, "%08lx %08lx %d,%d %dx%d %04x %04x %04x %p\n",
478 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
479 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams);
481 /* Find the parent window */
483 if (cs->hwndParent)
485 /* Make sure parent is valid */
486 if (!IsWindow( cs->hwndParent ))
488 fprintf( stderr, "CreateWindowEx: bad parent %04x\n", cs->hwndParent );
489 return 0;
492 else if (cs->style & WS_CHILD)
494 fprintf( stderr, "CreateWindowEx: no parent for child window\n" );
495 return 0; /* WS_CHILD needs a parent */
498 /* Find the window class */
500 if (!(classPtr = CLASS_FindClassByAtom( classAtom,
501 GetExePtr(cs->hInstance) )))
503 char buffer[256];
504 GlobalGetAtomName32A( classAtom, buffer, sizeof(buffer) );
505 fprintf( stderr, "CreateWindowEx: bad class '%s'\n", buffer );
506 return 0;
509 /* Fix the coordinates */
511 if (cs->x == CW_USEDEFAULT32) cs->x = cs->y = 0;
512 if (cs->cx == CW_USEDEFAULT32)
514 /* if (!(cs->style & (WS_CHILD | WS_POPUP))) cs->cx = cs->cy = 0;
515 else */
517 cs->cx = 600;
518 cs->cy = 400;
522 /* Create the window structure */
524 if (!(hwnd = USER_HEAP_ALLOC( sizeof(*wndPtr) + classPtr->cbWndExtra
525 - sizeof(wndPtr->wExtra) )))
527 dprintf_win( stddeb, "CreateWindowEx: out of memory\n" );
528 return 0;
531 /* Fill the window structure */
533 wndPtr = (WND *) USER_HEAP_LIN_ADDR( hwnd );
534 wndPtr->next = NULL;
535 wndPtr->child = NULL;
537 if (cs->style & WS_CHILD)
539 wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
540 wndPtr->owner = NULL;
542 else
544 wndPtr->parent = pWndDesktop;
545 if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
546 wndPtr->owner = NULL;
547 else
548 wndPtr->owner = WIN_FindWndPtr(WIN_GetTopParent(cs->hwndParent));
551 wndPtr->window = 0;
552 wndPtr->class = classPtr;
553 wndPtr->winproc = NULL;
554 wndPtr->dwMagic = WND_MAGIC;
555 wndPtr->hwndSelf = hwnd;
556 wndPtr->hInstance = cs->hInstance;
557 wndPtr->ptIconPos.x = -1;
558 wndPtr->ptIconPos.y = -1;
559 wndPtr->ptMaxPos.x = -1;
560 wndPtr->ptMaxPos.y = -1;
561 wndPtr->text = NULL;
562 wndPtr->hmemTaskQ = GetTaskQueue(0);
563 wndPtr->hrgnUpdate = 0;
564 wndPtr->hwndLastActive = hwnd;
565 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
566 wndPtr->dwExStyle = cs->dwExStyle;
567 wndPtr->wIDmenu = 0;
568 wndPtr->flags = 0;
569 wndPtr->pVScroll = NULL;
570 wndPtr->pHScroll = NULL;
571 wndPtr->pProp = NULL;
572 wndPtr->hSysMenu = MENU_GetDefSysMenu();
573 wndPtr->userdata = 0;
575 if (classPtr->cbWndExtra) memset( wndPtr->wExtra, 0, classPtr->cbWndExtra);
577 /* Call the WH_CBT hook */
579 hwndLinkAfter = (cs->style & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
581 if (HOOK_IsHooked( WH_CBT ))
583 CBT_CREATEWND32A cbtc;
585 cbtc.lpcs = cs;
586 cbtc.hwndInsertAfter = hwndLinkAfter;
587 wmcreate = !HOOK_CallHooks32A( WH_CBT, HCBT_CREATEWND, hwnd,
588 (LPARAM)&cbtc );
589 if (!wmcreate)
591 dprintf_win(stddeb, "CreateWindowEx: CBT-hook returned 0\n");
592 USER_HEAP_FREE( hwnd );
593 return 0;
597 /* Set the window procedure */
599 classPtr->cWindows++;
600 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)classPtr->winproc, 0 );
602 /* Correct the window style */
604 if (!(cs->style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
606 wndPtr->dwStyle |= WS_CAPTION | WS_CLIPSIBLINGS;
607 wndPtr->flags |= WIN_NEED_SIZE;
609 if (cs->dwExStyle & WS_EX_DLGMODALFRAME) wndPtr->dwStyle &= ~WS_THICKFRAME;
611 /* Get class or window DC if needed */
613 if (classPtr->style & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
614 else if (classPtr->style & CS_CLASSDC) wndPtr->dce = classPtr->dce;
615 else wndPtr->dce = NULL;
617 /* Insert the window in the linked list */
619 WIN_LinkWindow( hwnd, hwndLinkAfter );
621 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
623 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
625 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
626 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
627 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
628 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
629 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
631 if (cs->cx <= 0) cs->cx = 1;
632 if (cs->cy <= 0) cs->cy = 1;
634 wndPtr->rectWindow.left = cs->x;
635 wndPtr->rectWindow.top = cs->y;
636 wndPtr->rectWindow.right = cs->x + cs->cx;
637 wndPtr->rectWindow.bottom = cs->y + cs->cy;
638 wndPtr->rectClient = wndPtr->rectWindow;
639 wndPtr->rectNormal = wndPtr->rectWindow;
641 /* Create the X window (only for top-level windows, and then only */
642 /* when there's no desktop window) */
644 if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display)))
646 XSetWindowAttributes win_attr;
648 if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) ||
649 (cs->dwExStyle & WS_EX_DLGMODALFRAME)))
651 win_attr.event_mask = ExposureMask | KeyPressMask |
652 KeyReleaseMask | PointerMotionMask |
653 ButtonPressMask | ButtonReleaseMask |
654 FocusChangeMask | StructureNotifyMask;
655 win_attr.override_redirect = FALSE;
656 wndPtr->flags |= WIN_MANAGED;
658 else
660 win_attr.event_mask = ExposureMask | KeyPressMask |
661 KeyReleaseMask | PointerMotionMask |
662 ButtonPressMask | ButtonReleaseMask |
663 FocusChangeMask | StructureNotifyMask;
664 win_attr.override_redirect = TRUE;
666 win_attr.colormap = COLOR_GetColormap();
667 win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful;
668 win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0);
669 win_attr.cursor = CURSORICON_XCursor;
670 wndPtr->window = XCreateWindow( display, rootWindow, cs->x, cs->y,
671 cs->cx, cs->cy, 0, CopyFromParent,
672 InputOutput, CopyFromParent,
673 CWEventMask | CWOverrideRedirect |
674 CWColormap | CWCursor | CWSaveUnder |
675 CWBackingStore, &win_attr );
677 if ((wndPtr->flags & WIN_MANAGED) &&
678 (cs->dwExStyle & WS_EX_DLGMODALFRAME))
680 XSizeHints* size_hints = XAllocSizeHints();
682 if (size_hints)
684 size_hints->min_width = size_hints->max_width = cs->cx;
685 size_hints->min_height = size_hints->max_height = cs->cy;
686 size_hints->flags = (PSize | PMinSize | PMaxSize);
687 XSetWMSizeHints( display, wndPtr->window, size_hints,
688 XA_WM_NORMAL_HINTS );
689 XFree(size_hints);
693 if (cs->hwndParent) /* Get window owner */
695 Window win = WIN_GetXWindow( cs->hwndParent );
696 if (win) XSetTransientForHint( display, wndPtr->window, win );
698 EVENT_RegisterWindow( wndPtr );
701 /* Set the window menu */
703 if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
705 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
706 else
708 #if 0 /* FIXME: should check if classPtr->menuNameW can be used as is */
709 if (classPtr->menuNameA)
710 cs->hMenu = HIWORD(classPtr->menuNameA) ?
711 LoadMenu(cs->hInstance,SEGPTR_GET(classPtr->menuNameA)):
712 LoadMenu(cs->hInstance,(SEGPTR)classPtr->menuNameA);
713 #else
714 SEGPTR menuName = (SEGPTR)GetClassLong16( hwnd, GCL_MENUNAME );
715 if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
716 #endif
718 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
720 else wndPtr->wIDmenu = (UINT)cs->hMenu;
722 /* Send the WM_CREATE message
723 * Perhaps we shouldn't allow width/height changes as well.
724 * See p327 in "Internals".
727 maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
728 if (unicode)
730 if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
731 else
733 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
734 NULL, NULL, 0, &wndPtr->rectClient );
735 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
736 maxPos.y - wndPtr->rectWindow.top);
737 wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
740 else
742 if (!SendMessage32A( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
743 else
745 WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
746 NULL, NULL, 0, &wndPtr->rectClient );
747 OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
748 maxPos.y - wndPtr->rectWindow.top);
749 wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
753 if (wmcreate == -1)
755 /* Abort window creation */
756 dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
757 WIN_UnlinkWindow( hwnd );
758 WIN_DestroyWindow( wndPtr );
759 return 0;
762 /* Send the size messages */
764 if (!(wndPtr->flags & WIN_NEED_SIZE))
766 /* send it anyway */
767 SendMessage16( hwnd, WM_SIZE, SIZE_RESTORED,
768 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
769 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
770 SendMessage16( hwnd, WM_MOVE, 0, MAKELONG( wndPtr->rectClient.left,
771 wndPtr->rectClient.top ));
774 WIN_SendParentNotify( hwnd, WM_CREATE, wndPtr->wIDmenu, (LPARAM)hwnd );
775 if (!IsWindow(hwnd)) return 0;
777 /* Show the window, maximizing or minimizing if needed */
779 if (wndPtr->dwStyle & WS_MINIMIZE)
781 /* MinMaximize(hwnd, SW_SHOWMINNOACTIVE, 1) in "Internals" */
783 wndPtr->dwStyle &= ~WS_MAXIMIZE;
784 WINPOS_FindIconPos( hwnd );
785 SetWindowPos( hwnd, 0, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
786 SYSMETRICS_CXICON, SYSMETRICS_CYICON,
787 SWP_FRAMECHANGED | ((GetActiveWindow())? SWP_NOACTIVATE : 0) );
789 else if (wndPtr->dwStyle & WS_MAXIMIZE)
791 /* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
793 NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
794 SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
795 ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
798 if (cs->style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
800 /* Call WH_SHELL hook */
802 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
803 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWCREATED, hwnd, 0 );
805 dprintf_win(stddeb, "CreateWindowEx: returning %04x\n", hwnd);
806 return hwnd;
810 /***********************************************************************
811 * CreateWindow16 (USER.41)
813 HWND16 CreateWindow16( LPCSTR className, LPCSTR windowName,
814 DWORD style, INT16 x, INT16 y, INT16 width,
815 INT16 height, HWND16 parent, HMENU16 menu,
816 HINSTANCE16 instance, LPVOID data )
818 return CreateWindowEx16( 0, className, windowName, style,
819 x, y, width, height, parent, menu, instance, data );
823 /***********************************************************************
824 * CreateWindowEx16 (USER.452)
826 HWND16 CreateWindowEx16( DWORD exStyle, LPCSTR className, LPCSTR windowName,
827 DWORD style, INT16 x, INT16 y, INT16 width,
828 INT16 height, HWND16 parent, HMENU16 menu,
829 HINSTANCE16 instance, LPVOID data )
831 ATOM classAtom;
832 CREATESTRUCT32A cs;
834 /* Find the class atom */
836 if (!(classAtom = GlobalFindAtom32A( className )))
838 fprintf( stderr, "CreateWindowEx16: bad class name " );
839 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
840 else fprintf( stderr, "'%s'\n", className );
841 return 0;
844 /* Fix the coordinates */
846 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)x;
847 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)y;
848 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)width;
849 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT32 : (INT32)height;
851 /* Create the window */
853 cs.lpCreateParams = data;
854 cs.hInstance = (HINSTANCE32)instance;
855 cs.hMenu = (HMENU32)menu;
856 cs.hwndParent = (HWND32)parent;
857 cs.style = style;
858 cs.lpszName = windowName;
859 cs.lpszClass = className;
860 cs.dwExStyle = exStyle;
861 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
865 /***********************************************************************
866 * CreateWindowEx32A (USER32.82)
868 HWND32 CreateWindowEx32A( DWORD exStyle, LPCSTR className, LPCSTR windowName,
869 DWORD style, INT32 x, INT32 y, INT32 width,
870 INT32 height, HWND32 parent, HMENU32 menu,
871 HINSTANCE32 instance, LPVOID data )
873 ATOM classAtom;
874 CREATESTRUCT32A cs;
876 /* Find the class atom */
878 if (!(classAtom = GlobalFindAtom32A( className )))
880 fprintf( stderr, "CreateWindowEx32A: bad class name " );
881 if (!HIWORD(className)) fprintf( stderr, "%04x\n", LOWORD(className) );
882 else fprintf( stderr, "'%s'\n", className );
883 return 0;
886 /* Create the window */
888 cs.lpCreateParams = data;
889 cs.hInstance = instance;
890 cs.hMenu = menu;
891 cs.hwndParent = parent;
892 cs.x = x;
893 cs.y = y;
894 cs.cx = width;
895 cs.cy = height;
896 cs.style = style;
897 cs.lpszName = windowName;
898 cs.lpszClass = className;
899 cs.dwExStyle = exStyle;
900 return WIN_CreateWindowEx( &cs, classAtom, FALSE );
904 /***********************************************************************
905 * CreateWindowEx32W (USER32.83)
907 HWND32 CreateWindowEx32W( DWORD exStyle, LPCWSTR className, LPCWSTR windowName,
908 DWORD style, INT32 x, INT32 y, INT32 width,
909 INT32 height, HWND32 parent, HMENU32 menu,
910 HINSTANCE32 instance, LPVOID data )
912 ATOM classAtom;
913 CREATESTRUCT32W cs;
915 /* Find the class atom */
917 if (!(classAtom = GlobalFindAtom32W( className )))
919 if (HIWORD(className))
921 LPSTR cn = HEAP_strdupWtoA( GetProcessHeap(), 0, className );
922 fprintf( stderr, "CreateWindowEx32W: bad class name '%s'\n",cn);
923 HeapFree( GetProcessHeap(), 0, cn );
925 else
926 fprintf( stderr, "CreateWindowEx32W: bad class name %p\n", className );
927 return 0;
930 /* Create the window */
932 cs.lpCreateParams = data;
933 cs.hInstance = instance;
934 cs.hMenu = menu;
935 cs.hwndParent = parent;
936 cs.x = x;
937 cs.y = y;
938 cs.cx = width;
939 cs.cy = height;
940 cs.style = style;
941 cs.lpszName = windowName;
942 cs.lpszClass = className;
943 cs.dwExStyle = exStyle;
944 /* Note: we rely on the fact that CREATESTRUCT32A and */
945 /* CREATESTRUCT32W have the same layout. */
946 return WIN_CreateWindowEx( (CREATESTRUCT32A *)&cs, classAtom, TRUE );
950 /***********************************************************************
951 * WIN_CheckFocus
953 static void WIN_CheckFocus( WND* pWnd )
955 if( GetFocus16() == pWnd->hwndSelf )
956 SetFocus16( (pWnd->dwStyle & WS_CHILD) ? pWnd->parent->hwndSelf : 0 );
959 /***********************************************************************
960 * WIN_SendDestroyMsg
962 static void WIN_SendDestroyMsg( WND* pWnd )
964 WND* pChild;
966 WIN_CheckFocus(pWnd);
968 if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
969 if( !pWnd->window ) CLIPBOARD_DisOwn( pWnd );
971 SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0);
973 if( !IsWindow(pWnd->hwndSelf) )
975 dprintf_win(stddeb,"\tdestroyed itself while in WM_DESTROY!\n");
976 return;
979 pChild = pWnd->child;
980 while( pChild )
982 WIN_SendDestroyMsg( pChild );
983 pChild = pChild->next;
985 WIN_CheckFocus(pWnd);
989 /***********************************************************************
990 * DestroyWindow (USER.53)
992 BOOL DestroyWindow( HWND hwnd )
994 WND * wndPtr;
996 dprintf_win(stddeb, "DestroyWindow(%04x)\n", hwnd);
998 /* Initialization */
1000 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1001 if (wndPtr == pWndDesktop) return FALSE; /* Can't destroy desktop */
1003 /* Call hooks */
1005 if( HOOK_CallHooks16( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
1006 return FALSE;
1008 if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
1010 HOOK_CallHooks16( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
1011 /* FIXME: clean up palette - see "Internals" p.352 */
1014 if( !QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ) )
1015 WIN_SendParentNotify( hwnd, WM_DESTROY, wndPtr->wIDmenu, (LPARAM)hwnd );
1016 if( !IsWindow(hwnd) ) return TRUE;
1018 if( wndPtr->window ) CLIPBOARD_DisOwn( wndPtr ); /* before window is unmapped */
1020 /* Hide the window */
1022 if (wndPtr->dwStyle & WS_VISIBLE)
1024 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_HIDEWINDOW |
1025 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE |
1026 ((QUEUE_IsDoomedQueue(wndPtr->hmemTaskQ))?SWP_DEFERERASE:0) );
1027 if( !IsWindow(hwnd) ) return TRUE;
1030 /* Recursively destroy owned windows */
1032 if( !(wndPtr->dwStyle & WS_CHILD) )
1034 for (;;)
1036 WND *siblingPtr = wndPtr->parent->child; /* First sibling */
1037 while (siblingPtr)
1039 if (siblingPtr->owner == wndPtr)
1040 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1041 break;
1042 else
1043 siblingPtr->owner = NULL;
1044 siblingPtr = siblingPtr->next;
1046 if (siblingPtr) DestroyWindow( siblingPtr->hwndSelf );
1047 else break;
1050 WINPOS_ActivateOtherWindow(wndPtr);
1052 if( wndPtr->owner &&
1053 wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
1054 wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
1057 /* Send destroy messages */
1059 WIN_SendDestroyMsg( wndPtr );
1060 if( !IsWindow(hwnd) ) return TRUE;
1062 /* Unlink now so we won't bother with the children later on */
1064 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1066 /* Destroy the window storage */
1068 WIN_DestroyWindow( wndPtr );
1069 return TRUE;
1073 /***********************************************************************
1074 * CloseWindow (USER.43)
1076 BOOL CloseWindow(HWND hWnd)
1078 WND * wndPtr = WIN_FindWndPtr(hWnd);
1079 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return TRUE;
1080 ShowWindow(hWnd, SW_MINIMIZE);
1081 return TRUE;
1085 /***********************************************************************
1086 * OpenIcon (USER.44)
1088 BOOL OpenIcon(HWND hWnd)
1090 if (!IsIconic(hWnd)) return FALSE;
1091 ShowWindow(hWnd, SW_SHOWNORMAL);
1092 return(TRUE);
1096 /***********************************************************************
1097 * WIN_FindWindow
1099 * Implementation of FindWindow() and FindWindowEx().
1101 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
1102 LPCSTR title )
1104 WND *pWnd;
1105 CLASS *pClass = NULL;
1107 if (child)
1109 if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
1110 if (parent)
1112 if (!pWnd->parent || (pWnd->parent->hwndSelf != parent)) return 0;
1114 else if (pWnd->parent != pWndDesktop) return 0;
1115 pWnd = pWnd->next;
1117 else
1119 if (!(pWnd = parent ? WIN_FindWndPtr(parent) : pWndDesktop)) return 0;
1120 pWnd = pWnd->child;
1122 if (!pWnd) return 0;
1124 /* For a child window, all siblings will have the same hInstance, */
1125 /* so we can look for the class once and for all. */
1127 if (className && (pWnd->dwStyle & WS_CHILD))
1129 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance )))
1130 return 0;
1133 for ( ; pWnd; pWnd = pWnd->next)
1135 if (className && !(pWnd->dwStyle & WS_CHILD))
1137 if (!(pClass = CLASS_FindClassByAtom( className, pWnd->hInstance)))
1138 continue; /* Skip this window */
1140 if (pClass && (pWnd->class != pClass))
1141 continue; /* Not the right class */
1143 /* Now check the title */
1145 if (!title) return pWnd->hwndSelf;
1146 if (pWnd->text && !strcmp( pWnd->text, title )) return pWnd->hwndSelf;
1148 return 0;
1153 /***********************************************************************
1154 * FindWindow16 (USER.50)
1156 HWND16 FindWindow16( SEGPTR className, LPCSTR title )
1158 return FindWindowEx16( 0, 0, className, title );
1162 /***********************************************************************
1163 * FindWindowEx16 (USER.427)
1165 HWND16 FindWindowEx16( HWND16 parent, HWND16 child,
1166 SEGPTR className, LPCSTR title )
1168 ATOM atom = 0;
1170 if (className)
1172 /* If the atom doesn't exist, then no class */
1173 /* with this name exists either. */
1174 if (!(atom = GlobalFindAtom16( className ))) return 0;
1176 return WIN_FindWindow( parent, child, atom, title );
1180 /***********************************************************************
1181 * FindWindow32A (USER32.197)
1183 HWND32 FindWindow32A( LPCSTR className, LPCSTR title )
1185 return FindWindowEx32A( 0, 0, className, title );
1189 /***********************************************************************
1190 * FindWindowEx32A (USER32.198)
1192 HWND32 FindWindowEx32A( HWND32 parent, HWND32 child,
1193 LPCSTR className, LPCSTR title )
1195 ATOM atom = 0;
1197 if (className)
1199 /* If the atom doesn't exist, then no class */
1200 /* with this name exists either. */
1201 if (!(atom = GlobalFindAtom32A( className ))) return 0;
1203 return WIN_FindWindow( 0, 0, atom, title );
1207 /***********************************************************************
1208 * FindWindowEx32W (USER32.199)
1210 HWND32 FindWindowEx32W( HWND32 parent, HWND32 child,
1211 LPCWSTR className, LPCWSTR title )
1213 ATOM atom = 0;
1214 char *buffer;
1215 HWND hwnd;
1217 if (className)
1219 /* If the atom doesn't exist, then no class */
1220 /* with this name exists either. */
1221 if (!(atom = GlobalFindAtom32W( className ))) return 0;
1223 buffer = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
1224 hwnd = WIN_FindWindow( 0, 0, atom, buffer );
1225 HeapFree( GetProcessHeap(), 0, buffer );
1226 return hwnd;
1230 /***********************************************************************
1231 * FindWindow32W (USER32.200)
1233 HWND32 FindWindow32W( LPCWSTR className, LPCWSTR title )
1235 return FindWindowEx32W( 0, 0, className, title );
1239 /**********************************************************************
1240 * WIN_GetDesktop
1242 WND *WIN_GetDesktop(void)
1244 return pWndDesktop;
1248 /**********************************************************************
1249 * GetDesktopWindow16 (USER.286)
1251 HWND16 GetDesktopWindow16(void)
1253 return (HWND16)pWndDesktop->hwndSelf;
1257 /**********************************************************************
1258 * GetDesktopWindow32 (USER32.231)
1260 HWND32 GetDesktopWindow32(void)
1262 return pWndDesktop->hwndSelf;
1266 /**********************************************************************
1267 * GetDesktopHwnd (USER.278)
1269 * Exactly the same thing as GetDesktopWindow(), but not documented.
1270 * Don't ask me why...
1272 HWND16 GetDesktopHwnd(void)
1274 return (HWND16)pWndDesktop->hwndSelf;
1278 /*******************************************************************
1279 * EnableWindow (USER.34)
1281 BOOL EnableWindow( HWND hwnd, BOOL enable )
1283 WND *wndPtr;
1285 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1286 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1288 /* Enable window */
1289 wndPtr->dwStyle &= ~WS_DISABLED;
1290 SendMessage16( hwnd, WM_ENABLE, TRUE, 0 );
1291 return TRUE;
1293 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1295 /* Disable window */
1296 wndPtr->dwStyle |= WS_DISABLED;
1297 if ((hwnd == GetFocus32()) || IsChild( hwnd, GetFocus32() ))
1298 SetFocus32( 0 ); /* A disabled window can't have the focus */
1299 if ((hwnd == GetCapture32()) || IsChild( hwnd, GetCapture32() ))
1300 ReleaseCapture(); /* A disabled window can't capture the mouse */
1301 SendMessage16( hwnd, WM_ENABLE, FALSE, 0 );
1302 return FALSE;
1304 return ((wndPtr->dwStyle & WS_DISABLED) != 0);
1308 /***********************************************************************
1309 * IsWindowEnabled (USER.35) (USER32.348)
1311 BOOL IsWindowEnabled(HWND hWnd)
1313 WND * wndPtr;
1315 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1316 return !(wndPtr->dwStyle & WS_DISABLED);
1320 /***********************************************************************
1321 * IsWindowUnicode (USER32.349)
1323 BOOL32 IsWindowUnicode( HWND32 hwnd )
1325 WND * wndPtr;
1327 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1328 return (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1332 /**********************************************************************
1333 * GetWindowWord (USER.133) (USER32.313)
1335 WORD GetWindowWord( HWND32 hwnd, INT32 offset )
1337 WND * wndPtr = WIN_FindWndPtr( hwnd );
1338 if (!wndPtr) return 0;
1339 if (offset >= 0)
1341 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1343 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1344 return 0;
1346 return *(WORD *)(((char *)wndPtr->wExtra) + offset);
1348 switch(offset)
1350 case GWW_ID: return wndPtr->wIDmenu;
1351 case GWW_HWNDPARENT: return wndPtr->parent ? wndPtr->parent->hwndSelf : 0;
1352 case GWW_HINSTANCE: return (WORD)wndPtr->hInstance;
1353 default:
1354 fprintf( stderr, "GetWindowWord: invalid offset %d\n", offset );
1355 return 0;
1360 /**********************************************************************
1361 * WIN_GetWindowInstance
1363 HINSTANCE16 WIN_GetWindowInstance( HWND32 hwnd )
1365 WND * wndPtr = WIN_FindWndPtr( hwnd );
1366 if (!wndPtr) return (HINSTANCE16)0;
1367 return wndPtr->hInstance;
1371 /**********************************************************************
1372 * SetWindowWord (USER.134) (USER32.523)
1374 WORD SetWindowWord( HWND32 hwnd, INT32 offset, WORD newval )
1376 WORD *ptr, retval;
1377 WND * wndPtr = WIN_FindWndPtr( hwnd );
1378 if (!wndPtr) return 0;
1379 if (offset >= 0)
1381 if (offset + sizeof(WORD) > wndPtr->class->cbWndExtra)
1383 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1384 return 0;
1386 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1388 else switch(offset)
1390 case GWW_ID: ptr = (WORD *)&wndPtr->wIDmenu; break;
1391 case GWW_HINSTANCE: ptr = (WORD *)&wndPtr->hInstance; break;
1392 case GWW_HWNDPARENT: return SetParent( hwnd, newval );
1393 default:
1394 fprintf( stderr, "SetWindowWord: invalid offset %d\n", offset );
1395 return 0;
1397 retval = *ptr;
1398 *ptr = newval;
1399 return retval;
1403 /**********************************************************************
1404 * WIN_GetWindowLong
1406 * Helper function for GetWindowLong().
1408 static LONG WIN_GetWindowLong( HWND32 hwnd, INT32 offset, WINDOWPROCTYPE type )
1410 LONG retval;
1411 WND * wndPtr = WIN_FindWndPtr( hwnd );
1412 if (!wndPtr) return 0;
1413 if (offset >= 0)
1415 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1417 fprintf( stderr, "GetWindowLong: invalid offset %d\n", offset );
1418 return 0;
1420 retval = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1421 /* Special case for dialog window procedure */
1422 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1423 return (LONG)WINPROC_GetProc( (HWINDOWPROC)retval, type );
1424 return retval;
1426 switch(offset)
1428 case GWL_USERDATA: return wndPtr->userdata;
1429 case GWL_STYLE: return wndPtr->dwStyle;
1430 case GWL_EXSTYLE: return wndPtr->dwExStyle;
1431 case GWL_ID: return wndPtr->wIDmenu;
1432 case GWL_WNDPROC: return (LONG)WINPROC_GetProc( wndPtr->winproc,
1433 type );
1434 case GWL_HWNDPARENT: return wndPtr->parent ?
1435 (HWND32)wndPtr->parent->hwndSelf : 0;
1436 case GWL_HINSTANCE: return (HINSTANCE32)wndPtr->hInstance;
1437 default:
1438 fprintf( stderr, "GetWindowLong: unknown offset %d\n", offset );
1440 return 0;
1444 /**********************************************************************
1445 * WIN_SetWindowLong
1447 * Helper function for SetWindowLong().
1449 static LONG WIN_SetWindowLong( HWND32 hwnd, INT32 offset, LONG newval,
1450 WINDOWPROCTYPE type )
1452 LONG *ptr, retval;
1453 WND * wndPtr = WIN_FindWndPtr( hwnd );
1454 if (!wndPtr) return 0;
1455 if (offset >= 0)
1457 if (offset + sizeof(LONG) > wndPtr->class->cbWndExtra)
1459 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1460 return 0;
1462 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1463 /* Special case for dialog window procedure */
1464 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1466 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1467 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval, type );
1468 return retval;
1471 else switch(offset)
1473 case GWL_ID:
1474 case GWL_HINSTANCE:
1475 return SetWindowWord( hwnd, offset, (WORD)newval );
1476 case GWL_WNDPROC:
1477 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1478 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval, type );
1479 return retval;
1480 case GWL_STYLE:
1481 ptr = &wndPtr->dwStyle;
1482 /* Some bits can't be changed this way */
1483 newval &= ~(WS_VISIBLE | WS_CHILD);
1484 newval |= (*ptr & (WS_VISIBLE | WS_CHILD));
1485 break;
1486 case GWL_USERDATA: ptr = &wndPtr->userdata; break;
1487 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle; break;
1488 default:
1489 fprintf( stderr, "SetWindowLong: invalid offset %d\n", offset );
1490 return 0;
1492 retval = *ptr;
1493 *ptr = newval;
1494 return retval;
1498 /**********************************************************************
1499 * GetWindowLong16 (USER.135)
1501 LONG GetWindowLong16( HWND16 hwnd, INT16 offset )
1503 return WIN_GetWindowLong( (HWND32)hwnd, offset, WIN_PROC_16 );
1507 /**********************************************************************
1508 * GetWindowLong32A (USER32.304)
1510 LONG GetWindowLong32A( HWND32 hwnd, INT32 offset )
1512 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1516 /**********************************************************************
1517 * GetWindowLong32W (USER32.305)
1519 LONG GetWindowLong32W( HWND32 hwnd, INT32 offset )
1521 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1525 /**********************************************************************
1526 * SetWindowLong16 (USER.136)
1528 LONG SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1530 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_16 );
1534 /**********************************************************************
1535 * SetWindowLong32A (USER32.516)
1537 LONG SetWindowLong32A( HWND32 hwnd, INT32 offset, LONG newval )
1539 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1543 /**********************************************************************
1544 * SetWindowLong32W (USER32.517)
1546 LONG SetWindowLong32W( HWND32 hwnd, INT32 offset, LONG newval )
1548 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1552 /*******************************************************************
1553 * GetWindowText16 (USER.36)
1555 INT16 GetWindowText16( HWND16 hwnd, SEGPTR lpString, INT16 nMaxCount )
1557 return (INT16)SendMessage16(hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
1561 /*******************************************************************
1562 * GetWindowText32A (USER32.308)
1564 INT32 GetWindowText32A( HWND32 hwnd, LPSTR lpString, INT32 nMaxCount )
1566 return (INT32)SendMessage32A( hwnd, WM_GETTEXT, nMaxCount,
1567 (LPARAM)lpString );
1571 /*******************************************************************
1572 * GetWindowText32W (USER32.311)
1574 INT32 GetWindowText32W( HWND32 hwnd, LPWSTR lpString, INT32 nMaxCount )
1576 return (INT32)SendMessage32W( hwnd, WM_GETTEXT, nMaxCount,
1577 (LPARAM)lpString );
1581 /*******************************************************************
1582 * SetWindowText16 (USER.37)
1584 void SetWindowText16( HWND16 hwnd, SEGPTR lpString )
1586 SendMessage16( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1590 /*******************************************************************
1591 * SetWindowText32A (USER32.)
1593 void SetWindowText32A( HWND32 hwnd, LPCSTR lpString )
1595 SendMessage32A( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1599 /*******************************************************************
1600 * SetWindowText32W (USER32.)
1602 void SetWindowText32W( HWND32 hwnd, LPCWSTR lpString )
1604 SendMessage32W( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1608 /*******************************************************************
1609 * GetWindowTextLength16 (USER.38)
1611 INT16 GetWindowTextLength16( HWND16 hwnd )
1613 return (INT16)SendMessage16( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1617 /*******************************************************************
1618 * GetWindowTextLength32A (USER32.309)
1620 INT32 GetWindowTextLength32A( HWND32 hwnd )
1622 return SendMessage32A( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1625 /*******************************************************************
1626 * GetWindowTextLength32W (USER32.309)
1628 INT32 GetWindowTextLength32W( HWND32 hwnd )
1630 return SendMessage32W( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1633 /*******************************************************************
1634 * IsWindow (USER.47) (USER32.347)
1636 BOOL16 IsWindow( HWND32 hwnd )
1638 WND * wndPtr = WIN_FindWndPtr( hwnd );
1639 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
1643 /*****************************************************************
1644 * GetParent16 (USER.46)
1646 HWND16 GetParent16( HWND16 hwnd )
1648 return (HWND16)GetParent32( hwnd );
1652 /*****************************************************************
1653 * GetParent32 (USER32.277)
1655 HWND32 GetParent32( HWND32 hwnd )
1657 WND *wndPtr = WIN_FindWndPtr(hwnd);
1658 if (!wndPtr) return 0;
1659 wndPtr = (wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner;
1660 return wndPtr ? wndPtr->hwndSelf : 0;
1664 /*****************************************************************
1665 * WIN_GetTopParent
1667 * Get the top-level parent for a child window.
1669 HWND32 WIN_GetTopParent( HWND32 hwnd )
1671 WND *wndPtr = WIN_FindWndPtr( hwnd );
1672 while (wndPtr && (wndPtr->dwStyle & WS_CHILD)) wndPtr = wndPtr->parent;
1673 return wndPtr ? wndPtr->hwndSelf : 0;
1677 /*****************************************************************
1678 * SetParent (USER.233)
1680 HWND SetParent(HWND hwndChild, HWND hwndNewParent)
1682 HWND oldParent;
1684 WND *wndPtr = WIN_FindWndPtr(hwndChild);
1685 WND *pWndParent = WIN_FindWndPtr( hwndNewParent );
1686 if (!wndPtr || !pWndParent || !(wndPtr->dwStyle & WS_CHILD)) return 0;
1688 oldParent = wndPtr->parent->hwndSelf;
1690 WIN_UnlinkWindow(hwndChild);
1691 if (hwndNewParent) wndPtr->parent = pWndParent;
1692 WIN_LinkWindow(hwndChild, HWND_BOTTOM);
1694 if (IsWindowVisible(hwndChild)) UpdateWindow(hwndChild);
1696 return oldParent;
1701 /*******************************************************************
1702 * IsChild (USER.48)
1704 BOOL IsChild( HWND parent, HWND child )
1706 WND * wndPtr = WIN_FindWndPtr( child );
1707 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1709 wndPtr = wndPtr->parent;
1710 if (wndPtr->hwndSelf == parent) return TRUE;
1712 return FALSE;
1716 /***********************************************************************
1717 * IsWindowVisible (USER.49) (USER32.350)
1719 BOOL IsWindowVisible( HWND hwnd )
1721 WND *wndPtr = WIN_FindWndPtr( hwnd );
1722 while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
1724 if (!(wndPtr->dwStyle & WS_VISIBLE)) return FALSE;
1725 wndPtr = wndPtr->parent;
1727 return (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
1730 /***********************************************************************
1731 * WIN_IsWindowDrawable
1733 * hwnd is drawable when it is visible, all parents are not
1734 * minimized, and it is itself not minimized unless we are
1735 * trying to draw icon and the default class icon is set.
1737 BOOL32 WIN_IsWindowDrawable( WND* wnd , BOOL32 icon )
1739 HWND hwnd= wnd->hwndSelf;
1740 BOOL32 yes = TRUE;
1742 while(wnd && yes)
1744 if( wnd->dwStyle & WS_MINIMIZE )
1745 if( wnd->hwndSelf != hwnd ) break;
1746 else if( icon && wnd->class->hIcon ) break;
1748 yes = yes && (wnd->dwStyle & WS_VISIBLE);
1749 wnd = wnd->parent; }
1750 return (!wnd && yes);
1753 /*******************************************************************
1754 * GetTopWindow (USER.229)
1756 HWND GetTopWindow( HWND hwnd )
1758 WND * wndPtr = WIN_FindWndPtr( hwnd );
1759 if (wndPtr && wndPtr->child) return wndPtr->child->hwndSelf;
1760 else return 0;
1764 /*******************************************************************
1765 * GetWindow (USER.262)
1767 HWND GetWindow( HWND hwnd, WORD rel )
1769 WND * wndPtr = WIN_FindWndPtr( hwnd );
1770 if (!wndPtr) return 0;
1771 switch(rel)
1773 case GW_HWNDFIRST:
1774 if (wndPtr->parent) return wndPtr->parent->child->hwndSelf;
1775 else return 0;
1777 case GW_HWNDLAST:
1778 if (!wndPtr->parent) return 0; /* Desktop window */
1779 while (wndPtr->next) wndPtr = wndPtr->next;
1780 return wndPtr->hwndSelf;
1782 case GW_HWNDNEXT:
1783 if (!wndPtr->next) return 0;
1784 return wndPtr->next->hwndSelf;
1786 case GW_HWNDPREV:
1787 if (!wndPtr->parent) return 0; /* Desktop window */
1788 wndPtr = wndPtr->parent->child; /* First sibling */
1789 if (wndPtr->hwndSelf == hwnd) return 0; /* First in list */
1790 while (wndPtr->next)
1792 if (wndPtr->next->hwndSelf == hwnd) return wndPtr->hwndSelf;
1793 wndPtr = wndPtr->next;
1795 return 0;
1797 case GW_OWNER:
1798 return wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
1800 case GW_CHILD:
1801 return wndPtr->child ? wndPtr->child->hwndSelf : 0;
1803 return 0;
1807 /*******************************************************************
1808 * GetNextWindow (USER.230)
1810 HWND GetNextWindow( HWND hwnd, WORD flag )
1812 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
1813 return GetWindow( hwnd, flag );
1816 /*******************************************************************
1817 * ShowOwnedPopups (USER.265)
1819 void ShowOwnedPopups( HWND owner, BOOL fShow )
1821 WND *pWnd = pWndDesktop->child;
1822 while (pWnd)
1824 if (pWnd->owner && (pWnd->owner->hwndSelf == owner) &&
1825 (pWnd->dwStyle & WS_POPUP))
1826 ShowWindow( pWnd->hwndSelf, fShow ? SW_SHOW : SW_HIDE );
1827 pWnd = pWnd->next;
1832 /*******************************************************************
1833 * GetLastActivePopup (USER.287)
1835 HWND GetLastActivePopup(HWND hwnd)
1837 WND *wndPtr;
1838 wndPtr = WIN_FindWndPtr(hwnd);
1839 if (wndPtr == NULL) return hwnd;
1840 return wndPtr->hwndLastActive;
1844 /*******************************************************************
1845 * WIN_BuildWinArray
1847 * Build an array of pointers to all children of a given window.
1848 * The array must be freed with HeapFree(SystemHeap).
1850 WND **WIN_BuildWinArray( WND *wndPtr )
1852 WND **list, **ppWnd;
1853 WND *pWnd;
1854 INT32 count;
1856 /* First count the windows */
1858 if (!wndPtr) wndPtr = pWndDesktop;
1859 for (pWnd = wndPtr->child, count = 0; pWnd; pWnd = pWnd->next) count++;
1860 count++; /* For the terminating NULL */
1862 /* Now build the list of all windows */
1864 if (!(list = (WND **)HeapAlloc( SystemHeap, 0, sizeof(WND *) * count )))
1865 return NULL;
1866 for (pWnd = wndPtr->child, ppWnd = list; pWnd; pWnd = pWnd->next)
1867 *ppWnd++ = pWnd;
1868 *ppWnd = NULL;
1869 return list;
1873 /*******************************************************************
1874 * EnumWindows16 (USER.54)
1876 BOOL16 EnumWindows16( WNDENUMPROC16 lpEnumFunc, LPARAM lParam )
1878 WND **list, **ppWnd;
1880 /* We have to build a list of all windows first, to avoid */
1881 /* unpleasant side-effects, for instance if the callback */
1882 /* function changes the Z-order of the windows. */
1884 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1886 /* Now call the callback function for every window */
1888 for (ppWnd = list; *ppWnd; ppWnd++)
1890 /* Make sure that the window still exists */
1891 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1892 if (!lpEnumFunc( (*ppWnd)->hwndSelf, lParam )) break;
1894 HeapFree( SystemHeap, 0, list );
1895 return TRUE;
1899 /*******************************************************************
1900 * EnumWindows32 (USER32.192)
1902 BOOL32 EnumWindows32( WNDENUMPROC32 lpEnumFunc, LPARAM lParam )
1904 return (BOOL32)EnumWindows16( (WNDENUMPROC16)lpEnumFunc, lParam );
1908 /**********************************************************************
1909 * EnumTaskWindows16 (USER.225)
1911 BOOL16 EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func, LPARAM lParam )
1913 WND **list, **ppWnd;
1914 HQUEUE16 hQueue = GetTaskQueue( hTask );
1916 /* This function is the same as EnumWindows(), */
1917 /* except for an added check on the window queue. */
1919 if (!(list = WIN_BuildWinArray( pWndDesktop ))) return FALSE;
1921 /* Now call the callback function for every window */
1923 for (ppWnd = list; *ppWnd; ppWnd++)
1925 /* Make sure that the window still exists */
1926 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1927 if ((*ppWnd)->hmemTaskQ != hQueue) continue; /* Check the queue */
1928 if (!func( (*ppWnd)->hwndSelf, lParam )) break;
1930 HeapFree( SystemHeap, 0, list );
1931 return TRUE;
1935 /**********************************************************************
1936 * EnumThreadWindows (USER32.189)
1938 BOOL32 EnumThreadWindows( DWORD id, WNDENUMPROC32 func, LPARAM lParam )
1940 return (BOOL16)EnumTaskWindows16((HTASK16)id, (WNDENUMPROC16)func, lParam);
1944 /**********************************************************************
1945 * WIN_EnumChildWindows
1947 * Helper function for EnumChildWindows().
1949 static BOOL16 WIN_EnumChildWindows( WND **ppWnd, WNDENUMPROC16 func,
1950 LPARAM lParam )
1952 WND **childList;
1953 BOOL16 ret = FALSE;
1955 while (*ppWnd)
1957 /* Make sure that the window still exists */
1958 if (!IsWindow((*ppWnd)->hwndSelf)) continue;
1959 /* Build children list first */
1960 if (!(childList = WIN_BuildWinArray( *ppWnd ))) return FALSE;
1961 if (!func( (*ppWnd)->hwndSelf, lParam )) return FALSE;
1962 ret = WIN_EnumChildWindows( childList, func, lParam );
1963 HeapFree( SystemHeap, 0, childList );
1964 if (!ret) return FALSE;
1965 ppWnd++;
1967 return TRUE;
1971 /**********************************************************************
1972 * EnumChildWindows16 (USER.55)
1974 BOOL16 EnumChildWindows16( HWND16 parent, WNDENUMPROC16 func, LPARAM lParam )
1976 WND **list, *pParent;
1978 if (!(pParent = WIN_FindWndPtr( parent ))) return FALSE;
1979 if (!(list = WIN_BuildWinArray( pParent ))) return FALSE;
1980 WIN_EnumChildWindows( list, func, lParam );
1981 HeapFree( SystemHeap, 0, list );
1982 return TRUE;
1986 /**********************************************************************
1987 * EnumChildWindows32 (USER32.177)
1989 BOOL32 EnumChildWindows32( HWND32 parent, WNDENUMPROC32 func, LPARAM lParam )
1991 return (BOOL32)EnumChildWindows16( (HWND16)parent, (WNDENUMPROC16)func,
1992 lParam );
1996 /*******************************************************************
1997 * AnyPopup (USER.52)
1999 BOOL AnyPopup(void)
2001 WND *wndPtr;
2002 for (wndPtr = pWndDesktop->child; wndPtr; wndPtr = wndPtr->next)
2003 if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE)) return TRUE;
2004 return FALSE;
2007 /*******************************************************************
2008 * FlashWindow [USER.105]
2010 BOOL FlashWindow(HWND hWnd, BOOL bInvert)
2012 WND *wndPtr = WIN_FindWndPtr(hWnd);
2014 dprintf_win(stddeb,"FlashWindow: %04x\n", hWnd);
2016 if (!wndPtr) return FALSE;
2018 if (wndPtr->dwStyle & WS_MINIMIZE)
2020 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2022 HDC32 hDC = GetDC32(hWnd);
2024 if (!SendMessage16( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2025 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2027 ReleaseDC32( hWnd, hDC );
2028 wndPtr->flags |= WIN_NCACTIVATED;
2030 else
2032 PAINT_RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE |
2033 RDW_UPDATENOW | RDW_FRAME, 0 );
2034 wndPtr->flags &= ~WIN_NCACTIVATED;
2036 return TRUE;
2038 else
2040 WPARAM16 wparam;
2041 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2042 else wparam = (hWnd == GetActiveWindow());
2044 SendMessage16( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2045 return wparam;
2050 /*******************************************************************
2051 * SetSysModalWindow16 (USER.188)
2053 HWND16 SetSysModalWindow16( HWND16 hWnd )
2055 HWND hWndOldModal = hwndSysModal;
2056 hwndSysModal = hWnd;
2057 dprintf_win(stdnimp,"EMPTY STUB !! SetSysModalWindow(%04x) !\n", hWnd);
2058 return hWndOldModal;
2062 /*******************************************************************
2063 * GetSysModalWindow16 (USER.52)
2065 HWND16 GetSysModalWindow16(void)
2067 return hwndSysModal;
2071 /*******************************************************************
2072 * DRAG_QueryUpdate
2074 * recursively find a child that contains spDragInfo->pt point
2075 * and send WM_QUERYDROPOBJECT
2077 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL32 bNoSend )
2079 BOOL16 wParam,bResult = 0;
2080 POINT16 pt;
2081 LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
2082 WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
2083 RECT16 tempRect;
2085 if( !ptrQueryWnd || !ptrDragInfo ) return 0;
2087 pt = ptrDragInfo->pt;
2089 GetWindowRect16(hQueryWnd,&tempRect);
2091 if( !PtInRect16(&tempRect,pt) ||
2092 (ptrQueryWnd->dwStyle & WS_DISABLED) )
2093 return 0;
2095 if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
2097 tempRect = ptrQueryWnd->rectClient;
2098 if(ptrQueryWnd->dwStyle & WS_CHILD)
2099 MapWindowPoints16(ptrQueryWnd->parent->hwndSelf,0,(LPPOINT16)&tempRect,2);
2101 if( PtInRect16(&tempRect,pt) )
2103 wParam = 0;
2105 for (ptrWnd = ptrQueryWnd->child; ptrWnd ;ptrWnd = ptrWnd->next)
2106 if( ptrWnd->dwStyle & WS_VISIBLE )
2108 GetWindowRect16(ptrWnd->hwndSelf,&tempRect);
2110 if( PtInRect16(&tempRect,pt) )
2111 break;
2114 if(ptrWnd)
2116 dprintf_msg(stddeb,"DragQueryUpdate: hwnd = %04x, %d %d - %d %d\n",
2117 ptrWnd->hwndSelf, ptrWnd->rectWindow.left, ptrWnd->rectWindow.top,
2118 ptrWnd->rectWindow.right, ptrWnd->rectWindow.bottom );
2119 if( !(ptrWnd->dwStyle & WS_DISABLED) )
2120 bResult = DRAG_QueryUpdate(ptrWnd->hwndSelf, spDragInfo, bNoSend);
2123 if(bResult) return bResult;
2125 else wParam = 1;
2127 else wParam = 1;
2129 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2131 ptrDragInfo->hScope = hQueryWnd;
2133 bResult = ( bNoSend )
2134 ? ptrQueryWnd->dwExStyle & WS_EX_ACCEPTFILES
2135 : SendMessage16( hQueryWnd ,WM_QUERYDROPOBJECT ,
2136 (WPARAM16)wParam ,(LPARAM) spDragInfo );
2137 if( !bResult )
2138 ptrDragInfo->pt = pt;
2140 return bResult;
2143 /*******************************************************************
2144 * DragDetect ( USER.465 )
2147 BOOL16 DragDetect(HWND16 hWnd, POINT16 pt)
2149 MSG16 msg;
2150 RECT16 rect;
2152 rect.left = pt.x - wDragWidth;
2153 rect.right = pt.x + wDragWidth;
2155 rect.top = pt.y - wDragHeight;
2156 rect.bottom = pt.y + wDragHeight;
2158 SetCapture32(hWnd);
2160 while(1)
2162 while(PeekMessage16(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2164 if( msg.message == WM_LBUTTONUP )
2166 ReleaseCapture();
2167 return 0;
2169 if( msg.message == WM_MOUSEMOVE )
2171 if( !PtInRect16( &rect, MAKEPOINT16(msg.lParam) ) )
2173 ReleaseCapture();
2174 return 1;
2178 WaitMessage();
2181 return 0;
2184 /******************************************************************************
2185 * DragObject ( USER.464 )
2188 DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE16 hOfStruct,
2189 WORD szList , HCURSOR16 hCursor)
2191 MSG16 msg;
2192 LPDRAGINFO lpDragInfo;
2193 SEGPTR spDragInfo;
2194 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2195 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
2196 WND *wndPtr = WIN_FindWndPtr(hWnd);
2197 DWORD dwRet = 0;
2198 short dragDone = 0;
2199 HCURSOR16 hCurrentCursor = 0;
2200 HWND hCurrentWnd = 0;
2201 BOOL16 b;
2203 lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
2204 spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
2206 if( !lpDragInfo || !spDragInfo ) return 0L;
2208 hBummer = LoadCursor16(0,IDC_BUMMER);
2210 if( !hBummer || !wndPtr )
2212 GlobalFree16(hDragInfo);
2213 return 0L;
2216 if(hCursor)
2218 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2220 GlobalFree16(hDragInfo);
2221 return 0L;
2224 if( hDragCursor == hCursor ) hDragCursor = 0;
2225 else hCursor = hDragCursor;
2227 hOldCursor = SetCursor(hDragCursor);
2230 lpDragInfo->hWnd = hWnd;
2231 lpDragInfo->hScope = 0;
2232 lpDragInfo->wFlags = wObj;
2233 lpDragInfo->hList = szList; /* near pointer! */
2234 lpDragInfo->hOfStruct = hOfStruct;
2235 lpDragInfo->l = 0L;
2237 SetCapture32(hWnd);
2238 ShowCursor(1);
2240 while( !dragDone )
2242 WaitMessage();
2244 if( !PeekMessage16(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
2245 continue;
2247 *(lpDragInfo+1) = *lpDragInfo;
2249 lpDragInfo->pt = msg.pt;
2251 /* update DRAGINFO struct */
2252 dprintf_msg(stddeb,"drag: lpDI->hScope = %04x\n",lpDragInfo->hScope);
2254 if( (b = DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE)) > 0 )
2255 hCurrentCursor = hCursor;
2256 else
2258 hCurrentCursor = hBummer;
2259 lpDragInfo->hScope = 0;
2261 if( hCurrentCursor )
2262 SetCursor(hCurrentCursor);
2264 dprintf_msg(stddeb,"drag: got %04x\n", b);
2266 /* send WM_DRAGLOOP */
2267 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer) ,
2268 (LPARAM) spDragInfo );
2269 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2270 if( hCurrentWnd != lpDragInfo->hScope )
2272 if( hCurrentWnd )
2273 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2274 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
2275 HIWORD(spDragInfo)) );
2276 hCurrentWnd = lpDragInfo->hScope;
2277 if( hCurrentWnd )
2278 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2280 else
2281 if( hCurrentWnd )
2282 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2285 /* check if we're done */
2286 if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
2287 dragDone = TRUE;
2290 ReleaseCapture();
2291 ShowCursor(0);
2293 if( hCursor )
2295 SetCursor(hOldCursor);
2296 if( hDragCursor )
2297 DestroyCursor(hDragCursor);
2300 if( hCurrentCursor != hBummer )
2301 dwRet = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2302 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2303 GlobalFree16(hDragInfo);
2305 return dwRet;