2 *Copyright (C) 2003-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
29 * Earle F. Philhower III
32 #ifdef HAVE_XWIN_CONFIG_H
33 #include <xwin-config.h>
40 * References to external globals
44 extern Bool g_fClipboardStarted
;
47 * Local function prototypes
50 static INT_PTR CALLBACK
51 winExitDlgProc(HWND hDialog
, UINT message
, WPARAM wParam
, LPARAM lParam
);
53 static INT_PTR CALLBACK
54 winChangeDepthDlgProc(HWND hDialog
, UINT message
, WPARAM wParam
, LPARAM lParam
);
56 static INT_PTR CALLBACK
57 winAboutDlgProc(HWND hDialog
, UINT message
, WPARAM wParam
, LPARAM lParam
);
60 winDrawURLWindow(LPARAM lParam
);
62 static LRESULT CALLBACK
63 winURLWndProc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
);
66 winOverrideURLButton(HWND hdlg
, int id
);
69 winUnoverrideURLButton(HWND hdlg
, int id
);
72 * Owner-draw a button as a URL
76 winDrawURLWindow(LPARAM lParam
)
84 draw
= (DRAWITEMSTRUCT
*) lParam
;
85 GetWindowText(draw
->hwndItem
, str
, sizeof(str
));
87 GetClientRect(draw
->hwndItem
, &rect
);
89 /* Color the button depending upon its state */
90 if (draw
->itemState
& ODS_SELECTED
)
91 crText
= RGB(128 + 64, 0, 0);
92 else if (draw
->itemState
& ODS_FOCUS
)
93 crText
= RGB(0, 128 + 64, 0);
95 crText
= RGB(0, 0, 128 + 64);
96 SetTextColor(draw
->hDC
, crText
);
98 /* Create font 8 high, standard dialog font */
99 font
= CreateFont(-8, 0, 0, 0, FW_DONTCARE
, FALSE
, FALSE
, FALSE
,
100 0, 0, 0, 0, 0, "MS Sans Serif");
102 ErrorF("winDrawURLWindow: Unable to create URL font, bailing.\n");
106 SetBkMode(draw
->hDC
, OPAQUE
);
107 SelectObject(draw
->hDC
, font
);
108 DrawText(draw
->hDC
, str
, strlen(str
), &rect
, DT_LEFT
| DT_VCENTER
);
109 /* Delete the created font, replace it with stock font */
110 DeleteObject(SelectObject(draw
->hDC
, GetStockObject(ANSI_VAR_FONT
)));
114 * WndProc for overridden buttons
117 static LRESULT CALLBACK
118 winURLWndProc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
120 WNDPROC origCB
= NULL
;
123 /* If it's a SetCursor message, tell it to the hand */
124 if (msg
== WM_SETCURSOR
) {
125 cursor
= LoadCursor(NULL
, IDC_HAND
);
130 origCB
= (WNDPROC
) GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
131 /* Otherwise fall through to original WndProc */
133 return CallWindowProc(origCB
, hwnd
, msg
, wParam
, lParam
);
139 * Register and unregister the custom WndProc
143 winOverrideURLButton(HWND hwnd
, int id
)
147 origCB
= (WNDPROC
) SetWindowLongPtr(GetDlgItem(hwnd
, id
),
148 GWLP_WNDPROC
, (LONG_PTR
) winURLWndProc
);
149 SetWindowLongPtr(GetDlgItem(hwnd
, id
), GWLP_USERDATA
, (LONG_PTR
) origCB
);
153 winUnoverrideURLButton(HWND hwnd
, int id
)
157 origCB
= (WNDPROC
) SetWindowLongPtr(GetDlgItem(hwnd
, id
), GWLP_USERDATA
, 0);
159 SetWindowLongPtr(GetDlgItem(hwnd
, id
), GWLP_WNDPROC
, (LONG_PTR
) origCB
);
163 * Center a dialog window in the desktop window
164 * and set small and large icons to X icons.
168 winInitDialog(HWND hwndDlg
)
171 RECT rc
, rcDlg
, rcDesk
;
172 HICON hIcon
, hIconSmall
;
174 hwndDesk
= GetParent(hwndDlg
);
175 if (!hwndDesk
|| IsIconic(hwndDesk
))
176 hwndDesk
= GetDesktopWindow();
178 /* Remove minimize and maximize buttons */
179 SetWindowLongPtr(hwndDlg
, GWL_STYLE
, GetWindowLongPtr(hwndDlg
, GWL_STYLE
)
180 & ~(WS_MAXIMIZEBOX
| WS_MINIMIZEBOX
));
182 /* Set Window not to show in the task bar */
183 SetWindowLongPtr(hwndDlg
, GWL_EXSTYLE
,
184 GetWindowLongPtr(hwndDlg
, GWL_EXSTYLE
) & ~WS_EX_APPWINDOW
);
186 /* Center dialog window in the screen. Not done for multi-monitor systems, where
187 * it is likely to end up split across the screens. In that case, it appears
188 * near the Tray icon.
190 if (GetSystemMetrics(SM_CMONITORS
) > 1) {
191 /* Still need to refresh the frame change. */
192 SetWindowPos(hwndDlg
, HWND_TOPMOST
, 0, 0, 0, 0,
193 SWP_NOMOVE
| SWP_NOSIZE
| SWP_FRAMECHANGED
);
196 GetWindowRect(hwndDesk
, &rcDesk
);
197 GetWindowRect(hwndDlg
, &rcDlg
);
198 CopyRect(&rc
, &rcDesk
);
200 OffsetRect(&rcDlg
, -rcDlg
.left
, -rcDlg
.top
);
201 OffsetRect(&rc
, -rc
.left
, -rc
.top
);
202 OffsetRect(&rc
, -rcDlg
.right
, -rcDlg
.bottom
);
204 SetWindowPos(hwndDlg
,
206 rcDesk
.left
+ (rc
.right
/ 2),
207 rcDesk
.top
+ (rc
.bottom
/ 2),
208 0, 0, SWP_NOSIZE
| SWP_FRAMECHANGED
);
211 #ifdef XWIN_MULTIWINDOW
216 hIcon
= LoadIcon(g_hInstance
, MAKEINTRESOURCE(IDI_XWIN
));
218 #ifdef XWIN_MULTIWINDOW
220 hIconSmall
= g_hSmallIconX
;
223 hIconSmall
= LoadImage(g_hInstance
,
224 MAKEINTRESOURCE(IDI_XWIN
), IMAGE_ICON
,
225 GetSystemMetrics(SM_CXSMICON
),
226 GetSystemMetrics(SM_CYSMICON
), LR_SHARED
);
228 PostMessage(hwndDlg
, WM_SETICON
, ICON_BIG
, (LPARAM
) hIcon
);
229 PostMessage(hwndDlg
, WM_SETICON
, ICON_SMALL
, (LPARAM
) hIconSmall
);
233 * Display the Exit dialog box
237 winDisplayExitDialog(winPrivScreenPtr pScreenPriv
)
242 /* Count up running clients (clients[0] is serverClient) */
243 for (i
= 1; i
< currentMaxClients
; i
++)
244 if (clients
[i
] != NullClient
)
246 #if defined(XWIN_MULTIWINDOW)
247 /* Count down server internal clients */
248 if (pScreenPriv
->pScreenInfo
->fMultiWindow
)
249 liveClients
-= 2; /* multiwindow window manager & XMsgProc */
251 #if defined(XWIN_CLIPBOARD)
252 if (g_fClipboardStarted
)
253 liveClients
--; /* clipboard manager */
256 /* A user reported that this sometimes drops below zero. just eye-candy. */
260 /* Don't show the exit confirmation dialog if SilentExit & no clients,
261 or ForceExit, is enabled */
262 if ((pref
.fSilentExit
&& liveClients
<= 0) || pref
.fForceExit
) {
263 if (g_hDlgExit
!= NULL
) {
264 DestroyWindow(g_hDlgExit
);
267 PostMessage(pScreenPriv
->hwndScreen
, WM_GIVEUP
, 0, 0);
271 pScreenPriv
->iConnectedClients
= liveClients
;
273 /* Check if dialog already exists */
274 if (g_hDlgExit
!= NULL
) {
275 /* Dialog box already exists, display it */
276 ShowWindow(g_hDlgExit
, SW_SHOWDEFAULT
);
278 /* User has lost the dialog. Show them where it is. */
279 SetForegroundWindow(g_hDlgExit
);
284 /* Create dialog box */
285 g_hDlgExit
= CreateDialogParam(g_hInstance
,
287 pScreenPriv
->hwndScreen
,
288 winExitDlgProc
, (LPARAM
) pScreenPriv
);
290 /* Show the dialog box */
291 ShowWindow(g_hDlgExit
, SW_SHOW
);
293 /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
294 SetForegroundWindow(g_hDlgExit
);
296 /* Set focus to the Cancel button */
297 PostMessage(g_hDlgExit
, WM_NEXTDLGCTL
,
298 (WPARAM
) GetDlgItem(g_hDlgExit
, IDCANCEL
), TRUE
);
301 #define CONNECTED_CLIENTS_FORMAT "There %s currently %d client%s connected."
304 * Exit dialog window procedure
307 static INT_PTR CALLBACK
308 winExitDlgProc(HWND hDialog
, UINT message
, WPARAM wParam
, LPARAM lParam
)
310 static winPrivScreenPtr s_pScreenPriv
= NULL
;
312 /* Branch on message type */
316 char *pszConnectedClients
;
318 /* Store pointers to private structures for future use */
319 s_pScreenPriv
= (winPrivScreenPtr
) lParam
;
321 winInitDialog(hDialog
);
323 /* Format the connected clients string */
324 if (asprintf(&pszConnectedClients
, CONNECTED_CLIENTS_FORMAT
,
325 (s_pScreenPriv
->iConnectedClients
== 1) ? "is" : "are",
326 s_pScreenPriv
->iConnectedClients
,
327 (s_pScreenPriv
->iConnectedClients
== 1) ? "" : "s") == -1)
330 /* Set the number of connected clients */
331 SetWindowText(GetDlgItem(hDialog
, IDC_CLIENTS_CONNECTED
),
332 pszConnectedClients
);
333 free(pszConnectedClients
);
338 switch (LOWORD(wParam
)) {
340 /* Send message to call the GiveUp function */
341 PostMessage(s_pScreenPriv
->hwndScreen
, WM_GIVEUP
, 0, 0);
342 DestroyWindow(g_hDlgExit
);
345 /* Fix to make sure keyboard focus isn't trapped */
346 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
350 DestroyWindow(g_hDlgExit
);
353 /* Fix to make sure keyboard focus isn't trapped */
354 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
361 /* Show the cursor if it is hidden */
362 if (g_fSoftwareCursor
&& !g_fCursor
) {
369 DestroyWindow(g_hDlgExit
);
372 /* Fix to make sure keyboard focus isn't trapped */
373 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
381 * Display the Depth Change dialog box
385 winDisplayDepthChangeDialog(winPrivScreenPtr pScreenPriv
)
387 /* Check if dialog already exists */
388 if (g_hDlgDepthChange
!= NULL
) {
389 /* Dialog box already exists, display it */
390 ShowWindow(g_hDlgDepthChange
, SW_SHOWDEFAULT
);
392 /* User has lost the dialog. Show them where it is. */
393 SetForegroundWindow(g_hDlgDepthChange
);
399 * Display a notification to the user that the visual
400 * will not be displayed until the Windows display depth
401 * is restored to the original value.
403 g_hDlgDepthChange
= CreateDialogParam(g_hInstance
,
405 pScreenPriv
->hwndScreen
,
406 winChangeDepthDlgProc
,
407 (LPARAM
) pScreenPriv
);
408 /* Show the dialog box */
409 ShowWindow(g_hDlgDepthChange
, SW_SHOW
);
411 if (!g_hDlgDepthChange
)
412 ErrorF("winDisplayDepthChangeDialog - GetLastError: %d\n",
413 (int) GetLastError());
415 /* Minimize the display window */
416 ShowWindow(pScreenPriv
->hwndScreen
, SW_MINIMIZE
);
420 * Process messages for the dialog that is displayed for
421 * disruptive screen depth changes.
424 static INT_PTR CALLBACK
425 winChangeDepthDlgProc(HWND hwndDialog
, UINT message
,
426 WPARAM wParam
, LPARAM lParam
)
428 static winPrivScreenPtr s_pScreenPriv
= NULL
;
429 static winScreenInfo
*s_pScreenInfo
= NULL
;
432 winDebug("winChangeDepthDlgProc\n");
435 /* Branch on message type */
439 winDebug("winChangeDepthDlgProc - WM_INITDIALOG\n");
442 /* Store pointers to private structures for future use */
443 s_pScreenPriv
= (winPrivScreenPtr
) lParam
;
444 s_pScreenInfo
= s_pScreenPriv
->pScreenInfo
;
447 winDebug("winChangeDepthDlgProc - WM_INITDIALOG - s_pScreenPriv: %08x, "
448 "s_pScreenInfo: %08x\n",
449 s_pScreenPriv
, s_pScreenInfo
);
453 winDebug("winChangeDepthDlgProc - WM_INITDIALOG - orig bpp: %d, "
455 s_pScreenInfo
->dwBPP
,
456 GetDeviceCaps(s_pScreenPriv
->hdcScreen
, BITSPIXEL
));
459 winInitDialog(hwndDialog
);
463 case WM_DISPLAYCHANGE
:
465 winDebug("winChangeDepthDlgProc - WM_DISPLAYCHANGE - orig bpp: %d, "
467 s_pScreenInfo
->dwBPP
,
468 GetDeviceCaps(s_pScreenPriv
->hdcScreen
, BITSPIXEL
));
471 /* Dismiss the dialog if the display returns to the original depth */
472 if (GetDeviceCaps(s_pScreenPriv
->hdcScreen
, BITSPIXEL
) ==
473 s_pScreenInfo
->dwBPP
) {
474 ErrorF("winChangeDelthDlgProc - wParam == s_pScreenInfo->dwBPP\n");
476 /* Depth has been restored, dismiss dialog */
477 DestroyWindow(g_hDlgDepthChange
);
478 g_hDlgDepthChange
= NULL
;
480 /* Flag that we have a valid screen depth */
481 s_pScreenPriv
->fBadDepth
= FALSE
;
486 switch (LOWORD(wParam
)) {
489 winDebug("winChangeDepthDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
492 * User dismissed the dialog, hide it until the
493 * display mode is restored.
495 ShowWindow(g_hDlgDepthChange
, SW_HIDE
);
501 winDebug("winChangeDepthDlgProc - WM_CLOSE\n");
503 DestroyWindow(g_hDlgAbout
);
506 /* Fix to make sure keyboard focus isn't trapped */
507 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
515 * Display the About dialog box
519 winDisplayAboutDialog(winPrivScreenPtr pScreenPriv
)
521 /* Check if dialog already exists */
522 if (g_hDlgAbout
!= NULL
) {
523 /* Dialog box already exists, display it */
524 ShowWindow(g_hDlgAbout
, SW_SHOWDEFAULT
);
526 /* User has lost the dialog. Show them where it is. */
527 SetForegroundWindow(g_hDlgAbout
);
533 * Display the about box
535 g_hDlgAbout
= CreateDialogParam(g_hInstance
,
537 pScreenPriv
->hwndScreen
,
538 winAboutDlgProc
, (LPARAM
) pScreenPriv
);
540 /* Show the dialog box */
541 ShowWindow(g_hDlgAbout
, SW_SHOW
);
543 /* Needed to get keyboard controls (tab, arrows, enter, esc) to work */
544 SetForegroundWindow(g_hDlgAbout
);
546 /* Set focus to the OK button */
547 PostMessage(g_hDlgAbout
, WM_NEXTDLGCTL
,
548 (WPARAM
) GetDlgItem(g_hDlgAbout
, IDOK
), TRUE
);
552 * Process messages for the about dialog.
555 static INT_PTR CALLBACK
556 winAboutDlgProc(HWND hwndDialog
, UINT message
, WPARAM wParam
, LPARAM lParam
)
558 static winPrivScreenPtr s_pScreenPriv
= NULL
;
561 winDebug("winAboutDlgProc\n");
564 /* Branch on message type */
568 winDebug("winAboutDlgProc - WM_INITDIALOG\n");
571 /* Store pointer to private structure for future use */
572 s_pScreenPriv
= (winPrivScreenPtr
) lParam
;
574 winInitDialog(hwndDialog
);
576 /* Override the URL buttons */
577 winOverrideURLButton(hwndDialog
, ID_ABOUT_CHANGELOG
);
578 winOverrideURLButton(hwndDialog
, ID_ABOUT_WEBSITE
);
579 winOverrideURLButton(hwndDialog
, ID_ABOUT_UG
);
580 winOverrideURLButton(hwndDialog
, ID_ABOUT_FAQ
);
585 /* Draw the URL buttons as needed */
586 winDrawURLWindow(lParam
);
591 /* Show the cursor if it is hidden */
592 if (g_fSoftwareCursor
&& !g_fCursor
) {
599 switch (LOWORD(wParam
)) {
602 winDebug("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
604 DestroyWindow(g_hDlgAbout
);
607 /* Fix to make sure keyboard focus isn't trapped */
608 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
610 /* Restore window procedures for URL buttons */
611 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_CHANGELOG
);
612 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_WEBSITE
);
613 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_UG
);
614 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_FAQ
);
618 case ID_ABOUT_CHANGELOG
:
622 const char *pszWinPath
= "http://x.cygwin.com/"
623 "devel/server/changelog.html";
625 iReturn
= (INT_PTR
) ShellExecute(NULL
,
627 pszWinPath
, NULL
, NULL
, SW_MAXIMIZE
);
629 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_CHANGELOG - "
630 "ShellExecute failed: %d\n", (int)iReturn
);
635 case ID_ABOUT_WEBSITE
:
637 const char *pszPath
= __VENDORDWEBSUPPORT__
;
640 iReturn
= (INT_PTR
) ShellExecute(NULL
,
642 pszPath
, NULL
, NULL
, SW_MAXIMIZE
);
644 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
645 "ShellExecute failed: %d\n", (int)iReturn
);
653 const char *pszPath
= "http://x.cygwin.com/docs/ug/";
656 iReturn
= (INT_PTR
) ShellExecute(NULL
,
658 pszPath
, NULL
, NULL
, SW_MAXIMIZE
);
660 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_UG - "
661 "ShellExecute failed: %d\n", (int)iReturn
);
668 const char *pszPath
= "http://x.cygwin.com/docs/faq/";
671 iReturn
= (INT_PTR
) ShellExecute(NULL
,
673 pszPath
, NULL
, NULL
, SW_MAXIMIZE
);
675 ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_FAQ - "
676 "ShellExecute failed: %d\n", (int)iReturn
);
684 winDebug("winAboutDlgProc - WM_CLOSE\n");
686 DestroyWindow(g_hDlgAbout
);
689 /* Fix to make sure keyboard focus isn't trapped */
690 PostMessage(s_pScreenPriv
->hwndScreen
, WM_NULL
, 0, 0);
692 /* Restore window procedures for URL buttons */
693 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_CHANGELOG
);
694 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_WEBSITE
);
695 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_UG
);
696 winUnoverrideURLButton(hwndDialog
, ID_ABOUT_FAQ
);