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_WEBSITE);
582
/* Draw the URL buttons as needed */
583
winDrawURLWindow(lParam);
588
/* Show the cursor if it is hidden */
589
if (g_fSoftwareCursor && !g_fCursor) {
596
switch (LOWORD(wParam)) {
599
winDebug("winAboutDlgProc - WM_COMMAND - IDOK or IDCANCEL\n");
601
DestroyWindow(g_hDlgAbout);
604
/* Fix to make sure keyboard focus isn't trapped */
605
PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
607
/* Restore window procedures for URL buttons */
608
winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);
612
case ID_ABOUT_WEBSITE:
614
const char *pszPath = __VENDORDWEBSUPPORT__;
617
iReturn = (INT_PTR) ShellExecute(NULL,
619
pszPath, NULL, NULL, SW_MAXIMIZE);
621
ErrorF("winAboutDlgProc - WM_COMMAND - ID_ABOUT_WEBSITE - "
622
"ShellExecute failed: %d\n", (int)iReturn);
631
winDebug("winAboutDlgProc - WM_CLOSE\n");
633
DestroyWindow(g_hDlgAbout);
636
/* Fix to make sure keyboard focus isn't trapped */
637
PostMessage(s_pScreenPriv->hwndScreen, WM_NULL, 0, 0);
639
/* Restore window procedures for URL buttons */
640
winUnoverrideURLButton(hwndDialog, ID_ABOUT_WEBSITE);