2 *Copyright (C) 2001-2004 Harold L Hunt II All Rights Reserved.
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL HAROLD L HUNT II BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *Except as contained in this notice, the name of Harold L Hunt II
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from Harold L Hunt II.
28 * Authors: Harold L Hunt II
31 #ifdef HAVE_XWIN_CONFIG_H
32 #include <xwin-config.h>
38 #define ABS_AUTOHIDE 1
42 * Local function prototypes
46 winGetWorkArea (RECT
*prcWorkArea
, winScreenInfo
*pScreenInfo
);
49 winAdjustForAutoHide (RECT
*prcWorkArea
);
53 * Create a full screen window
57 winCreateBoundingWindowFullScreen (ScreenPtr pScreen
)
59 winScreenPriv(pScreen
);
60 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
61 int iX
= pScreenInfo
->dwInitialX
;
62 int iY
= pScreenInfo
->dwInitialY
;
63 int iWidth
= pScreenInfo
->dwWidth
;
64 int iHeight
= pScreenInfo
->dwHeight
;
65 HWND
*phwnd
= &pScreenPriv
->hwndScreen
;
70 winDebug ("winCreateBoundingWindowFullScreen\n");
73 /* Setup our window class */
74 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
75 wc
.lpfnWndProc
= winWindowProc
;
78 wc
.hInstance
= g_hInstance
;
79 wc
.hIcon
= LoadIcon (g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
));
82 wc
.lpszMenuName
= NULL
;
83 wc
.lpszClassName
= WINDOW_CLASS
;
86 /* Set display and screen-specific tooltip text */
87 if (g_pszQueryHost
!= NULL
)
97 (int) pScreenInfo
->dwScreen
);
99 /* Create the window */
100 *phwnd
= CreateWindowExA (0, /* Extended styles */
101 WINDOW_CLASS
, /* Class name */
102 szTitle
, /* Window name */
104 iX
, /* Horizontal position */
105 iY
, /* Vertical position */
106 iWidth
, /* Right edge */
107 iHeight
, /* Bottom edge */
108 (HWND
) NULL
, /* No parent or owner window */
109 (HMENU
) NULL
, /* No menu */
110 GetModuleHandle (NULL
),/* Instance handle */
111 pScreenPriv
); /* ScreenPrivates */
113 /* Branch on the server engine */
114 switch (pScreenInfo
->dwEngine
)
116 #ifdef XWIN_NATIVEGDI
117 case WIN_SERVER_SHADOW_GDI
:
118 /* Show the window */
119 ShowWindow (*phwnd
, SW_SHOWMAXIMIZED
);
124 /* Hide the window */
125 ShowWindow (*phwnd
, SW_SHOWNORMAL
);
129 /* Send first paint message */
130 UpdateWindow (*phwnd
);
132 /* Attempt to bring our window to the top of the display */
133 BringWindowToTop (*phwnd
);
140 * Create our primary Windows display window
144 winCreateBoundingWindowWindowed (ScreenPtr pScreen
)
146 winScreenPriv(pScreen
);
147 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
148 int iWidth
= pScreenInfo
->dwUserWidth
;
149 int iHeight
= pScreenInfo
->dwUserHeight
;
152 HWND
*phwnd
= &pScreenPriv
->hwndScreen
;
154 RECT rcClient
, rcWorkArea
;
156 BOOL fForceShowWindow
= FALSE
;
159 winDebug ("winCreateBoundingWindowWindowed - User w: %d h: %d\n",
160 (int) pScreenInfo
->dwUserWidth
, (int) pScreenInfo
->dwUserHeight
);
161 winDebug ("winCreateBoundingWindowWindowed - Current w: %d h: %d\n",
162 (int) pScreenInfo
->dwWidth
, (int) pScreenInfo
->dwHeight
);
164 /* Set the common window style flags */
165 dwWindowStyle
= WS_OVERLAPPED
| WS_SYSMENU
| WS_MINIMIZEBOX
;
167 /* Decorated or undecorated window */
168 if (pScreenInfo
->fDecoration
169 #ifdef XWIN_MULTIWINDOWEXTWM
170 && !pScreenInfo
->fMWExtWM
172 && !pScreenInfo
->fRootless
173 #ifdef XWIN_MULTIWINDOW
174 && !pScreenInfo
->fMultiWindow
178 /* Try to handle startup via run.exe. run.exe instructs Windows to
179 * hide all created windows. Detect this case and make sure the
180 * window is shown nevertheless */
181 STARTUPINFO startupInfo
;
182 GetStartupInfo(&startupInfo
);
183 if (startupInfo
.dwFlags
& STARTF_USESHOWWINDOW
&&
184 startupInfo
.wShowWindow
== SW_HIDE
)
186 fForceShowWindow
= TRUE
;
188 dwWindowStyle
|= WS_CAPTION
;
189 if (pScreenInfo
->fScrollbars
)
190 dwWindowStyle
|= WS_THICKFRAME
| WS_MAXIMIZEBOX
;
193 dwWindowStyle
|= WS_POPUP
;
195 /* Setup our window class */
196 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
197 wc
.lpfnWndProc
= winWindowProc
;
200 wc
.hInstance
= g_hInstance
;
201 wc
.hIcon
= LoadIcon (g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
));
203 wc
.hbrBackground
= (HBRUSH
) GetStockObject (WHITE_BRUSH
);
204 wc
.lpszMenuName
= NULL
;
205 wc
.lpszClassName
= WINDOW_CLASS
;
208 /* Get size of work area */
209 winGetWorkArea (&rcWorkArea
, pScreenInfo
);
211 /* Adjust for auto-hide taskbars */
212 winAdjustForAutoHide (&rcWorkArea
);
214 /* Did the user specify a position? */
215 if (pScreenInfo
->fUserGavePosition
)
217 iPosX
= pScreenInfo
->dwInitialX
;
218 iPosY
= pScreenInfo
->dwInitialY
;
222 iPosX
= rcWorkArea
.left
;
223 iPosY
= rcWorkArea
.top
;
226 /* Did the user specify a height and width? */
227 if (pScreenInfo
->fUserGaveHeightAndWidth
)
229 /* User gave a desired height and width, try to accomodate */
231 winDebug ("winCreateBoundingWindowWindowed - User gave height "
235 /* Adjust the window width and height for borders and title bar */
236 if (pScreenInfo
->fDecoration
237 #ifdef XWIN_MULTIWINDOWEXTWM
238 && !pScreenInfo
->fMWExtWM
240 && !pScreenInfo
->fRootless
241 #ifdef XWIN_MULTIWINDOW
242 && !pScreenInfo
->fMultiWindow
247 winDebug ("winCreateBoundingWindowWindowed - Window has decoration\n");
249 /* Are we using scrollbars? */
250 if (pScreenInfo
->fScrollbars
)
253 winDebug ("winCreateBoundingWindowWindowed - Window has "
257 iWidth
+= 2 * GetSystemMetrics (SM_CXSIZEFRAME
);
258 iHeight
+= 2 * GetSystemMetrics (SM_CYSIZEFRAME
)
259 + GetSystemMetrics (SM_CYCAPTION
);
264 winDebug ("winCreateBoundingWindowWindowed - Window does not have "
268 iWidth
+= 2 * GetSystemMetrics (SM_CXFIXEDFRAME
);
269 iHeight
+= 2 * GetSystemMetrics (SM_CYFIXEDFRAME
)
270 + GetSystemMetrics (SM_CYCAPTION
);
276 /* By default, we are creating a window that is as large as possible */
278 winDebug ("winCreateBoundingWindowWindowed - User did not give "
279 "height and width\n");
281 /* Defaults are wrong if we have multiple monitors */
282 if (pScreenInfo
->fMultipleMonitors
)
284 iWidth
= GetSystemMetrics (SM_CXVIRTUALSCREEN
);
285 iHeight
= GetSystemMetrics (SM_CYVIRTUALSCREEN
);
289 /* Clean up the scrollbars flag, if necessary */
290 if ((!pScreenInfo
->fDecoration
291 #ifdef XWIN_MULTIWINDOWEXTWM
292 || pScreenInfo
->fMWExtWM
294 || pScreenInfo
->fRootless
295 #ifdef XWIN_MULTIWINDOW
296 || pScreenInfo
->fMultiWindow
299 && pScreenInfo
->fScrollbars
)
301 /* We cannot have scrollbars if we do not have a window border */
302 pScreenInfo
->fScrollbars
= FALSE
;
306 #ifdef XWIN_MULTIWINDOWEXTWM
307 && !pScreenInfo
->fMWExtWM
309 #ifdef XWIN_MULTIWINDOW
310 && !pScreenInfo
->fMultiWindow
314 /* Trim window width to fit work area */
315 if (iWidth
> (rcWorkArea
.right
- rcWorkArea
.left
))
316 iWidth
= rcWorkArea
.right
- rcWorkArea
.left
;
318 /* Trim window height to fit work area */
319 if (iHeight
>= (rcWorkArea
.bottom
- rcWorkArea
.top
))
320 iHeight
= rcWorkArea
.bottom
- rcWorkArea
.top
;
323 winDebug ("winCreateBoundingWindowWindowed - Adjusted width: %d "\
329 /* Set display and screen-specific tooltip text */
330 if (g_pszQueryHost
!= NULL
)
340 (int) pScreenInfo
->dwScreen
);
342 /* Create the window */
343 *phwnd
= CreateWindowExA (0, /* Extended styles */
344 WINDOW_CLASS
, /* Class name */
345 szTitle
, /* Window name */
347 iPosX
, /* Horizontal position */
348 iPosY
, /* Vertical position */
349 iWidth
, /* Right edge */
350 iHeight
, /* Bottom edge */
351 (HWND
) NULL
, /* No parent or owner window */
352 (HMENU
) NULL
, /* No menu */
353 GetModuleHandle (NULL
),/* Instance handle */
354 pScreenPriv
); /* ScreenPrivates */
357 ErrorF ("winCreateBoundingWindowWindowed - CreateWindowEx () failed\n");
362 winDebug ("winCreateBoundingWindowWindowed - CreateWindowEx () returned\n");
365 if (fForceShowWindow
)
367 ErrorF("winCreateBoundingWindowWindowed - Setting normal windowstyle\n");
368 ShowWindow(*phwnd
, SW_SHOW
);
371 /* Get the client area coordinates */
372 if (!GetClientRect (*phwnd
, &rcClient
))
374 ErrorF ("winCreateBoundingWindowWindowed - GetClientRect () "
379 winDebug ("winCreateBoundingWindowWindowed - WindowClient "
380 "w %ld h %ld r %ld l %ld b %ld t %ld\n",
381 rcClient
.right
- rcClient
.left
,
382 rcClient
.bottom
- rcClient
.top
,
383 rcClient
.right
, rcClient
.left
,
384 rcClient
.bottom
, rcClient
.top
);
386 /* We adjust the visual size if the user did not specify it */
387 if (!(pScreenInfo
->fScrollbars
&& pScreenInfo
->fUserGaveHeightAndWidth
))
390 * User did not give a height and width with scrollbars enabled,
391 * so we will resize the underlying visual to be as large as
392 * the initial view port (page size). This way scrollbars will
393 * not appear until the user shrinks the window, if they ever do.
395 * NOTE: We have to store the viewport size here because
396 * the user may have an autohide taskbar, which would
397 * cause the viewport size to be one less in one dimension
398 * than the viewport size that we calculated by subtracting
399 * the size of the borders and caption.
401 pScreenInfo
->dwWidth
= rcClient
.right
- rcClient
.left
;
402 pScreenInfo
->dwHeight
= rcClient
.bottom
- rcClient
.top
;
407 * NOTE: For the uninitiated, the page size is the number of pixels
408 * that we can display in the x or y direction at a time and the
409 * range is the total number of pixels in the x or y direction that we
410 * have available to display. In other words, the page size is the
411 * size of the window area minus the space the caption, borders, and
412 * scrollbars (if any) occupy, and the range is the size of the
413 * underlying X visual. Notice that, contrary to what some of the
414 * MSDN Library arcticles lead you to believe, the windows
415 * ``client area'' size does not include the scrollbars. In other words,
416 * the whole client area size that is reported to you is drawable by
417 * you; you do not have to subtract the size of the scrollbars from
418 * the client area size, and if you did it would result in the size
419 * of the scrollbars being double counted.
422 /* Setup scrollbar page and range, if scrollbars are enabled */
423 if (pScreenInfo
->fScrollbars
)
427 /* Initialize the scrollbar info structure */
428 si
.cbSize
= sizeof (si
);
429 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
432 /* Setup the width range and page size */
433 si
.nMax
= pScreenInfo
->dwWidth
- 1;
434 si
.nPage
= rcClient
.right
- rcClient
.left
;
435 winDebug ("winCreateBoundingWindowWindowed - HORZ nMax: %d nPage :%d\n",
437 SetScrollInfo (*phwnd
, SB_HORZ
, &si
, TRUE
);
439 /* Setup the height range and page size */
440 si
.nMax
= pScreenInfo
->dwHeight
- 1;
441 si
.nPage
= rcClient
.bottom
- rcClient
.top
;
442 winDebug ("winCreateBoundingWindowWindowed - VERT nMax: %d nPage :%d\n",
444 SetScrollInfo (*phwnd
, SB_VERT
, &si
, TRUE
);
448 /* Show the window */
450 #ifdef XWIN_MULTIWINDOWEXTWM
451 || pScreenInfo
->fMWExtWM
453 #ifdef XWIN_MULTIWINDOW
454 || pScreenInfo
->fMultiWindow
458 #if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
459 pScreenPriv
->fRootWindowShown
= FALSE
;
461 ShowWindow (*phwnd
, SW_HIDE
);
464 ShowWindow (*phwnd
, SW_SHOWNORMAL
);
465 if (!UpdateWindow (*phwnd
))
467 ErrorF ("winCreateBoundingWindowWindowed - UpdateWindow () failed\n");
471 /* Attempt to bring our window to the top of the display */
473 #ifdef XWIN_MULTIWINDOWEXTWM
474 && !pScreenInfo
->fMWExtWM
476 && !pScreenInfo
->fRootless
477 #ifdef XWIN_MULTIWINDOW
478 && !pScreenInfo
->fMultiWindow
482 if (!BringWindowToTop (*phwnd
))
484 ErrorF ("winCreateBoundingWindowWindowed - BringWindowToTop () "
490 #ifdef XWIN_NATIVEGDI
491 /* Paint window background blue */
492 if (pScreenInfo
->dwEngine
== WIN_SERVER_NATIVE_GDI
)
493 winPaintBackground (*phwnd
, RGB (0x00, 0x00, 0xFF));
496 winDebug ("winCreateBoundingWindowWindowed - Returning\n");
503 * Find the work area of all attached monitors
507 winGetWorkArea (RECT
*prcWorkArea
, winScreenInfo
*pScreenInfo
)
509 int iPrimaryWidth
, iPrimaryHeight
;
512 int iPrimaryNonWorkAreaWidth
, iPrimaryNonWorkAreaHeight
;
514 /* SPI_GETWORKAREA only gets the work area of the primary screen. */
515 SystemParametersInfo (SPI_GETWORKAREA
, 0, prcWorkArea
, 0);
517 /* Bail out here if we aren't using multiple monitors */
518 if (!pScreenInfo
->fMultipleMonitors
)
521 winDebug ("winGetWorkArea - Original WorkArea: %d %d %d %d\n",
522 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
523 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
525 /* Get size of full virtual screen */
526 iWidth
= GetSystemMetrics (SM_CXVIRTUALSCREEN
);
527 iHeight
= GetSystemMetrics (SM_CYVIRTUALSCREEN
);
529 winDebug ("winGetWorkArea - Virtual screen is %d x %d\n", iWidth
, iHeight
);
531 /* Get origin of full virtual screen */
532 iLeft
= GetSystemMetrics (SM_XVIRTUALSCREEN
);
533 iTop
= GetSystemMetrics (SM_YVIRTUALSCREEN
);
535 winDebug ("winGetWorkArea - Virtual screen origin is %d, %d\n", iLeft
, iTop
);
537 /* Get size of primary screen */
538 iPrimaryWidth
= GetSystemMetrics (SM_CXSCREEN
);
539 iPrimaryHeight
= GetSystemMetrics (SM_CYSCREEN
);
541 winDebug ("winGetWorkArea - Primary screen is %d x %d\n",
542 iPrimaryWidth
, iPrimaryHeight
);
544 /* Work out how much of the primary screen we aren't using */
545 iPrimaryNonWorkAreaWidth
= iPrimaryWidth
- (prcWorkArea
->right
-
547 iPrimaryNonWorkAreaHeight
= iPrimaryHeight
- (prcWorkArea
->bottom
550 /* Update the rectangle to include all monitors */
553 prcWorkArea
->left
= iLeft
;
557 prcWorkArea
->top
= iTop
;
559 prcWorkArea
->right
= prcWorkArea
->left
+ iWidth
-
560 iPrimaryNonWorkAreaWidth
;
561 prcWorkArea
->bottom
= prcWorkArea
->top
+ iHeight
-
562 iPrimaryNonWorkAreaHeight
;
564 winDebug ("winGetWorkArea - Adjusted WorkArea for multiple "
565 "monitors: %d %d %d %d\n",
566 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
567 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
574 * Adjust the client area so that any auto-hide toolbars
575 * will work correctly.
579 winAdjustForAutoHide (RECT
*prcWorkArea
)
584 winDebug ("winAdjustForAutoHide - Original WorkArea: %d %d %d %d\n",
585 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
586 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
588 /* Find out if the Windows taskbar is set to auto-hide */
589 ZeroMemory (&abd
, sizeof (abd
));
590 abd
.cbSize
= sizeof (abd
);
591 if (SHAppBarMessage (ABM_GETSTATE
, &abd
) & ABS_AUTOHIDE
)
592 winDebug ("winAdjustForAutoHide - Taskbar is auto hide\n");
594 /* Look for a TOP auto-hide taskbar */
596 hwndAutoHide
= (HWND
) SHAppBarMessage (ABM_GETAUTOHIDEBAR
, &abd
);
597 if (hwndAutoHide
!= NULL
)
599 winDebug ("winAdjustForAutoHide - Found TOP auto-hide taskbar\n");
600 prcWorkArea
->top
+= 1;
603 /* Look for a LEFT auto-hide taskbar */
604 abd
.uEdge
= ABE_LEFT
;
605 hwndAutoHide
= (HWND
) SHAppBarMessage (ABM_GETAUTOHIDEBAR
, &abd
);
606 if (hwndAutoHide
!= NULL
)
608 winDebug ("winAdjustForAutoHide - Found LEFT auto-hide taskbar\n");
609 prcWorkArea
->left
+= 1;
612 /* Look for a BOTTOM auto-hide taskbar */
613 abd
.uEdge
= ABE_BOTTOM
;
614 hwndAutoHide
= (HWND
) SHAppBarMessage (ABM_GETAUTOHIDEBAR
, &abd
);
615 if (hwndAutoHide
!= NULL
)
617 winDebug ("winAdjustForAutoHide - Found BOTTOM auto-hide taskbar\n");
618 prcWorkArea
->bottom
-= 1;
621 /* Look for a RIGHT auto-hide taskbar */
622 abd
.uEdge
= ABE_RIGHT
;
623 hwndAutoHide
= (HWND
) SHAppBarMessage (ABM_GETAUTOHIDEBAR
, &abd
);
624 if (hwndAutoHide
!= NULL
)
626 winDebug ("winAdjustForAutoHide - Found RIGHT auto-hide taskbar\n");
627 prcWorkArea
->right
-= 1;
630 winDebug ("winAdjustForAutoHide - Adjusted WorkArea: %d %d %d %d\n",
631 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
632 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
635 /* Obtain the task bar window dimensions */
636 abd
.hWnd
= hwndAutoHide
;
637 hwndAutoHide
= (HWND
) SHAppBarMessage (ABM_GETTASKBARPOS
, &abd
);
638 winDebug ("hwndAutoHide %08x abd.hWnd %08x %d %d %d %d\n",
639 hwndAutoHide
, abd
.hWnd
,
640 abd
.rc
.top
, abd
.rc
.left
, abd
.rc
.bottom
, abd
.rc
.right
);