- rewrite the transaction system to be based on a settings overlay,
[wine] / programs / winecfg / x11drvdlg.c
1 /*
2  * Graphics configuration code
3  *
4  * Copyright 2003 Mark Westcott
5  * Copyright 2003-2004 Mike Hearn
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #include <windef.h>
28 #include <winbase.h>
29 #include <winreg.h>
30 #include <wine/debug.h>
31
32 #include "resource.h"
33 #include "winecfg.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
36
37 #define RES_MAXLEN 5 /* the maximum number of characters in a screen dimension. 5 digits should be plenty, what kind of crazy person runs their screen >10,000 pixels across? */
38
39 int updating_ui;
40
41 void update_gui_for_desktop_mode(HWND dialog) {
42     WINE_TRACE("\n");
43
44     updating_ui = TRUE;
45     
46     /* do we have desktop mode enabled? */
47     if (exists(keypath("x11drv"), "Desktop"))
48     {
49         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_CHECKED);
50         
51         enable(IDC_DESKTOP_WIDTH);
52         enable(IDC_DESKTOP_HEIGHT);
53         enable(IDC_DESKTOP_SIZE);
54         enable(IDC_DESKTOP_BY);
55         
56         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "640");
57         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "480");   
58     }
59     else
60     {
61         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_UNCHECKED);
62         
63         disable(IDC_DESKTOP_WIDTH);
64         disable(IDC_DESKTOP_HEIGHT);
65         disable(IDC_DESKTOP_SIZE);
66         disable(IDC_DESKTOP_BY);
67
68         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "");
69         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "");
70     }
71
72     updating_ui = FALSE;
73 }
74
75 /* pokes the win32 api to setup the dialog from the config struct */
76 void initGraphDlg (HWND hDlg)
77 {
78     static char *default_desktop = "640x480";
79     char *buf;
80     char *bufindex;
81
82     update_gui_for_desktop_mode(hDlg);
83
84     updating_ui = TRUE;
85     
86     /* desktop size */
87     buf = get(keypath("x11drv"), "Desktop", default_desktop);
88     bufindex = strchr(buf, 'x');
89     if(!bufindex) /* handle invalid "Desktop" values */
90     {
91       free(buf);
92       buf = strdup(default_desktop);
93       bufindex = strchr(buf, 'x');
94     }
95     *bufindex = '\0';
96     bufindex++;
97     SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_WIDTH), buf);
98     SetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_HEIGHT), bufindex);
99     HeapFree(GetProcessHeap(), 0, buf);
100
101     SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_RESETCONTENT, 0, 0);
102     SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "8 bit");
103     SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "16 bit");
104     SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "24 bit");
105     SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_ADDSTRING, 0, (LPARAM) "32 bit"); /* is this valid? */
106
107     buf = get(keypath("x11drv"), "ScreenDepth", "24");
108     if (strcmp(buf, "8") == 0)
109         SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 0, 0);
110     else if (strcmp(buf, "16") == 0)
111         SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 1, 0);
112     else if (strcmp(buf, "24") == 0)
113         SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 2, 0);
114     else if (strcmp(buf, "32") == 0)
115         SendDlgItemMessage(hDlg, IDC_SCREEN_DEPTH, CB_SETCURSEL, 3, 0);
116     else
117         WINE_ERR("Invalid screen depth read from registry (%s)\n", buf);
118     HeapFree(GetProcessHeap(), 0, buf);
119
120     SendDlgItemMessage(hDlg, IDC_DESKTOP_WIDTH, EM_LIMITTEXT, RES_MAXLEN, 0);
121     SendDlgItemMessage(hDlg, IDC_DESKTOP_HEIGHT, EM_LIMITTEXT, RES_MAXLEN, 0);
122
123     buf = get(keypath("x11drv"), "DXGrab", "Y");
124     if (IS_OPTION_TRUE(*buf))
125         CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_CHECKED);
126     else
127         CheckDlgButton(hDlg, IDC_DX_MOUSE_GRAB, BST_UNCHECKED);
128     HeapFree(GetProcessHeap(), 0, buf);
129
130     buf = get(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
131     if (IS_OPTION_TRUE(*buf))
132         CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_CHECKED);
133     else
134         CheckDlgButton(hDlg, IDC_DOUBLE_BUFFER, BST_UNCHECKED);
135     HeapFree(GetProcessHeap(), 0, buf);
136     
137     updating_ui = FALSE;
138 }
139
140 void setFromDesktopSizeEdits(HWND hDlg) {
141     char *width = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
142     char *height = HeapAlloc(GetProcessHeap(), 0, RES_MAXLEN+1);
143     char *new = HeapAlloc(GetProcessHeap(), 0, (RES_MAXLEN*2) + 2);
144
145     if (updating_ui) goto end;
146     
147     WINE_TRACE("\n");
148     
149     GetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_WIDTH), width, RES_MAXLEN+1);
150     GetWindowText(GetDlgItem(hDlg, IDC_DESKTOP_HEIGHT), height, RES_MAXLEN+1);
151
152     if (strcmp(width, "") == 0) strcpy(width, "640");
153     if (strcmp(height, "") == 0) strcpy(height, "480");
154     
155     sprintf(new, "%sx%s", width, height);
156     set(keypath("x11drv"), "Desktop", new);
157     
158 end:
159     HeapFree(GetProcessHeap(), 0, width);
160     HeapFree(GetProcessHeap(), 0, height);
161     HeapFree(GetProcessHeap(), 0, new);
162 }
163
164 void onEnableDesktopClicked(HWND hDlg) {
165     WINE_TRACE("\n");
166     if (IsDlgButtonChecked(hDlg, IDC_ENABLE_DESKTOP) == BST_CHECKED) {
167         /* it was just unchecked, so read the values of the edit boxes, set the config value */
168         setFromDesktopSizeEdits(hDlg);
169     } else {
170         /* it was just checked, so remove the config values */
171         set(keypath("x11drv"), "Desktop", NULL);
172     }
173     update_gui_for_desktop_mode(hDlg);
174 }
175
176 void onScreenDepthChanged(HWND hDlg) {
177     char *newvalue = getDialogItemText(hDlg, IDC_SCREEN_DEPTH);
178     char *spaceIndex = strchr(newvalue, ' ');
179     
180     WINE_TRACE("newvalue=%s\n", newvalue);
181     if (updating_ui) return;
182
183     *spaceIndex = '\0';
184     set(keypath("x11drv"), "ScreenDepth", newvalue);
185     free(newvalue);
186 }
187
188 void onDXMouseGrabClicked(HWND hDlg) {
189     if (IsDlgButtonChecked(hDlg, IDC_DX_MOUSE_GRAB) == BST_CHECKED)
190         set(keypath("x11drv"), "DXGrab", "Y");
191     else
192         set(keypath("x11drv"), "DXGrab", "N");
193 }
194
195
196 void onDoubleBufferClicked(HWND hDlg) {
197     if (IsDlgButtonChecked(hDlg, IDC_DOUBLE_BUFFER) == BST_CHECKED)
198         set(keypath("x11drv"), "DesktopDoubleBuffered", "Y");
199     else
200         set(keypath("x11drv"), "DesktopDoubleBuffered", "N");
201 }
202
203 INT_PTR CALLBACK
204 GraphDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
205 {
206     switch (uMsg) {
207         case WM_INITDIALOG:
208             break;
209
210         case WM_SHOWWINDOW:
211             set_window_title(hDlg);
212             break;
213             
214         case WM_COMMAND:
215             switch(HIWORD(wParam)) {
216                 case EN_CHANGE: {
217                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
218                     if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updating_ui )
219                         setFromDesktopSizeEdits(hDlg);
220                     break;
221                 }
222                 case BN_CLICKED: {
223                     if (updating_ui) break;
224                     switch(LOWORD(wParam)) {
225                         case IDC_ENABLE_DESKTOP: onEnableDesktopClicked(hDlg); break;
226                         case IDC_DX_MOUSE_GRAB:  onDXMouseGrabClicked(hDlg); break;
227                         case IDC_DOUBLE_BUFFER:  onDoubleBufferClicked(hDlg); break;
228                     };
229                     break;
230                 }
231                 case CBN_SELCHANGE: {
232                     if (LOWORD(wParam) == IDC_SCREEN_DEPTH) onScreenDepthChanged(hDlg);
233                     break;
234                 }
235                     
236                 default:
237                     break;
238             }
239             break;
240         
241         
242         case WM_NOTIFY:
243             switch (((LPNMHDR)lParam)->code) {
244                 case PSN_KILLACTIVE: {
245                     SetWindowLong(hDlg, DWL_MSGRESULT, FALSE);
246                     break;
247                 }
248                 case PSN_APPLY: {
249                     apply();
250                     SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
251                     break;
252                 }
253                 case PSN_SETACTIVE: {
254                     initGraphDlg (hDlg);
255                     break;
256                 }
257             }
258             break;
259
260         default:
261             break;
262     }
263     return FALSE;
264 }