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 * Local function prototypes
42 winGetWorkArea(RECT
* prcWorkArea
, winScreenInfo
* pScreenInfo
);
45 winAdjustForAutoHide(RECT
* prcWorkArea
, winScreenInfo
* pScreenInfo
);
48 * Create a full screen window
52 winCreateBoundingWindowFullScreen(ScreenPtr pScreen
)
54 winScreenPriv(pScreen
);
55 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
56 int iX
= pScreenInfo
->dwInitialX
;
57 int iY
= pScreenInfo
->dwInitialY
;
58 int iWidth
= pScreenInfo
->dwWidth
;
59 int iHeight
= pScreenInfo
->dwHeight
;
60 HWND
*phwnd
= &pScreenPriv
->hwndScreen
;
65 winDebug("winCreateBoundingWindowFullScreen\n");
68 /* Setup our window class */
69 wc
.cbSize
= sizeof(WNDCLASSEX
);
70 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
71 wc
.lpfnWndProc
= winWindowProc
;
74 wc
.hInstance
= g_hInstance
;
76 (HICON
) LoadImage(g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
), IMAGE_ICON
,
77 GetSystemMetrics(SM_CXICON
),
78 GetSystemMetrics(SM_CYICON
), 0);
81 wc
.lpszMenuName
= NULL
;
82 wc
.lpszClassName
= WINDOW_CLASS
;
84 (HICON
) LoadImage(g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
), IMAGE_ICON
,
85 GetSystemMetrics(SM_CXSMICON
),
86 GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTSIZE
);
89 /* Set display and screen-specific tooltip text */
90 if (g_pszQueryHost
!= NULL
)
94 g_pszQueryHost
, display
, (int) pScreenInfo
->dwScreen
);
98 WINDOW_TITLE
, display
, (int) pScreenInfo
->dwScreen
);
100 /* Create the window */
101 *phwnd
= CreateWindowExA(0, /* Extended styles */
102 WINDOW_CLASS
, /* Class name */
103 szTitle
, /* Window name */
104 WS_POPUP
, 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
) {
115 #ifdef XWIN_NATIVEGDI
116 case WIN_SERVER_SHADOW_GDI
:
117 /* Show the window */
118 ShowWindow(*phwnd
, SW_SHOWMAXIMIZED
);
123 /* Hide the window */
124 ShowWindow(*phwnd
, SW_SHOWNORMAL
);
128 /* Send first paint message */
129 UpdateWindow(*phwnd
);
131 /* Attempt to bring our window to the top of the display */
132 BringWindowToTop(*phwnd
);
138 * Create our primary Windows display window
142 winCreateBoundingWindowWindowed(ScreenPtr pScreen
)
144 winScreenPriv(pScreen
);
145 winScreenInfo
*pScreenInfo
= pScreenPriv
->pScreenInfo
;
146 int iWidth
= pScreenInfo
->dwUserWidth
;
147 int iHeight
= pScreenInfo
->dwUserHeight
;
150 HWND
*phwnd
= &pScreenPriv
->hwndScreen
;
152 RECT rcClient
, rcWorkArea
;
154 BOOL fForceShowWindow
= FALSE
;
157 winDebug("winCreateBoundingWindowWindowed - User w: %d h: %d\n",
158 (int) pScreenInfo
->dwUserWidth
, (int) pScreenInfo
->dwUserHeight
);
159 winDebug("winCreateBoundingWindowWindowed - Current w: %d h: %d\n",
160 (int) pScreenInfo
->dwWidth
, (int) pScreenInfo
->dwHeight
);
162 /* Set the common window style flags */
163 dwWindowStyle
= WS_OVERLAPPED
| WS_SYSMENU
| WS_MINIMIZEBOX
;
165 /* Decorated or undecorated window */
166 if (pScreenInfo
->fDecoration
167 #ifdef XWIN_MULTIWINDOWEXTWM
168 && !pScreenInfo
->fMWExtWM
170 && !pScreenInfo
->fRootless
171 #ifdef XWIN_MULTIWINDOW
172 && !pScreenInfo
->fMultiWindow
175 /* Try to handle startup via run.exe. run.exe instructs Windows to
176 * hide all created windows. Detect this case and make sure the
177 * window is shown nevertheless */
178 STARTUPINFO startupInfo
;
180 GetStartupInfo(&startupInfo
);
181 if (startupInfo
.dwFlags
& STARTF_USESHOWWINDOW
&&
182 startupInfo
.wShowWindow
== SW_HIDE
) {
183 fForceShowWindow
= TRUE
;
185 dwWindowStyle
|= WS_CAPTION
;
186 if (pScreenInfo
->iResizeMode
!= notAllowed
)
187 dwWindowStyle
|= WS_THICKFRAME
| WS_MAXIMIZEBOX
;
190 dwWindowStyle
|= WS_POPUP
;
192 /* Setup our window class */
193 wc
.cbSize
= sizeof(WNDCLASSEX
);
194 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
195 wc
.lpfnWndProc
= winWindowProc
;
198 wc
.hInstance
= g_hInstance
;
200 (HICON
) LoadImage(g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
), IMAGE_ICON
,
201 GetSystemMetrics(SM_CXICON
),
202 GetSystemMetrics(SM_CYICON
), 0);
204 wc
.hbrBackground
= (HBRUSH
) GetStockObject(WHITE_BRUSH
);
205 wc
.lpszMenuName
= NULL
;
206 wc
.lpszClassName
= WINDOW_CLASS
;
208 (HICON
) LoadImage(g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
), IMAGE_ICON
,
209 GetSystemMetrics(SM_CXSMICON
),
210 GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTSIZE
);
211 RegisterClassEx(&wc
);
213 /* Get size of work area */
214 winGetWorkArea(&rcWorkArea
, pScreenInfo
);
216 /* Adjust for auto-hide taskbars */
217 winAdjustForAutoHide(&rcWorkArea
, pScreenInfo
);
219 /* Did the user specify a position? */
220 if (pScreenInfo
->fUserGavePosition
) {
221 iPosX
= pScreenInfo
->dwInitialX
;
222 iPosY
= pScreenInfo
->dwInitialY
;
225 iPosX
= rcWorkArea
.left
;
226 iPosY
= rcWorkArea
.top
;
229 /* Clean up the scrollbars flag, if necessary */
230 if ((!pScreenInfo
->fDecoration
231 #ifdef XWIN_MULTIWINDOWEXTWM
232 || pScreenInfo
->fMWExtWM
234 || pScreenInfo
->fRootless
235 #ifdef XWIN_MULTIWINDOW
236 || pScreenInfo
->fMultiWindow
239 && (pScreenInfo
->iResizeMode
== resizeWithScrollbars
)) {
240 /* We cannot have scrollbars if we do not have a window border */
241 pScreenInfo
->iResizeMode
= notAllowed
;
244 /* Did the user specify a height and width? */
245 if (pScreenInfo
->fUserGaveHeightAndWidth
) {
246 /* User gave a desired height and width, try to accomodate */
248 winDebug("winCreateBoundingWindowWindowed - User gave height "
252 /* Adjust the window width and height for borders and title bar */
253 if (pScreenInfo
->fDecoration
254 #ifdef XWIN_MULTIWINDOWEXTWM
255 && !pScreenInfo
->fMWExtWM
257 && !pScreenInfo
->fRootless
258 #ifdef XWIN_MULTIWINDOW
259 && !pScreenInfo
->fMultiWindow
264 ("winCreateBoundingWindowWindowed - Window has decoration\n");
267 /* Are we resizable */
268 if (pScreenInfo
->iResizeMode
!= notAllowed
) {
271 ("winCreateBoundingWindowWindowed - Window is resizable\n");
274 iWidth
+= 2 * GetSystemMetrics(SM_CXSIZEFRAME
);
275 iHeight
+= 2 * GetSystemMetrics(SM_CYSIZEFRAME
)
276 + GetSystemMetrics(SM_CYCAPTION
);
281 ("winCreateBoundingWindowWindowed - Window is not resizable\n");
284 iWidth
+= 2 * GetSystemMetrics(SM_CXFIXEDFRAME
);
285 iHeight
+= 2 * GetSystemMetrics(SM_CYFIXEDFRAME
)
286 + GetSystemMetrics(SM_CYCAPTION
);
291 /* By default, we are creating a window that is as large as possible */
293 winDebug("winCreateBoundingWindowWindowed - User did not give "
294 "height and width\n");
296 /* Defaults are wrong if we have multiple monitors */
297 if (pScreenInfo
->fMultipleMonitors
) {
298 iWidth
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
299 iHeight
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
303 /* Make sure window is no bigger than work area */
305 #ifdef XWIN_MULTIWINDOWEXTWM
306 && !pScreenInfo
->fMWExtWM
308 #ifdef XWIN_MULTIWINDOW
309 && !pScreenInfo
->fMultiWindow
312 /* Trim window width to fit work area */
313 if (iWidth
> (rcWorkArea
.right
- rcWorkArea
.left
))
314 iWidth
= rcWorkArea
.right
- rcWorkArea
.left
;
316 /* Trim window height to fit work area */
317 if (iHeight
>= (rcWorkArea
.bottom
- rcWorkArea
.top
))
318 iHeight
= rcWorkArea
.bottom
- rcWorkArea
.top
;
321 winDebug("winCreateBoundingWindowWindowed - Adjusted width: %d "
322 "height: %d\n", iWidth
, iHeight
);
326 /* Set display and screen-specific tooltip text */
327 if (g_pszQueryHost
!= NULL
)
331 g_pszQueryHost
, display
, (int) pScreenInfo
->dwScreen
);
335 WINDOW_TITLE
, display
, (int) pScreenInfo
->dwScreen
);
337 /* Create the window */
338 *phwnd
= CreateWindowExA(0, /* Extended styles */
339 WINDOW_CLASS
, /* Class name */
340 szTitle
, /* Window name */
341 dwWindowStyle
, iPosX
, /* Horizontal position */
342 iPosY
, /* Vertical position */
343 iWidth
, /* Right edge */
344 iHeight
, /* Bottom edge */
345 (HWND
) NULL
, /* No parent or owner window */
346 (HMENU
) NULL
, /* No menu */
347 GetModuleHandle(NULL
), /* Instance handle */
348 pScreenPriv
); /* ScreenPrivates */
349 if (*phwnd
== NULL
) {
350 ErrorF("winCreateBoundingWindowWindowed - CreateWindowEx () failed\n");
355 winDebug("winCreateBoundingWindowWindowed - CreateWindowEx () returned\n");
358 if (fForceShowWindow
) {
360 ("winCreateBoundingWindowWindowed - Setting normal windowstyle\n");
361 ShowWindow(*phwnd
, SW_SHOW
);
364 /* Get the client area coordinates */
365 if (!GetClientRect(*phwnd
, &rcClient
)) {
366 ErrorF("winCreateBoundingWindowWindowed - GetClientRect () "
371 winDebug("winCreateBoundingWindowWindowed - WindowClient "
372 "w %ld h %ld r %ld l %ld b %ld t %ld\n",
373 rcClient
.right
- rcClient
.left
,
374 rcClient
.bottom
- rcClient
.top
,
375 rcClient
.right
, rcClient
.left
, rcClient
.bottom
, rcClient
.top
);
377 /* We adjust the visual size if the user did not specify it */
379 ((pScreenInfo
->iResizeMode
== resizeWithScrollbars
) &&
380 pScreenInfo
->fUserGaveHeightAndWidth
)) {
382 * User did not give a height and width with scrollbars enabled,
383 * so we will resize the underlying visual to be as large as
384 * the initial view port (page size). This way scrollbars will
385 * not appear until the user shrinks the window, if they ever do.
387 * NOTE: We have to store the viewport size here because
388 * the user may have an autohide taskbar, which would
389 * cause the viewport size to be one less in one dimension
390 * than the viewport size that we calculated by subtracting
391 * the size of the borders and caption.
393 pScreenInfo
->dwWidth
= rcClient
.right
- rcClient
.left
;
394 pScreenInfo
->dwHeight
= rcClient
.bottom
- rcClient
.top
;
399 * NOTE: For the uninitiated, the page size is the number of pixels
400 * that we can display in the x or y direction at a time and the
401 * range is the total number of pixels in the x or y direction that we
402 * have available to display. In other words, the page size is the
403 * size of the window area minus the space the caption, borders, and
404 * scrollbars (if any) occupy, and the range is the size of the
405 * underlying X visual. Notice that, contrary to what some of the
406 * MSDN Library arcticles lead you to believe, the windows
407 * ``client area'' size does not include the scrollbars. In other words,
408 * the whole client area size that is reported to you is drawable by
409 * you; you do not have to subtract the size of the scrollbars from
410 * the client area size, and if you did it would result in the size
411 * of the scrollbars being double counted.
414 /* Setup scrollbar page and range, if scrollbars are enabled */
415 if (pScreenInfo
->fScrollbars
) {
418 /* Initialize the scrollbar info structure */
419 si
.cbSize
= sizeof(si
);
420 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
423 /* Setup the width range and page size */
424 si
.nMax
= pScreenInfo
->dwWidth
- 1;
425 si
.nPage
= rcClient
.right
- rcClient
.left
;
426 winDebug("winCreateBoundingWindowWindowed - HORZ nMax: %d nPage :%d\n",
428 SetScrollInfo(*phwnd
, SB_HORZ
, &si
, TRUE
);
430 /* Setup the height range and page size */
431 si
.nMax
= pScreenInfo
->dwHeight
- 1;
432 si
.nPage
= rcClient
.bottom
- rcClient
.top
;
433 winDebug("winCreateBoundingWindowWindowed - VERT nMax: %d nPage :%d\n",
435 SetScrollInfo(*phwnd
, SB_VERT
, &si
, TRUE
);
439 /* Show the window */
441 #ifdef XWIN_MULTIWINDOWEXTWM
442 || pScreenInfo
->fMWExtWM
444 #ifdef XWIN_MULTIWINDOW
445 || pScreenInfo
->fMultiWindow
448 #if defined(XWIN_MULTIWINDOW) || defined(XWIN_MULTIWINDOWEXTWM)
449 pScreenPriv
->fRootWindowShown
= FALSE
;
451 ShowWindow(*phwnd
, SW_HIDE
);
454 ShowWindow(*phwnd
, SW_SHOWNORMAL
);
455 if (!UpdateWindow(*phwnd
)) {
456 ErrorF("winCreateBoundingWindowWindowed - UpdateWindow () failed\n");
460 /* Attempt to bring our window to the top of the display */
462 #ifdef XWIN_MULTIWINDOWEXTWM
463 && !pScreenInfo
->fMWExtWM
465 && !pScreenInfo
->fRootless
466 #ifdef XWIN_MULTIWINDOW
467 && !pScreenInfo
->fMultiWindow
470 if (!BringWindowToTop(*phwnd
)) {
471 ErrorF("winCreateBoundingWindowWindowed - BringWindowToTop () "
477 #ifdef XWIN_NATIVEGDI
478 /* Paint window background blue */
479 if (pScreenInfo
->dwEngine
== WIN_SERVER_NATIVE_GDI
)
480 winPaintBackground(*phwnd
, RGB(0x00, 0x00, 0xFF));
483 winDebug("winCreateBoundingWindowWindowed - Returning\n");
489 * Find the work area of all attached monitors
493 winGetWorkArea(RECT
* prcWorkArea
, winScreenInfo
* pScreenInfo
)
495 int iPrimaryWidth
, iPrimaryHeight
;
498 int iPrimaryNonWorkAreaWidth
, iPrimaryNonWorkAreaHeight
;
500 /* Use GetMonitorInfo to get work area for monitor */
501 if (!pScreenInfo
->fMultipleMonitors
) {
504 mi
.cbSize
= sizeof(MONITORINFO
);
505 if (GetMonitorInfo(pScreenInfo
->hMonitor
, &mi
)) {
506 *prcWorkArea
= mi
.rcWork
;
508 winDebug("winGetWorkArea - Monitor %d WorkArea: %d %d %d %d\n",
509 pScreenInfo
->iMonitor
,
510 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
511 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
514 ErrorF("winGetWorkArea - GetMonitorInfo() failed for monitor %d\n",
515 pScreenInfo
->iMonitor
);
518 /* Bail out here if we aren't using multiple monitors */
522 /* SPI_GETWORKAREA only gets the work area of the primary screen. */
523 SystemParametersInfo(SPI_GETWORKAREA
, 0, prcWorkArea
, 0);
525 winDebug("winGetWorkArea - Primary Monitor WorkArea: %d %d %d %d\n",
526 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
527 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
529 /* Get size of full virtual screen */
530 iWidth
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
531 iHeight
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
533 winDebug("winGetWorkArea - Virtual screen is %d x %d\n", iWidth
, iHeight
);
535 /* Get origin of full virtual screen */
536 iLeft
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
537 iTop
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
539 winDebug("winGetWorkArea - Virtual screen origin is %d, %d\n", iLeft
, iTop
);
541 /* Get size of primary screen */
542 iPrimaryWidth
= GetSystemMetrics(SM_CXSCREEN
);
543 iPrimaryHeight
= GetSystemMetrics(SM_CYSCREEN
);
545 winDebug("winGetWorkArea - Primary screen is %d x %d\n",
546 iPrimaryWidth
, iPrimaryHeight
);
548 /* Work out how much of the primary screen we aren't using */
549 iPrimaryNonWorkAreaWidth
= iPrimaryWidth
- (prcWorkArea
->right
-
551 iPrimaryNonWorkAreaHeight
= iPrimaryHeight
- (prcWorkArea
->bottom
554 /* Update the rectangle to include all monitors */
556 prcWorkArea
->left
= iLeft
;
559 prcWorkArea
->top
= iTop
;
561 prcWorkArea
->right
= prcWorkArea
->left
+ iWidth
- iPrimaryNonWorkAreaWidth
;
562 prcWorkArea
->bottom
= prcWorkArea
->top
+ iHeight
-
563 iPrimaryNonWorkAreaHeight
;
565 winDebug("winGetWorkArea - Adjusted WorkArea for multiple "
566 "monitors: %d %d %d %d\n",
567 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
568 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
574 winTaskbarOnScreenEdge(unsigned int uEdge
, winScreenInfo
* pScreenInfo
)
579 ZeroMemory(&abd
, sizeof(abd
));
580 abd
.cbSize
= sizeof(abd
);
583 hwndAutoHide
= (HWND
) SHAppBarMessage(ABM_GETAUTOHIDEBAR
, &abd
);
584 if (hwndAutoHide
!= NULL
) {
586 Found an autohide taskbar on that edge, but is it on the
587 same monitor as the screen window?
589 if (pScreenInfo
->fMultipleMonitors
||
590 (MonitorFromWindow(hwndAutoHide
, MONITOR_DEFAULTTONULL
) ==
591 pScreenInfo
->hMonitor
))
598 * Adjust the client area so that any auto-hide toolbars
599 * will work correctly.
603 winAdjustForAutoHide(RECT
* prcWorkArea
, winScreenInfo
* pScreenInfo
)
607 winDebug("winAdjustForAutoHide - Original WorkArea: %d %d %d %d\n",
608 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
609 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);
611 /* Find out if the Windows taskbar is set to auto-hide */
612 ZeroMemory(&abd
, sizeof(abd
));
613 abd
.cbSize
= sizeof(abd
);
614 if (SHAppBarMessage(ABM_GETSTATE
, &abd
) & ABS_AUTOHIDE
)
615 winDebug("winAdjustForAutoHide - Taskbar is auto hide\n");
618 Despite the forgoing, we are checking for any AppBar
619 hiding along a monitor edge, not just the Windows TaskBar.
622 /* Look for a TOP auto-hide taskbar */
623 if (winTaskbarOnScreenEdge(ABE_TOP
, pScreenInfo
)) {
624 winDebug("winAdjustForAutoHide - Found TOP auto-hide taskbar\n");
625 prcWorkArea
->top
+= 1;
628 /* Look for a LEFT auto-hide taskbar */
629 if (winTaskbarOnScreenEdge(ABE_LEFT
, pScreenInfo
)) {
630 winDebug("winAdjustForAutoHide - Found LEFT auto-hide taskbar\n");
631 prcWorkArea
->left
+= 1;
634 /* Look for a BOTTOM auto-hide taskbar */
635 if (winTaskbarOnScreenEdge(ABE_BOTTOM
, pScreenInfo
)) {
636 winDebug("winAdjustForAutoHide - Found BOTTOM auto-hide taskbar\n");
637 prcWorkArea
->bottom
-= 1;
640 /* Look for a RIGHT auto-hide taskbar */
641 if (winTaskbarOnScreenEdge(ABE_RIGHT
, pScreenInfo
)) {
642 winDebug("winAdjustForAutoHide - Found RIGHT auto-hide taskbar\n");
643 prcWorkArea
->right
-= 1;
646 winDebug("winAdjustForAutoHide - Adjusted WorkArea: %d %d %d %d\n",
647 (int) prcWorkArea
->top
, (int) prcWorkArea
->left
,
648 (int) prcWorkArea
->bottom
, (int) prcWorkArea
->right
);