winecfg: Update the DPI trackbar according to the edit box changes.
[wine] / programs / winecfg / x11drvdlg.c
1 /*
2  * Graphics configuration code
3  *
4  * Copyright 2003 Mark Westcott
5  * Copyright 2003-2004 Mike Hearn
6  * Copyright 2005 Raphael Junqueira
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  *
22  */
23
24 #define WIN32_LEAN_AND_MEAN
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29
30 #include <windows.h>
31 #include <wine/debug.h>
32
33 #include "resource.h"
34 #include "winecfg.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(winecfg);
37
38 #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? */
39 #define MINDPI 96
40 #define MAXDPI 480
41 #define DEFDPI 96
42
43 #define IDT_DPIEDIT 0x1234
44
45 static const WCHAR logpixels_reg[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\','C','u','r','r','e','n','t','\\','S','o','f','t','w','a','r','e','\\','F','o','n','t','s',0};
46 static const WCHAR logpixels[] = {'L','o','g','P','i','x','e','l','s',0};
47
48 static struct SHADERMODE
49 {
50   UINT displayStrID;
51   const char* settingStr;
52 } const D3D_VS_Modes[] = {
53   {IDS_SHADER_MODE_HARDWARE,  "hardware"},
54   {IDS_SHADER_MODE_NONE,      "none"},
55   {0, 0}
56 };
57
58
59 int updating_ui;
60
61 static void update_gui_for_desktop_mode(HWND dialog) {
62     int desktopenabled = FALSE;
63
64     WINE_TRACE("\n");
65     updating_ui = TRUE;
66
67     if (current_app)
68     {
69         disable(IDC_ENABLE_DESKTOP);
70         disable(IDC_DESKTOP_WIDTH);
71         disable(IDC_DESKTOP_HEIGHT);
72         disable(IDC_DESKTOP_SIZE);
73         disable(IDC_DESKTOP_BY);
74         return;
75     }
76     enable(IDC_ENABLE_DESKTOP);
77
78     /* do we have desktop mode enabled? */
79     if (reg_key_exists(config_key, keypath("X11 Driver"), "Desktop"))
80     {
81         char* buf, *bufindex;
82         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_CHECKED);
83
84         buf = get_reg_key(config_key, keypath("X11 Driver"), "Desktop", "800x600");
85         /* note: this test must match the one in x11drv */
86         if( buf[0] != 'n' &&  buf[0] != 'N' &&  buf[0] != 'F' &&  buf[0] != 'f'
87                 &&  buf[0] != '0') {
88             desktopenabled = TRUE;
89             enable(IDC_DESKTOP_WIDTH);
90             enable(IDC_DESKTOP_HEIGHT);
91             enable(IDC_DESKTOP_SIZE);
92             enable(IDC_DESKTOP_BY);
93
94             bufindex = strchr(buf, 'x');
95             if (bufindex) {
96                 *bufindex = 0;
97                 ++bufindex;
98                 SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), buf);
99                 SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), bufindex);
100             } else {
101                 WINE_TRACE("Desktop registry entry is malformed\n");
102                 SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "800");
103                 SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "600");
104             }
105         }
106         HeapFree(GetProcessHeap(), 0, buf);
107     }
108     if (!desktopenabled)
109     {
110         CheckDlgButton(dialog, IDC_ENABLE_DESKTOP, BST_UNCHECKED);
111         
112         disable(IDC_DESKTOP_WIDTH);
113         disable(IDC_DESKTOP_HEIGHT);
114         disable(IDC_DESKTOP_SIZE);
115         disable(IDC_DESKTOP_BY);
116
117         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_WIDTH), "");
118         SetWindowText(GetDlgItem(dialog, IDC_DESKTOP_HEIGHT), "");
119     }
120
121     updating_ui = FALSE;
122 }
123
124 static void init_dialog(HWND dialog)
125 {
126     unsigned int it;
127     char* buf;
128
129     update_gui_for_desktop_mode(dialog);
130
131     updating_ui = TRUE;
132     
133     SendDlgItemMessage(dialog, IDC_DESKTOP_WIDTH, EM_LIMITTEXT, RES_MAXLEN, 0);
134     SendDlgItemMessage(dialog, IDC_DESKTOP_HEIGHT, EM_LIMITTEXT, RES_MAXLEN, 0);
135
136     buf = get_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "N");
137     if (IS_OPTION_TRUE(*buf))
138         CheckDlgButton(dialog, IDC_DX_MOUSE_GRAB, BST_CHECKED);
139     else
140         CheckDlgButton(dialog, IDC_DX_MOUSE_GRAB, BST_UNCHECKED);
141     HeapFree(GetProcessHeap(), 0, buf);
142
143     buf = get_reg_key(config_key, keypath("X11 Driver"), "Managed", "Y");
144     if (IS_OPTION_TRUE(*buf))
145         CheckDlgButton(dialog, IDC_ENABLE_MANAGED, BST_CHECKED);
146     else
147         CheckDlgButton(dialog, IDC_ENABLE_MANAGED, BST_UNCHECKED);
148     HeapFree(GetProcessHeap(), 0, buf);
149
150     SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_RESETCONTENT, 0, 0);
151     for (it = 0; 0 != D3D_VS_Modes[it].displayStrID; ++it) {
152       SendDlgItemMessageW (dialog, IDC_D3D_VSHADER_MODE, CB_ADDSTRING, 0,
153           (LPARAM)load_string (D3D_VS_Modes[it].displayStrID));
154     }  
155     buf = get_reg_key(config_key, keypath("Direct3D"), "VertexShaderMode", "hardware"); 
156     for (it = 0; NULL != D3D_VS_Modes[it].settingStr; ++it) {
157       if (strcmp(buf, D3D_VS_Modes[it].settingStr) == 0) {
158         SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_SETCURSEL, it, 0);
159         break ;
160       }
161     }
162     if (NULL == D3D_VS_Modes[it].settingStr) {
163       WINE_ERR("Invalid Direct3D VertexShader Mode read from registry (%s)\n", buf);
164     }
165     HeapFree(GetProcessHeap(), 0, buf);
166
167     buf = get_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "enabled");
168     if (!strcmp(buf, "enabled"))
169       CheckDlgButton(dialog, IDC_D3D_PSHADER_MODE, BST_CHECKED);
170     else
171       CheckDlgButton(dialog, IDC_D3D_PSHADER_MODE, BST_UNCHECKED);
172     HeapFree(GetProcessHeap(), 0, buf);
173
174     updating_ui = FALSE;
175 }
176
177 static void set_from_desktop_edits(HWND dialog) {
178     char *width, *height, *new;
179
180     if (updating_ui) return;
181     
182     WINE_TRACE("\n");
183
184     width = get_text(dialog, IDC_DESKTOP_WIDTH);
185     height = get_text(dialog, IDC_DESKTOP_HEIGHT);
186
187     if (width == NULL || strcmp(width, "") == 0) {
188         HeapFree(GetProcessHeap(), 0, width);
189         width = strdupA("800");
190     }
191     
192     if (height == NULL || strcmp(height, "") == 0) {
193         HeapFree(GetProcessHeap(), 0, height);
194         height = strdupA("600");
195     }
196
197     new = HeapAlloc(GetProcessHeap(), 0, strlen(width) + strlen(height) + 2 /* x + terminator */);
198     sprintf(new, "%sx%s", width, height);
199     set_reg_key(config_key, keypath("X11 Driver"), "Desktop", new);
200     
201     HeapFree(GetProcessHeap(), 0, width);
202     HeapFree(GetProcessHeap(), 0, height);
203     HeapFree(GetProcessHeap(), 0, new);
204 }
205
206 static void on_enable_desktop_clicked(HWND dialog) {
207     WINE_TRACE("\n");
208     
209     if (IsDlgButtonChecked(dialog, IDC_ENABLE_DESKTOP) == BST_CHECKED) {
210         set_from_desktop_edits(dialog);
211     } else {
212         set_reg_key(config_key, keypath("X11 Driver"), "Desktop", NULL);
213     }
214     
215     update_gui_for_desktop_mode(dialog);
216 }
217
218 static void on_enable_managed_clicked(HWND dialog) {
219     WINE_TRACE("\n");
220     
221     if (IsDlgButtonChecked(dialog, IDC_ENABLE_MANAGED) == BST_CHECKED) {
222         set_reg_key(config_key, keypath("X11 Driver"), "Managed", "Y");
223     } else {
224         set_reg_key(config_key, keypath("X11 Driver"), "Managed", "N");
225     }
226 }
227
228 static void on_dx_mouse_grab_clicked(HWND dialog) {
229     if (IsDlgButtonChecked(dialog, IDC_DX_MOUSE_GRAB) == BST_CHECKED) 
230         set_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "Y");
231     else
232         set_reg_key(config_key, keypath("X11 Driver"), "DXGrab", "N");
233 }
234
235 static void on_d3d_vshader_mode_changed(HWND dialog) {
236   int selected_mode = SendDlgItemMessage(dialog, IDC_D3D_VSHADER_MODE, CB_GETCURSEL, 0, 0);  
237   set_reg_key(config_key, keypath("Direct3D"), "VertexShaderMode",
238       D3D_VS_Modes[selected_mode].settingStr); 
239 }
240
241 static void on_d3d_pshader_mode_clicked(HWND dialog) {
242     if (IsDlgButtonChecked(dialog, IDC_D3D_PSHADER_MODE) == BST_CHECKED)
243         set_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "enabled");
244     else
245         set_reg_key(config_key, keypath("Direct3D"), "PixelShaderMode", "disabled");
246 }
247 static INT read_logpixels_reg(void)
248 {
249     DWORD dwLogPixels;
250     WCHAR *buf = get_reg_keyW(HKEY_LOCAL_MACHINE, logpixels_reg, logpixels, NULL);
251     dwLogPixels = buf ? *buf : DEFDPI;
252     HeapFree(GetProcessHeap(), 0, buf);
253     return dwLogPixels;
254 }
255
256 static void init_dpi_editbox(HWND hDlg)
257 {
258     DWORD dwLogpixels;
259     char szLogpixels[MAXBUFLEN];
260
261     updating_ui = TRUE;
262
263     dwLogpixels = read_logpixels_reg();
264     WINE_TRACE("%u\n", dwLogpixels);
265
266     sprintf(szLogpixels, "%u", dwLogpixels);
267     SetDlgItemText(hDlg, IDC_RES_DPIEDIT, szLogpixels);
268
269     updating_ui = FALSE;
270 }
271
272 static void init_trackbar(HWND hDlg)
273 {
274     HWND hTrackBar = GetDlgItem(hDlg, IDC_RES_TRACKBAR);
275     DWORD dwLogpixels;
276
277     updating_ui = TRUE;
278
279     dwLogpixels = read_logpixels_reg();
280
281     SendMessageW(hTrackBar, TBM_SETRANGE, TRUE, MAKELONG(MINDPI, MAXDPI));
282     SendMessageW(hTrackBar, TBM_SETPOS, TRUE, dwLogpixels);
283
284     updating_ui = FALSE;
285 }
286
287 static void update_dpi_trackbar_from_edit(HWND hDlg, BOOL fix)
288 {
289     DWORD dpi;
290
291     updating_ui = TRUE;
292
293     dpi = GetDlgItemInt(hDlg, IDC_RES_DPIEDIT, NULL, FALSE);
294
295     if (fix)
296     {
297         DWORD fixed_dpi = dpi;
298
299         if (dpi < MINDPI) fixed_dpi = MINDPI;
300         if (dpi > MAXDPI) fixed_dpi = MAXDPI;
301
302         if (fixed_dpi != dpi)
303         {
304             char buf[16];
305
306             dpi = fixed_dpi;
307             sprintf(buf, "%u", dpi);
308             SetDlgItemText(hDlg, IDC_RES_DPIEDIT, buf);
309         }
310     }
311
312     if (dpi >= MINDPI && dpi <= MAXDPI)
313     {
314         SendDlgItemMessage(hDlg, IDC_RES_TRACKBAR, TBM_SETPOS, TRUE, dpi);
315         set_reg_key_dwordW(HKEY_LOCAL_MACHINE, logpixels_reg, logpixels, dpi);
316     }
317
318     updating_ui = FALSE;
319 }
320
321 INT_PTR CALLBACK
322 GraphDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
323 {
324     switch (uMsg) {
325         case WM_INITDIALOG:
326             init_dpi_editbox(hDlg);
327             init_trackbar(hDlg);
328             break;
329
330         case WM_SHOWWINDOW:
331             set_window_title(hDlg);
332             break;
333
334         case WM_TIMER:
335             if (wParam == IDT_DPIEDIT)
336             {
337                 KillTimer(hDlg, IDT_DPIEDIT);
338                 update_dpi_trackbar_from_edit(hDlg, TRUE);
339             }
340             break;
341             
342         case WM_COMMAND:
343             switch(HIWORD(wParam)) {
344                 case EN_CHANGE: {
345                     if (updating_ui) break;
346                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
347                     if ( ((LOWORD(wParam) == IDC_DESKTOP_WIDTH) || (LOWORD(wParam) == IDC_DESKTOP_HEIGHT)) && !updating_ui )
348                         set_from_desktop_edits(hDlg);
349                     else if (LOWORD(wParam) == IDC_RES_DPIEDIT)
350                     {
351                         update_dpi_trackbar_from_edit(hDlg, FALSE);
352                         SetTimer(hDlg, IDT_DPIEDIT, 1500, NULL);
353                     }
354                     break;
355                 }
356                 case BN_CLICKED: {
357                     if (updating_ui) break;
358                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
359                     switch(LOWORD(wParam)) {
360                         case IDC_ENABLE_DESKTOP: on_enable_desktop_clicked(hDlg); break;
361                         case IDC_ENABLE_MANAGED: on_enable_managed_clicked(hDlg); break;
362                         case IDC_DX_MOUSE_GRAB:  on_dx_mouse_grab_clicked(hDlg); break;
363                         case IDC_D3D_PSHADER_MODE: on_d3d_pshader_mode_clicked(hDlg); break;
364                     }
365                     break;
366                 }
367                 case CBN_SELCHANGE: {
368                     SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
369                     switch (LOWORD(wParam)) {
370                     case IDC_D3D_VSHADER_MODE: on_d3d_vshader_mode_changed(hDlg); break;
371                     }
372                     break;
373                 }
374                     
375                 default:
376                     break;
377             }
378             break;
379         
380         
381         case WM_NOTIFY:
382             switch (((LPNMHDR)lParam)->code) {
383                 case PSN_KILLACTIVE: {
384                     SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE);
385                     break;
386                 }
387                 case PSN_APPLY: {
388                     apply();
389                     SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
390                     break;
391                 }
392                 case PSN_SETACTIVE: {
393                     init_dialog (hDlg);
394                     break;
395                 }
396             }
397             break;
398
399         case WM_HSCROLL:
400             switch (wParam) {
401                 default: {
402                     char buf[MAXBUFLEN];
403                     int i = SendMessageW(GetDlgItem(hDlg, IDC_RES_TRACKBAR), TBM_GETPOS, 0, 0);
404                     buf[0] = 0;
405                     sprintf(buf, "%d", i);
406                     SendMessage(GetDlgItem(hDlg, IDC_RES_DPIEDIT), WM_SETTEXT, 0, (LPARAM) buf);
407                     set_reg_key_dwordW(HKEY_LOCAL_MACHINE, logpixels_reg, logpixels, i);
408                     break;
409                 }
410             }
411             break;
412
413         default:
414             break;
415     }
416     return FALSE;
417 }