2 * Window related functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
12 #include <X11/Shell.h>
18 #include "sysmetrics.h"
20 extern Display * display;
21 extern Colormap COLOR_WinColormap;
23 extern void EVENT_RegisterWindow( Window w, HWND hwnd ); /* event.c */
25 static HWND firstWindow = 0;
27 /***********************************************************************
30 * Return a pointer to the WND structure corresponding to a HWND.
32 WND * WIN_FindWndPtr( HWND hwnd )
36 if (!hwnd) return NULL;
37 ptr = (WND *) USER_HEAP_ADDR( hwnd );
38 if (ptr->dwMagic != WND_MAGIC) return NULL;
43 /***********************************************************************
46 * Remove a window from the siblings linked list.
48 BOOL WIN_UnlinkWindow( HWND hwnd )
51 WND * wndPtr = WIN_FindWndPtr( hwnd );
53 if (!wndPtr) return FALSE;
54 if (wndPtr->hwndParent)
56 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
57 curWndPtr = &parentPtr->hwndChild;
59 else curWndPtr = &firstWindow;
61 while (*curWndPtr != hwnd)
63 WND * curPtr = WIN_FindWndPtr( *curWndPtr );
64 curWndPtr = &curPtr->hwndNext;
66 *curWndPtr = wndPtr->hwndNext;
71 /***********************************************************************
74 * Insert a window into the siblings linked list.
75 * The window is inserted after the specified window, which can also
76 * be specified as HWND_TOP or HWND_BOTTOM.
78 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
80 HWND * hwndPtr = NULL; /* pointer to hwnd to change */
82 WND * wndPtr = WIN_FindWndPtr( hwnd );
83 if (!wndPtr) return FALSE;
85 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
87 /* Make hwndPtr point to the first sibling hwnd */
88 if (wndPtr->hwndParent)
90 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
91 if (parentPtr) hwndPtr = &parentPtr->hwndChild;
93 else hwndPtr = &firstWindow;
94 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
97 WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
98 hwndPtr = &nextPtr->hwndNext;
101 else /* Normal case */
103 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
104 if (afterPtr) hwndPtr = &afterPtr->hwndNext;
106 if (!hwndPtr) return FALSE;
107 wndPtr->hwndNext = *hwndPtr;
113 /***********************************************************************
114 * WIN_FindWinToRepaint
116 * Find a window that needs repaint.
118 HWND WIN_FindWinToRepaint( HWND hwnd )
122 if (!hwnd) hwnd = firstWindow;
123 for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
125 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
126 if (wndPtr->hrgnUpdate) return hwnd;
127 if (wndPtr->hwndChild)
130 if ((child = WIN_FindWinToRepaint( wndPtr->hwndChild )))
138 /***********************************************************************
139 * WIN_SendParentNotify
141 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
142 * the window has the WS_EX_NOPARENTNOTIFY style.
144 static void WIN_SendParentNotify( HWND hwnd, WND * wndPtr, WORD event )
146 HWND current = wndPtr->hwndParent;
148 if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) return;
151 SendMessage( current, WM_PARENTNOTIFY,
152 event, MAKELONG( hwnd, wndPtr->wIDmenu ) );
153 current = GetParent( current );
158 /***********************************************************************
159 * CreateWindow (USER.41)
161 HWND CreateWindow( LPSTR className, LPSTR windowName,
162 DWORD style, short x, short y, short width, short height,
163 HWND parent, HMENU menu, HANDLE instance, LPSTR data )
165 return CreateWindowEx( 0, className, windowName, style,
166 x, y, width, height, parent, menu, instance, data );
170 /***********************************************************************
171 * CreateWindowEx (USER.452)
173 HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
174 DWORD style, short x, short y, short width, short height,
175 HWND parent, HMENU menu, HANDLE instance, LPSTR data )
179 WND *wndPtr, *parentPtr = NULL;
180 CREATESTRUCT *createStruct;
181 HANDLE hcreateStruct;
183 XSetWindowAttributes win_attr;
189 printf( "CreateWindowEx: %d '%s' '%s' %d,%d %dx%d %08x %x\n",
190 exStyle, className, windowName, x, y, width, height, style, parent);
193 if (x == CW_USEDEFAULT) x = y = 0;
194 if (width == CW_USEDEFAULT)
199 if (width == 0) width = 1;
200 if (height == 0) height = 1;
202 /* Find the parent and class */
206 /* Check if parent is valid */
207 parentPtr = WIN_FindWndPtr( parent );
208 if (!parent) return 0;
210 else if (style & WS_CHILD) return 0; /* WS_CHILD needs a parent */
212 if (!(class = CLASS_FindClassByName( className, &classPtr ))) {
213 printf("CreateWindow BAD CLASSNAME '%s' !\n", className);
217 /* Correct the window style */
219 if (!(style & (WS_POPUP | WS_CHILD))) /* Overlapped window */
220 style |= WS_CAPTION | WS_CLIPSIBLINGS;
221 if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
223 /* Create the window structure */
225 hwnd = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra);
228 /* Fill the structure */
230 wndPtr = (WND *) USER_HEAP_ADDR( hwnd );
231 wndPtr->hwndNext = 0;
232 wndPtr->hwndChild = 0;
233 wndPtr->dwMagic = WND_MAGIC;
234 wndPtr->hwndParent = (style & WS_CHILD) ? parent : 0;
235 wndPtr->hwndOwner = (style & WS_CHILD) ? 0 : parent;
236 wndPtr->hClass = class;
237 wndPtr->hInstance = instance;
238 wndPtr->rectWindow.left = x;
239 wndPtr->rectWindow.top = y;
240 wndPtr->rectWindow.right = x + width;
241 wndPtr->rectWindow.bottom = y + height;
242 wndPtr->rectClient = wndPtr->rectWindow;
243 wndPtr->hmemTaskQ = GetTaskQueue(0);
244 wndPtr->hrgnUpdate = 0;
245 wndPtr->hwndLastActive = 0;
246 wndPtr->lpfnWndProc = classPtr->wc.lpfnWndProc;
247 wndPtr->dwStyle = style;
248 wndPtr->dwExStyle = exStyle;
249 wndPtr->hmenuSystem = 0;
250 wndPtr->wIDmenu = menu;
254 wndPtr->hWndVScroll = 0;
255 wndPtr->hWndHScroll = 0;
256 wndPtr->hWndMenuBar = 0;
257 wndPtr->hWndCaption = 0;
259 if (classPtr->wc.cbWndExtra)
260 memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
261 if (classPtr->wc.style & CS_DBLCLKS) wndPtr->flags |= WIN_DOUBLE_CLICKS;
262 classPtr->cWindows++;
264 /* Get class or window DC if needed */
265 if (classPtr->wc.style & CS_OWNDC)
267 wndPtr->flags |= WIN_OWN_DC;
268 wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
270 else if (classPtr->wc.style & CS_CLASSDC)
272 wndPtr->flags |= WIN_CLASS_DC;
273 wndPtr->hdce = classPtr->hdce;
275 else wndPtr->hdce = 0;
277 /* Insert the window in the linked list */
279 WIN_LinkWindow( hwnd, HWND_TOP );
281 /* Create the X window */
283 win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
284 PointerMotionMask | ButtonPressMask |
285 ButtonReleaseMask | StructureNotifyMask |
286 FocusChangeMask | EnterWindowMask;
287 win_attr.override_redirect = /*True*/ False;
288 win_attr.colormap = COLOR_WinColormap;
289 if (style & WS_CHILD)
291 parentWindow = parentPtr->window;
292 x_rel = x + parentPtr->rectClient.left - parentPtr->rectWindow.left;
293 y_rel = y + parentPtr->rectClient.top - parentPtr->rectWindow.top;
297 parentWindow = DefaultRootWindow( display );
301 wndPtr->window = XCreateWindow(display, parentWindow,
302 x_rel, y_rel, width, height, 0,
303 CopyFromParent, InputOutput, CopyFromParent,
304 CWEventMask | CWOverrideRedirect |
305 CWColormap, &win_attr );
306 XStoreName( display, wndPtr->window, windowName );
308 /* Send the WM_CREATE message */
310 hcreateStruct = GlobalAlloc( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
311 createStruct = (CREATESTRUCT *) GlobalLock( hcreateStruct );
312 createStruct->lpCreateParams = data;
313 createStruct->hInstance = instance;
314 createStruct->hMenu = menu;
315 createStruct->hwndParent = parent;
316 createStruct->cx = width;
317 createStruct->cy = height;
320 createStruct->style = style;
321 createStruct->lpszName = windowName;
322 createStruct->lpszClass = className;
323 createStruct->dwExStyle = 0;
325 wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
326 if (!wmcreate) wmcreate = -1;
329 /* Send WM_NCCALCSIZE message */
330 NCCALCSIZE_PARAMS *params;
332 hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
335 params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
336 params->rgrc[0] = wndPtr->rectWindow;
337 params->lppos = NULL;
338 SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
339 wndPtr->rectClient = params->rgrc[0];
340 GlobalUnlock( hparams );
341 GlobalFree( hparams );
343 wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
346 GlobalUnlock( hcreateStruct );
347 GlobalFree( hcreateStruct );
351 /* Abort window creation */
353 WIN_UnlinkWindow( hwnd );
354 XDestroyWindow( display, wndPtr->window );
355 if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
356 classPtr->cWindows--;
357 USER_HEAP_FREE( hwnd );
361 /* Create scrollbars */
363 if (windowName != NULL) SetWindowText(hwnd, windowName);
364 if ((style & WS_CAPTION) == WS_CAPTION) {
365 wndPtr->hWndCaption = CreateWindow("CAPTION", "",
366 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
367 0, -20, width, 20, hwnd, 1, instance, 0L);
369 if (((style & WS_CHILD) != WS_CHILD) && (wndPtr->wIDmenu != 0)) {
370 lpbar = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
372 lpbar->ownerWnd = hwnd;
373 wndPtr->hWndMenuBar = CreateWindow("POPUPMENU", "",
374 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
375 0, 0, width, 20, hwnd, 2, instance, (LPSTR)lpbar);
378 if ((style & WS_VSCROLL) == WS_VSCROLL)
380 wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
381 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
382 wndPtr->rectClient.right-wndPtr->rectClient.left, 0,
383 SYSMETRICS_CXVSCROLL,
384 wndPtr->rectClient.bottom-wndPtr->rectClient.top,
385 hwnd, 3, instance, 0L);
387 if ((style & WS_HSCROLL) == WS_HSCROLL)
389 wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
390 WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
391 0, wndPtr->rectClient.bottom-wndPtr->rectClient.top,
392 wndPtr->rectClient.right-wndPtr->rectClient.left,
393 SYSMETRICS_CYHSCROLL,
394 hwnd, 4, instance, 0L);
397 EVENT_RegisterWindow( wndPtr->window, hwnd );
399 WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
401 if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
405 /***********************************************************************
406 * DestroyWindow (USER.53)
408 BOOL DestroyWindow( HWND hwnd )
415 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
416 if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
417 WIN_SendParentNotify( hwnd, wndPtr, WM_DESTROY );
419 /* Send destroy messages */
421 SendMessage( hwnd, WM_DESTROY, 0, 0 );
422 SendMessage( hwnd, WM_NCDESTROY, 0, 0 );
424 /* Destroy all children */
426 if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
427 if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
428 while (wndPtr->hwndChild) /* The child removes itself from the list */
429 DestroyWindow( wndPtr->hwndChild );
431 /* Remove the window from the linked list */
433 WIN_UnlinkWindow( hwnd );
435 /* Destroy the window */
437 XDestroyWindow( display, wndPtr->window );
438 if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
439 classPtr->cWindows--;
440 USER_HEAP_FREE( hwnd );
445 /***********************************************************************
446 * CloseWindow (USER.43)
448 void CloseWindow(HWND hWnd)
450 WND * wndPtr = WIN_FindWndPtr(hWnd);
451 if (wndPtr->dwStyle & WS_CHILD) return;
452 ShowWindow(hWnd, SW_MINIMIZE);
457 /***********************************************************************
460 BOOL OpenIcon(HWND hWnd)
462 if (!IsIconic(hWnd)) return FALSE;
463 ShowWindow(hWnd, SW_SHOWNORMAL);
469 /***********************************************************************
470 * FindWindow (USER.50)
472 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
478 /***********************************************************************
479 * UpdateWindow (USER.124)
481 void UpdateWindow( HWND hwnd )
483 if (GetUpdateRect( hwnd, NULL, FALSE ))
485 if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
489 /**********************************************************************
492 HMENU GetMenu( HWND hwnd )
494 WND * wndPtr = WIN_FindWndPtr(hwnd);
497 return wndPtr->wIDmenu;
500 /**********************************************************************
503 BOOL SetMenu(HWND hwnd, HMENU hmenu)
509 /**********************************************************************
510 * GetDesktopWindow (USER.286)
512 HWND GetDesktopWindow()
519 /**********************************************************************
520 * GetWindowWord (USER.133)
522 WORD GetWindowWord( HWND hwnd, short offset )
524 WND * wndPtr = WIN_FindWndPtr( hwnd );
525 if (!wndPtr) return 0;
526 if (offset >= 0) return *(WORD *)(((char *)wndPtr->wExtra) + offset);
529 case GWW_ID: return wndPtr->wIDmenu;
530 case GWW_HWNDPARENT: return wndPtr->hwndParent;
531 case GWW_HINSTANCE: return wndPtr->hInstance;
537 /**********************************************************************
538 * SetWindowWord (USER.134)
540 WORD SetWindowWord( HWND hwnd, short offset, WORD newval )
543 WND * wndPtr = WIN_FindWndPtr( hwnd );
544 if (!wndPtr) return 0;
545 if (offset >= 0) ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
548 case GWW_ID: ptr = &wndPtr->wIDmenu;
549 case GWW_HINSTANCE: ptr = &wndPtr->hInstance;
558 /**********************************************************************
559 * GetWindowLong (USER.135)
561 LONG GetWindowLong( HWND hwnd, short offset )
563 WND * wndPtr = WIN_FindWndPtr( hwnd );
564 if (!wndPtr) return 0;
565 if (offset >= 0) return *(LONG *)(((char *)wndPtr->wExtra) + offset);
568 case GWL_STYLE: return wndPtr->dwStyle;
569 case GWL_EXSTYLE: return wndPtr->dwExStyle;
570 case GWL_WNDPROC: return (LONG)wndPtr->lpfnWndProc;
576 /**********************************************************************
577 * SetWindowLong (USER.136)
579 LONG SetWindowLong( HWND hwnd, short offset, LONG newval )
582 WND * wndPtr = WIN_FindWndPtr( hwnd );
583 if (!wndPtr) return 0;
584 if (offset >= 0) ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
587 case GWL_STYLE: ptr = &wndPtr->dwStyle;
588 case GWL_EXSTYLE: ptr = &wndPtr->dwExStyle;
589 case GWL_WNDPROC: ptr = (LONG *)(&wndPtr->lpfnWndProc);
598 /*******************************************************************
599 * GetWindowText (USER.36)
601 int GetWindowText(HWND hwnd, LPSTR lpString, int nMaxCount)
603 return (int)SendMessage(hwnd, WM_GETTEXT, (WORD)nMaxCount,
607 /*******************************************************************
608 * SetWindowText (USER.37)
610 void SetWindowText(HWND hwnd, LPSTR lpString)
612 SendMessage(hwnd, WM_SETTEXT, (WORD)NULL, (DWORD)lpString);
615 /*******************************************************************
616 * GetWindowTextLength (USER.38)
618 int GetWindowTextLength(HWND hwnd)
620 return (int)SendMessage(hwnd, WM_GETTEXTLENGTH, (WORD)NULL,
625 /*******************************************************************
628 BOOL IsWindow( HWND hwnd )
630 WND * wndPtr = WIN_FindWndPtr( hwnd );
631 return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
635 /*****************************************************************
636 * GetParent (USER.46)
638 HWND GetParent(HWND hwnd)
640 WND *wndPtr = WIN_FindWndPtr(hwnd);
641 if (!wndPtr) return 0;
642 return wndPtr->hwndParent;
646 /*******************************************************************
649 BOOL IsChild( HWND parent, HWND child )
655 if (!(parentPtr = WIN_FindWndPtr( parent ))) return FALSE;
656 curChild = parentPtr->hwndChild;
660 if (curChild == child) return TRUE;
661 if (IsChild( curChild, child )) return TRUE;
662 if (!(childPtr = WIN_FindWndPtr( curChild ))) return FALSE;
663 curChild = childPtr->hwndNext;
669 /***********************************************************************
670 * IsWindowVisible (USER.49)
672 BOOL IsWindowVisible(HWND hWnd)
674 WND * wndPtr = WIN_FindWndPtr(hWnd);
675 if (wndPtr == 0) return(FALSE);
676 else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
681 /*******************************************************************
682 * GetTopWindow (USER.229)
684 HWND GetTopWindow( HWND hwnd )
686 WND * wndPtr = WIN_FindWndPtr( hwnd );
687 if (wndPtr) return wndPtr->hwndChild;
692 /*******************************************************************
693 * GetWindow (USER.262)
695 HWND GetWindow( HWND hwnd, WORD rel )
697 WND * wndPtr = WIN_FindWndPtr( hwnd );
698 if (!wndPtr) return 0;
702 if (wndPtr->hwndParent)
704 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
705 return parentPtr->hwndChild;
707 else return firstWindow;
710 while (wndPtr->hwndNext)
712 hwnd = wndPtr->hwndNext;
713 wndPtr = WIN_FindWndPtr( hwnd );
718 return wndPtr->hwndNext;
724 if (wndPtr->hwndParent)
726 WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
727 hwndPrev = parentPtr->hwndChild;
729 else hwndPrev = firstWindow;
730 if (hwndPrev == hwnd) return 0;
733 wndPtr = WIN_FindWndPtr( hwndPrev );
734 if (wndPtr->hwndNext == hwnd) break;
735 hwndPrev = wndPtr->hwndNext;
741 return wndPtr->hwndOwner;
744 return wndPtr->hwndChild;
750 /*******************************************************************
751 * GetNextWindow (USER.230)
753 HWND GetNextWindow( HWND hwnd, WORD flag )
755 if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
756 return GetWindow( hwnd, flag );