2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
15 #include "sysmetrics.h"
17 #include "cursoricon.h"
20 #include "nonclient.h"
23 #include "shm_main_blk.h"
27 /* #define DEBUG_WIN */
28 /* #define DEBUG_MENU */
31 static HWND hwndDesktop
= 0;
32 static HWND hWndSysModal
= 0;
34 /***********************************************************************
37 * Return a pointer to the WND structure corresponding to a HWND.
39 WND
* WIN_FindWndPtr( HWND hwnd
)
43 if (!hwnd
) return NULL
;
44 ptr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
45 if (ptr
->dwMagic
!= WND_MAGIC
) return NULL
;
50 /***********************************************************************
53 * Return the X window associated to a window.
55 Window
WIN_GetXWindow( HWND hwnd
)
57 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
58 while (wndPtr
&& !wndPtr
->window
)
60 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
62 return wndPtr
? wndPtr
->window
: 0;
66 /***********************************************************************
69 * Remove a window from the siblings linked list.
71 BOOL
WIN_UnlinkWindow( HWND hwnd
)
74 WND
*parentPtr
, *wndPtr
;
76 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
77 if (!(parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
))) return FALSE
;
79 curWndPtr
= &parentPtr
->hwndChild
;
81 while (*curWndPtr
!= hwnd
)
83 WND
* curPtr
= WIN_FindWndPtr( *curWndPtr
);
84 curWndPtr
= &curPtr
->hwndNext
;
86 *curWndPtr
= wndPtr
->hwndNext
;
91 /***********************************************************************
94 * Insert a window into the siblings linked list.
95 * The window is inserted after the specified window, which can also
96 * be specified as HWND_TOP or HWND_BOTTOM.
98 BOOL
WIN_LinkWindow( HWND hwnd
, HWND hwndInsertAfter
)
100 HWND
* hwndPtr
= NULL
; /* pointer to hwnd to change */
101 WND
*wndPtr
, *parentPtr
;
103 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
104 if (!(parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
))) return FALSE
;
106 if ((hwndInsertAfter
== HWND_TOP
) || (hwndInsertAfter
== HWND_BOTTOM
))
108 hwndPtr
= &parentPtr
->hwndChild
; /* Point to first sibling hwnd */
109 if (hwndInsertAfter
== HWND_BOTTOM
) /* Find last sibling hwnd */
112 WND
* nextPtr
= WIN_FindWndPtr( *hwndPtr
);
113 hwndPtr
= &nextPtr
->hwndNext
;
116 else /* Normal case */
118 WND
* afterPtr
= WIN_FindWndPtr( hwndInsertAfter
);
119 if (afterPtr
) hwndPtr
= &afterPtr
->hwndNext
;
121 if (!hwndPtr
) return FALSE
;
122 wndPtr
->hwndNext
= *hwndPtr
;
128 /***********************************************************************
129 * WIN_FindWinToRepaint
131 * Find a window that needs repaint.
133 HWND
WIN_FindWinToRepaint( HWND hwnd
)
137 /* Note: the desktop window never gets WM_PAINT messages */
138 if (!hwnd
) hwnd
= GetTopWindow( hwndDesktop
);
139 for ( ; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
141 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return 0;
142 dprintf_win( stddeb
, "WIN_FindWinToRepaint: "NPFMT
", style %08lx\n",
143 hwnd
, wndPtr
->dwStyle
);
144 if (!(wndPtr
->dwStyle
& WS_VISIBLE
) || (wndPtr
->flags
& WIN_NO_REDRAW
))
146 if ((wndPtr
->dwStyle
& WS_MINIMIZE
) && (WIN_CLASS_INFO(wndPtr
).hIcon
))
148 if (wndPtr
->hrgnUpdate
|| (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
150 if (wndPtr
->hwndChild
)
153 if ((child
= WIN_FindWinToRepaint( wndPtr
->hwndChild
)))
161 /***********************************************************************
162 * WIN_SendParentNotify
164 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
165 * the window has the WS_EX_NOPARENTNOTIFY style.
167 void WIN_SendParentNotify( HWND hwnd
, WORD event
, WORD idChild
, LONG lValue
)
169 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
171 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
173 if (wndPtr
->dwExStyle
& WS_EX_NOPARENTNOTIFY
) break;
175 SendMessage( wndPtr
->hwndParent
, WM_PARENTNOTIFY
,
176 MAKEWPARAM(event
,idChild
),
179 SendMessage( wndPtr
->hwndParent
, WM_PARENTNOTIFY
, event
,
180 MAKELPARAM(LOWORD(lValue
), idChild
) );
182 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
187 /***********************************************************************
190 * Destroy storage associated to a window
192 static void WIN_DestroyWindow( HWND hwnd
)
194 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
195 CLASS
*classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
);
199 DDE_DestroyWindow(hwnd
);
200 #endif /* CONFIG_IPC */
202 if (!wndPtr
|| !classPtr
) return;
203 WIN_UnlinkWindow( hwnd
); /* Remove the window from the linked list */
204 wndPtr
->dwMagic
= 0; /* Mark it as invalid */
205 if ((wndPtr
->hrgnUpdate
) || (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
207 if (wndPtr
->hrgnUpdate
) DeleteObject( wndPtr
->hrgnUpdate
);
208 MSG_DecPaintCount( wndPtr
->hmemTaskQ
);
210 if (!(wndPtr
->dwStyle
& WS_CHILD
))
212 if (wndPtr
->wIDmenu
) DestroyMenu( (HMENU
)wndPtr
->wIDmenu
);
214 if (wndPtr
->hSysMenu
) DestroyMenu( wndPtr
->hSysMenu
);
215 if (wndPtr
->window
) XDestroyWindow( display
, wndPtr
->window
);
216 if (classPtr
->wc
.style
& CS_OWNDC
) DCE_FreeDCE( wndPtr
->hdce
);
217 classPtr
->cWindows
--;
218 USER_HEAP_FREE( hwnd
);
222 /***********************************************************************
223 * WIN_CreateDesktopWindow
225 * Create the desktop window.
227 BOOL
WIN_CreateDesktopWindow(void)
234 if (!(hclass
= CLASS_FindClassByName( DESKTOP_CLASS_ATOM
, 0, &classPtr
)))
237 hwndDesktop
= USER_HEAP_ALLOC( sizeof(WND
)+classPtr
->wc
.cbWndExtra
);
238 if (!hwndDesktop
) return FALSE
;
239 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwndDesktop
);
241 wndPtr
->hwndNext
= 0;
242 wndPtr
->hwndChild
= 0;
243 wndPtr
->dwMagic
= WND_MAGIC
;
244 wndPtr
->hwndParent
= 0;
245 wndPtr
->hwndOwner
= 0;
246 wndPtr
->hClass
= hclass
;
247 wndPtr
->hInstance
= 0;
248 wndPtr
->rectWindow
.left
= 0;
249 wndPtr
->rectWindow
.top
= 0;
250 wndPtr
->rectWindow
.right
= SYSMETRICS_CXSCREEN
;
251 wndPtr
->rectWindow
.bottom
= SYSMETRICS_CYSCREEN
;
252 wndPtr
->rectClient
= wndPtr
->rectWindow
;
253 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
254 wndPtr
->ptIconPos
.x
= -1;
255 wndPtr
->ptIconPos
.y
= -1;
256 wndPtr
->ptMaxPos
.x
= -1;
257 wndPtr
->ptMaxPos
.y
= -1;
258 wndPtr
->hmemTaskQ
= 0; /* Desktop does not belong to a task */
259 wndPtr
->hrgnUpdate
= 0;
260 wndPtr
->hwndLastActive
= hwndDesktop
;
261 wndPtr
->lpfnWndProc
= classPtr
->wc
.lpfnWndProc
;
262 wndPtr
->dwStyle
= WS_VISIBLE
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
;
263 wndPtr
->dwExStyle
= 0;
265 wndPtr
->hVScroll
= 0;
266 wndPtr
->hHScroll
= 0;
270 wndPtr
->window
= rootWindow
;
271 wndPtr
->hSysMenu
= 0;
273 EVENT_RegisterWindow( wndPtr
->window
, hwndDesktop
);
274 SendMessage( hwndDesktop
, WM_NCCREATE
, 0, 0 );
275 if ((hdc
= GetDC( hwndDesktop
)) != 0)
277 SendMessage( hwndDesktop
, WM_ERASEBKGND
, (WPARAM
)hdc
, 0 );
278 ReleaseDC( hwndDesktop
, hdc
);
284 /***********************************************************************
285 * CreateWindow (USER.41)
287 HWND
CreateWindow( SEGPTR className
, SEGPTR windowName
,
288 DWORD style
, INT x
, INT y
, INT width
, INT height
,
289 HWND parent
, HMENU menu
, HANDLE instance
, SEGPTR data
)
291 return CreateWindowEx( 0, className
, windowName
, style
,
292 x
, y
, width
, height
, parent
, menu
, instance
, data
);
296 /***********************************************************************
297 * CreateWindowEx (USER.452)
299 HWND
CreateWindowEx( DWORD exStyle
, SEGPTR className
, SEGPTR windowName
,
300 DWORD style
, INT x
, INT y
, INT width
, INT height
,
301 HWND parent
, HMENU menu
, HANDLE instance
, SEGPTR data
)
306 POINT maxSize
, maxPos
, minTrack
, maxTrack
;
307 CREATESTRUCT createStruct
;
309 XSetWindowAttributes win_attr
;
311 /* FIXME: windowName and className should be SEGPTRs */
313 dprintf_win( stddeb
, "CreateWindowEx: " );
314 if (HIWORD(windowName
))
315 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(windowName
) );
317 dprintf_win( stddeb
, "%04x ", LOWORD(windowName
) );
318 if (HIWORD(className
))
319 dprintf_win( stddeb
, "'%s' ", (char *)PTR_SEG_TO_LIN(className
) );
321 dprintf_win( stddeb
, "%04x ", LOWORD(className
) );
323 dprintf_win(stddeb
, "%08lx %08lx %d,%d %dx%d "NPFMT
" "NPFMT
" "NPFMT
" %08lx\n",
324 exStyle
, style
, x
, y
, width
, height
,
325 parent
, menu
, instance
, (DWORD
)data
);
327 if (x
== CW_USEDEFAULT
) x
= y
= 0;
328 if (width
== CW_USEDEFAULT
)
334 /* Find the parent and class */
338 /* Make sure parent is valid */
339 if (!IsWindow( parent
)) {
340 dprintf_win(stddeb
,"CreateWindowEx: Parent "NPFMT
" is not a window\n", parent
);
346 if (style
& WS_CHILD
) {
347 dprintf_win(stddeb
,"CreateWindowEx: no parent\n");
348 return 0; /* WS_CHILD needs a parent */
352 if (!(class = CLASS_FindClassByName( className
, GetExePtr(instance
),
355 fprintf(stderr
,"CreateWindow BAD CLASSNAME " );
356 if (HIWORD(className
)) fprintf( stderr
, "'%s'\n",
357 (char *)PTR_SEG_TO_LIN(className
) );
358 else fprintf( stderr
, "%04x\n", LOWORD(className
) );
362 /* Correct the window style */
364 if (!(style
& (WS_POPUP
| WS_CHILD
))) /* Overlapped window */
365 style
|= WS_CAPTION
| WS_CLIPSIBLINGS
;
366 if (exStyle
& WS_EX_DLGMODALFRAME
) style
&= ~WS_THICKFRAME
;
368 /* Create the window structure */
370 hwnd
= USER_HEAP_ALLOC( sizeof(WND
)+classPtr
->wc
.cbWndExtra
);
372 dprintf_win(stddeb
,"CreateWindowEx: Out of memory\n");
376 /* Fill the structure */
378 wndPtr
= (WND
*) USER_HEAP_LIN_ADDR( hwnd
);
379 wndPtr
->hwndNext
= 0;
380 wndPtr
->hwndChild
= 0;
382 wndPtr
->dwMagic
= WND_MAGIC
;
383 wndPtr
->hwndParent
= (style
& WS_CHILD
) ? parent
: hwndDesktop
;
384 wndPtr
->hwndOwner
= (style
& WS_CHILD
) ? 0 : WIN_GetTopParent(parent
);
385 wndPtr
->hClass
= class;
386 wndPtr
->hInstance
= instance
;
387 wndPtr
->ptIconPos
.x
= -1;
388 wndPtr
->ptIconPos
.y
= -1;
389 wndPtr
->ptMaxPos
.x
= -1;
390 wndPtr
->ptMaxPos
.y
= -1;
391 wndPtr
->hmemTaskQ
= GetTaskQueue(0);
392 wndPtr
->hrgnUpdate
= 0;
393 wndPtr
->hwndPrevActive
= 0;
394 wndPtr
->hwndLastActive
= hwnd
;
395 wndPtr
->lpfnWndProc
= classPtr
->wc
.lpfnWndProc
;
396 wndPtr
->dwStyle
= style
& ~WS_VISIBLE
;
397 wndPtr
->dwExStyle
= exStyle
;
401 wndPtr
->hVScroll
= 0;
402 wndPtr
->hHScroll
= 0;
403 wndPtr
->hSysMenu
= 0;
406 if (classPtr
->wc
.cbWndExtra
)
407 memset( wndPtr
->wExtra
, 0, classPtr
->wc
.cbWndExtra
);
408 classPtr
->cWindows
++;
410 /* Get class or window DC if needed */
412 if (classPtr
->wc
.style
& CS_OWNDC
)
413 wndPtr
->hdce
= DCE_AllocDCE( DCE_WINDOW_DC
);
414 else if (classPtr
->wc
.style
& CS_CLASSDC
)
415 wndPtr
->hdce
= classPtr
->hdce
;
419 /* Insert the window in the linked list */
421 WIN_LinkWindow( hwnd
, HWND_TOP
);
423 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
425 NC_GetMinMaxInfo( hwnd
, &maxSize
, &maxPos
, &minTrack
, &maxTrack
);
427 if (maxSize
.x
< width
) width
= maxSize
.x
;
428 if (maxSize
.y
< height
) height
= maxSize
.y
;
429 if (width
<= 0) width
= 1;
430 if (height
<= 0) height
= 1;
432 wndPtr
->rectWindow
.left
= x
;
433 wndPtr
->rectWindow
.top
= y
;
434 wndPtr
->rectWindow
.right
= x
+ width
;
435 wndPtr
->rectWindow
.bottom
= y
+ height
;
436 wndPtr
->rectClient
= wndPtr
->rectWindow
;
437 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
439 /* Create the X window (only for top-level windows, and then only */
440 /* when there's no desktop window) */
442 if (!(style
& WS_CHILD
) && (rootWindow
== DefaultRootWindow(display
)))
444 win_attr
.event_mask
= ExposureMask
| KeyPressMask
| KeyReleaseMask
|
445 PointerMotionMask
| ButtonPressMask
|
446 ButtonReleaseMask
| FocusChangeMask
;
447 win_attr
.override_redirect
= TRUE
;
448 win_attr
.colormap
= COLOR_WinColormap
;
449 win_attr
.backing_store
= Options
.backingstore
? WhenMapped
: NotUseful
;
450 win_attr
.save_under
= ((classPtr
->wc
.style
& CS_SAVEBITS
) != 0);
451 win_attr
.cursor
= CURSORICON_XCursor
;
452 wndPtr
->window
= XCreateWindow( display
, rootWindow
, x
, y
,
453 width
, height
, 0, CopyFromParent
,
454 InputOutput
, CopyFromParent
,
455 CWEventMask
| CWOverrideRedirect
|
456 CWColormap
| CWCursor
| CWSaveUnder
|
457 CWBackingStore
, &win_attr
);
458 XStoreName( display
, wndPtr
->window
, PTR_SEG_TO_LIN(windowName
) );
459 EVENT_RegisterWindow( wndPtr
->window
, hwnd
);
462 if ((style
& WS_CAPTION
) && !(style
& WS_CHILD
))
464 if (menu
) SetMenu(hwnd
, menu
);
465 else if (classPtr
->wc
.lpszMenuName
)
466 SetMenu( hwnd
, LoadMenu( instance
, classPtr
->wc
.lpszMenuName
) );
468 else wndPtr
->wIDmenu
= (UINT
)menu
;
470 /* Send the WM_CREATE message */
472 createStruct
.lpCreateParams
= (LPSTR
)data
;
473 createStruct
.hInstance
= instance
;
474 createStruct
.hMenu
= menu
;
475 createStruct
.hwndParent
= parent
;
476 createStruct
.cx
= width
;
477 createStruct
.cy
= height
;
480 createStruct
.style
= style
;
481 createStruct
.lpszName
= windowName
;
482 createStruct
.lpszClass
= className
;
483 createStruct
.dwExStyle
= 0;
485 wmcreate
= SendMessage( hwnd
, WM_NCCREATE
, 0, MAKE_SEGPTR(&createStruct
) );
488 dprintf_win(stddeb
,"CreateWindowEx: WM_NCCREATE return 0\n");
493 WINPOS_SendNCCalcSize( hwnd
, FALSE
, &wndPtr
->rectWindow
,
494 NULL
, NULL
, NULL
, &wndPtr
->rectClient
);
495 wmcreate
= SendMessage(hwnd
, WM_CREATE
, 0, MAKE_SEGPTR(&createStruct
));
500 /* Abort window creation */
501 dprintf_win(stddeb
,"CreateWindowEx: wmcreate==-1, aborting\n");
502 WIN_DestroyWindow( hwnd
);
506 /* Create a copy of SysMenu */
507 if (style
& WS_SYSMENU
) wndPtr
->hSysMenu
= CopySysMenu();
509 WIN_SendParentNotify( hwnd
, WM_CREATE
, wndPtr
->wIDmenu
, (LONG
)hwnd
);
511 /* Show the window, maximizing or minimizing if needed */
513 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
515 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
516 WINPOS_FindIconPos( hwnd
);
517 SetWindowPos( hwnd
, 0, wndPtr
->ptIconPos
.x
, wndPtr
->ptIconPos
.y
,
518 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
,
520 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
522 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
524 SetWindowPos( hwnd
, 0, maxPos
.x
, maxPos
.y
, maxSize
.x
, maxSize
.y
,
526 (style
& WS_VISIBLE
) ? SWP_SHOWWINDOW
: 0 );
528 else if (style
& WS_VISIBLE
) ShowWindow( hwnd
, SW_SHOW
);
530 dprintf_win(stddeb
, "CreateWindowEx: return "NPFMT
" \n", hwnd
);
535 /***********************************************************************
536 * DestroyWindow (USER.53)
538 BOOL
DestroyWindow( HWND hwnd
)
543 dprintf_win(stddeb
, "DestroyWindow ("NPFMT
")\n", hwnd
);
547 if (hwnd
== hwndDesktop
) return FALSE
; /* Can't destroy desktop */
548 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
549 if (!(classPtr
= CLASS_FindClassPtr( wndPtr
->hClass
))) return FALSE
;
551 /* Hide the window */
553 if (wndPtr
->dwStyle
& WS_VISIBLE
)
554 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_HIDEWINDOW
| SWP_NOACTIVATE
|
555 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOSIZE
);
556 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
558 WIN_SendParentNotify( hwnd
, WM_DESTROY
, wndPtr
->wIDmenu
, (LONG
)hwnd
);
560 /* Recursively destroy owned windows */
564 HWND hwndSibling
= GetWindow( hwnd
, GW_HWNDFIRST
);
567 WND
*siblingPtr
= WIN_FindWndPtr( hwndSibling
);
568 if (siblingPtr
->hwndOwner
== hwnd
) break;
569 hwndSibling
= siblingPtr
->hwndNext
;
571 if (hwndSibling
) DestroyWindow( hwndSibling
);
575 /* Send destroy messages and destroy children */
577 SendMessage( hwnd
, WM_DESTROY
, 0, 0 );
578 while (wndPtr
->hwndChild
) /* The child removes itself from the list */
579 DestroyWindow( wndPtr
->hwndChild
);
580 SendMessage( hwnd
, WM_NCDESTROY
, 0, 0 );
582 /* Destroy the window */
584 WIN_DestroyWindow( hwnd
);
589 /***********************************************************************
590 * CloseWindow (USER.43)
592 void CloseWindow(HWND hWnd
)
594 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
595 if (wndPtr
->dwStyle
& WS_CHILD
) return;
596 ShowWindow(hWnd
, SW_MINIMIZE
);
600 /***********************************************************************
603 BOOL
OpenIcon(HWND hWnd
)
605 if (!IsIconic(hWnd
)) return FALSE
;
606 ShowWindow(hWnd
, SW_SHOWNORMAL
);
611 /***********************************************************************
612 * FindWindow (USER.50)
614 HWND
FindWindow( SEGPTR ClassMatch
, LPSTR TitleMatch
)
622 hclass
= CLASS_FindClassByName( ClassMatch
, (HINSTANCE
)0xffff,
624 if (!hclass
) return 0;
628 hwnd
= GetTopWindow( hwndDesktop
);
631 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
632 if (!hclass
|| (wndPtr
->hClass
== hclass
))
634 /* Found matching class */
635 if (!TitleMatch
) return hwnd
;
638 char *textPtr
= (char *) USER_HEAP_LIN_ADDR( wndPtr
->hText
);
639 if (!strcmp( textPtr
, TitleMatch
)) return hwnd
;
642 hwnd
= wndPtr
->hwndNext
;
648 /**********************************************************************
649 * GetDesktopWindow (USER.286)
650 * GetDeskTopHwnd (USER.278)
652 HWND
GetDesktopWindow(void)
658 /*******************************************************************
659 * EnableWindow (USER.34)
661 BOOL
EnableWindow( HWND hwnd
, BOOL enable
)
665 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
666 if (enable
&& (wndPtr
->dwStyle
& WS_DISABLED
))
669 wndPtr
->dwStyle
&= ~WS_DISABLED
;
670 SendMessage( hwnd
, WM_ENABLE
, TRUE
, 0 );
673 else if (!enable
&& !(wndPtr
->dwStyle
& WS_DISABLED
))
676 wndPtr
->dwStyle
|= WS_DISABLED
;
677 if ((hwnd
== GetFocus()) || IsChild( hwnd
, GetFocus() ))
678 SetFocus( 0 ); /* A disabled window can't have the focus */
679 if ((hwnd
== GetCapture()) || IsChild( hwnd
, GetCapture() ))
680 ReleaseCapture(); /* A disabled window can't capture the mouse */
681 SendMessage( hwnd
, WM_ENABLE
, FALSE
, 0 );
684 return ((wndPtr
->dwStyle
& WS_DISABLED
) != 0);
688 /***********************************************************************
689 * IsWindowEnabled (USER.35)
691 BOOL
IsWindowEnabled(HWND hWnd
)
695 if (!(wndPtr
= WIN_FindWndPtr(hWnd
))) return FALSE
;
696 return !(wndPtr
->dwStyle
& WS_DISABLED
);
700 /**********************************************************************
701 * GetWindowWord (USER.133)
703 WORD
GetWindowWord( HWND hwnd
, short offset
)
705 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
706 if (!wndPtr
) return 0;
707 if (offset
>= 0) return *(WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
710 case GWW_ID
: return wndPtr
->wIDmenu
;
714 fprintf(stderr
,"GetWindowWord called with offset %d.\n",offset
);
717 case GWW_HWNDPARENT
: return (WORD
)wndPtr
->hwndParent
;
718 case GWW_HINSTANCE
: return (WORD
)wndPtr
->hInstance
;
725 /**********************************************************************
726 * WIN_GetWindowInstance
728 HINSTANCE
WIN_GetWindowInstance(HWND hwnd
)
730 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
731 if (!wndPtr
) return (HINSTANCE
)0;
732 return wndPtr
->hInstance
;
736 /**********************************************************************
737 * SetWindowWord (USER.134)
739 WORD
SetWindowWord( HWND hwnd
, short offset
, WORD newval
)
742 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
743 if (!wndPtr
) return 0;
744 if (offset
>= 0) ptr
= (WORD
*)(((char *)wndPtr
->wExtra
) + offset
);
750 fprintf(stderr
,"SetWindowWord called with offset %d.\n",offset
);
753 case GWW_ID
: ptr
= &wndPtr
->wIDmenu
; break;
754 case GWW_HINSTANCE
: ptr
= (WORD
*)&wndPtr
->hInstance
; break;
764 /**********************************************************************
765 * GetWindowLong (USER.135)
767 LONG
GetWindowLong( HWND hwnd
, short offset
)
769 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
770 if (!wndPtr
) return 0;
771 if (offset
>= 0) return *(LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
774 case GWL_STYLE
: return wndPtr
->dwStyle
;
775 case GWL_EXSTYLE
: return wndPtr
->dwExStyle
;
776 case GWL_WNDPROC
: return (LONG
)wndPtr
->lpfnWndProc
;
778 case GWW_HWNDPARENT
: return (LONG
)wndPtr
->hwndParent
;
779 case GWW_HINSTANCE
: return (LONG
)wndPtr
->hInstance
;
786 /**********************************************************************
787 * SetWindowLong (USER.136)
789 LONG
SetWindowLong( HWND hwnd
, short offset
, LONG newval
)
792 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
793 if (!wndPtr
) return 0;
794 if (offset
>= 0) ptr
= (LONG
*)(((char *)wndPtr
->wExtra
) + offset
);
797 case GWL_STYLE
: ptr
= &wndPtr
->dwStyle
; break;
798 case GWL_EXSTYLE
: ptr
= &wndPtr
->dwExStyle
; break;
799 case GWL_WNDPROC
: ptr
= (LONG
*)&wndPtr
->lpfnWndProc
; break;
808 /*******************************************************************
809 * GetWindowText (USER.36)
811 int WIN16_GetWindowText( HWND hwnd
, SEGPTR lpString
, int nMaxCount
)
813 return (int)SendMessage(hwnd
, WM_GETTEXT
, (WORD
)nMaxCount
,
817 int GetWindowText( HWND hwnd
, LPSTR lpString
, int nMaxCount
)
822 /* We have to allocate a buffer on the USER heap */
823 /* to be able to pass its address to 16-bit code */
824 if (!(handle
= USER_HEAP_ALLOC( nMaxCount
))) return 0;
825 len
= (int)SendMessage( hwnd
, WM_GETTEXT
, (WPARAM
)nMaxCount
,
826 (LPARAM
)USER_HEAP_SEG_ADDR(handle
) );
827 strncpy( lpString
, USER_HEAP_LIN_ADDR(handle
), nMaxCount
);
828 USER_HEAP_FREE( handle
);
833 /*******************************************************************
834 * SetWindowText (USER.37)
836 void WIN16_SetWindowText( HWND hwnd
, SEGPTR lpString
)
838 SendMessage( hwnd
, WM_SETTEXT
, 0, (DWORD
)lpString
);
841 void SetWindowText( HWND hwnd
, LPSTR lpString
)
845 /* We have to allocate a buffer on the USER heap */
846 /* to be able to pass its address to 16-bit code */
847 if (!(handle
= USER_HEAP_ALLOC( strlen(lpString
)+1 ))) return;
848 strcpy( USER_HEAP_LIN_ADDR(handle
), lpString
);
849 SendMessage( hwnd
, WM_SETTEXT
, 0, (LPARAM
)USER_HEAP_SEG_ADDR(handle
) );
850 USER_HEAP_FREE( handle
);
854 /*******************************************************************
855 * GetWindowTextLength (USER.38)
857 int GetWindowTextLength(HWND hwnd
)
859 return (int)SendMessage(hwnd
, WM_GETTEXTLENGTH
, 0, 0 );
863 /*******************************************************************
866 BOOL
IsWindow( HWND hwnd
)
868 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
869 return ((wndPtr
!= NULL
) && (wndPtr
->dwMagic
== WND_MAGIC
));
873 /*****************************************************************
874 * GetParent (USER.46)
876 HWND
GetParent(HWND hwnd
)
878 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
879 if (!wndPtr
) return 0;
880 return (wndPtr
->dwStyle
& WS_CHILD
) ?
881 wndPtr
->hwndParent
: wndPtr
->hwndOwner
;
885 /*****************************************************************
888 * Get the top-level parent for a child window.
890 HWND
WIN_GetTopParent( HWND hwnd
)
894 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
895 if (wndPtr
->dwStyle
& WS_CHILD
) hwnd
= wndPtr
->hwndParent
;
902 /*****************************************************************
903 * SetParent (USER.233)
905 HWND
SetParent(HWND hwndChild
, HWND hwndNewParent
)
909 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
910 if (!wndPtr
|| !(wndPtr
->dwStyle
& WS_CHILD
)) return 0;
912 temp
= wndPtr
->hwndParent
;
914 WIN_UnlinkWindow(hwndChild
);
916 wndPtr
->hwndParent
= hwndNewParent
;
918 wndPtr
->hwndParent
= GetDesktopWindow();
919 WIN_LinkWindow(hwndChild
, HWND_BOTTOM
);
921 if (IsWindowVisible(hwndChild
)) UpdateWindow(hwndChild
);
928 /*******************************************************************
931 BOOL
IsChild( HWND parent
, HWND child
)
933 WND
* wndPtr
= WIN_FindWndPtr( child
);
934 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
936 if (wndPtr
->hwndParent
== parent
) return TRUE
;
937 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
943 /***********************************************************************
944 * IsWindowVisible (USER.49)
946 BOOL
IsWindowVisible( HWND hwnd
)
948 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
949 while (wndPtr
&& (wndPtr
->dwStyle
& WS_CHILD
))
951 if (!(wndPtr
->dwStyle
& WS_VISIBLE
)) return FALSE
;
952 wndPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
954 return (wndPtr
&& (wndPtr
->dwStyle
& WS_VISIBLE
));
959 /*******************************************************************
960 * GetTopWindow (USER.229)
962 HWND
GetTopWindow( HWND hwnd
)
964 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
965 if (wndPtr
) return wndPtr
->hwndChild
;
970 /*******************************************************************
971 * GetWindow (USER.262)
973 HWND
GetWindow( HWND hwnd
, WORD rel
)
975 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
976 if (!wndPtr
) return 0;
980 if (wndPtr
->hwndParent
)
982 WND
* parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
983 return parentPtr
->hwndChild
;
988 if (!wndPtr
->hwndParent
) return 0; /* Desktop window */
989 while (wndPtr
->hwndNext
)
991 hwnd
= wndPtr
->hwndNext
;
992 wndPtr
= WIN_FindWndPtr( hwnd
);
997 return wndPtr
->hwndNext
;
1003 if (wndPtr
->hwndParent
)
1005 WND
* parentPtr
= WIN_FindWndPtr( wndPtr
->hwndParent
);
1006 hwndPrev
= parentPtr
->hwndChild
;
1008 else return 0; /* Desktop window */
1009 if (hwndPrev
== hwnd
) return 0;
1012 wndPtr
= WIN_FindWndPtr( hwndPrev
);
1013 if (wndPtr
->hwndNext
== hwnd
) break;
1014 hwndPrev
= wndPtr
->hwndNext
;
1020 return wndPtr
->hwndOwner
;
1023 return wndPtr
->hwndChild
;
1029 /*******************************************************************
1030 * GetNextWindow (USER.230)
1032 HWND
GetNextWindow( HWND hwnd
, WORD flag
)
1034 if ((flag
!= GW_HWNDNEXT
) && (flag
!= GW_HWNDPREV
)) return 0;
1035 return GetWindow( hwnd
, flag
);
1038 /*******************************************************************
1039 * ShowOwnedPopups (USER.265)
1041 void ShowOwnedPopups( HWND owner
, BOOL fShow
)
1043 HWND hwnd
= GetWindow( hwndDesktop
, GW_CHILD
);
1046 WND
*wnd
= WIN_FindWndPtr(hwnd
);
1047 if (wnd
->hwndOwner
== owner
&& (wnd
->dwStyle
& WS_POPUP
))
1048 ShowWindow( hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
1049 hwnd
= wnd
->hwndNext
;
1054 /*******************************************************************
1055 * GetLastActivePopup (USER.287)
1057 HWND
GetLastActivePopup(HWND hwnd
)
1060 wndPtr
= WIN_FindWndPtr(hwnd
);
1061 if (wndPtr
== NULL
) return hwnd
;
1062 return wndPtr
->hwndLastActive
;
1066 /*******************************************************************
1067 * EnumWindows (USER.54)
1069 BOOL
EnumWindows( FARPROC lpEnumFunc
, LPARAM lParam
)
1076 /* We have to build a list of all windows first, to avoid */
1077 /* unpleasant side-effects, for instance if the callback */
1078 /* function changes the Z-order of the windows. */
1080 /* First count the windows */
1083 for (hwnd
= GetTopWindow(hwndDesktop
); hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1085 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1088 if (!count
) return TRUE
;
1090 /* Now build the list of all windows */
1092 if (!(list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1093 for (hwnd
= GetTopWindow(hwndDesktop
), pWnd
= list
; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1095 wndPtr
= WIN_FindWndPtr( hwnd
);
1099 /* Now call the callback function for every window */
1101 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1103 /* Make sure that window still exists */
1104 if (!IsWindow(*pWnd
)) continue;
1105 if (!CallEnumWindowsProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1112 /**********************************************************************
1113 * EnumTaskWindows (USER.225)
1115 BOOL
EnumTaskWindows( HTASK hTask
, FARPROC lpEnumFunc
, LONG lParam
)
1120 HANDLE hQueue
= GetTaskQueue( hTask
);
1123 /* This function is the same as EnumWindows(), */
1124 /* except for an added check on the window queue. */
1126 /* First count the windows */
1129 for (hwnd
= GetTopWindow(hwndDesktop
); hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1131 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1132 if (wndPtr
->hmemTaskQ
== hQueue
) count
++;
1134 if (!count
) return TRUE
;
1136 /* Now build the list of all windows */
1138 if (!(list
= (HWND
*)malloc( sizeof(HWND
) * count
))) return FALSE
;
1139 for (hwnd
= GetTopWindow(hwndDesktop
), pWnd
= list
; hwnd
!= 0; hwnd
= wndPtr
->hwndNext
)
1141 wndPtr
= WIN_FindWndPtr( hwnd
);
1142 if (wndPtr
->hmemTaskQ
== hQueue
) *pWnd
++ = hwnd
;
1145 /* Now call the callback function for every window */
1147 for (pWnd
= list
; count
> 0; count
--, pWnd
++)
1149 /* Make sure that window still exists */
1150 if (!IsWindow(*pWnd
)) continue;
1151 if (!CallEnumTaskWndProc( lpEnumFunc
, *pWnd
, lParam
)) break;
1158 /*******************************************************************
1161 * o hwnd is the first child to use, loop until all next windows
1166 * o call ourselves with the next child window
1169 static BOOL
WIN_EnumChildWin(HWND hwnd
, FARPROC wndenumprc
, LPARAM lParam
)
1175 if (!(wndPtr
=WIN_FindWndPtr(hwnd
))) return 0;
1176 if (!CallEnumWindowsProc( wndenumprc
, hwnd
, lParam
)) return 0;
1177 if (!WIN_EnumChildWin(wndPtr
->hwndChild
, wndenumprc
, lParam
)) return 0;
1178 hwnd
=wndPtr
->hwndNext
;
1183 /*******************************************************************
1184 * EnumChildWindows (USER.55)
1186 * o gets the first child of hwnd
1188 * o calls WIN_EnumChildWin to do a recursive decent of child windows
1190 BOOL
EnumChildWindows(HWND hwnd
, FARPROC wndenumprc
, LPARAM lParam
)
1194 dprintf_enum(stddeb
,"EnumChildWindows\n");
1196 if (hwnd
== 0) return 0;
1197 if (!(wndPtr
= WIN_FindWndPtr(hwnd
))) return 0;
1198 hwnd
= wndPtr
->hwndChild
;
1199 return WIN_EnumChildWin(hwnd
, wndenumprc
, lParam
);
1203 /*******************************************************************
1204 * AnyPopup [USER.52]
1208 dprintf_win(stdnimp
,"EMPTY STUB !! AnyPopup !\n");
1212 /*******************************************************************
1213 * FlashWindow [USER.105]
1215 BOOL
FlashWindow(HWND hWnd
, BOOL bInvert
)
1217 dprintf_win(stdnimp
,"EMPTY STUB !! FlashWindow !\n");
1222 /*******************************************************************
1223 * SetSysModalWindow [USER.188]
1225 HWND
SetSysModalWindow(HWND hWnd
)
1227 HWND hWndOldModal
= hWndSysModal
;
1228 hWndSysModal
= hWnd
;
1229 dprintf_win(stdnimp
,"EMPTY STUB !! SetSysModalWindow("NPFMT
") !\n", hWnd
);
1230 return hWndOldModal
;
1234 /*******************************************************************
1235 * GetSysModalWindow [USER.189]
1237 HWND
GetSysModalWindow(void)
1239 return hWndSysModal
;