INT21_GetFreeDiskSpace(): The drive parameter is found in the DL
[wine] / dlls / x11drv / xrandr.c
1 /*
2  * Wine X11drv Xrandr interface
3  *
4  * Copyright 2003 Alexander James Pasadyn
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include <string.h>
23 #include <stdio.h>
24
25 #ifdef HAVE_LIBXRANDR
26
27 #include <X11/Xlib.h>
28 #include <X11/extensions/Xrandr.h>
29 #include "x11drv.h"
30
31 #include "x11ddraw.h"
32 #include "xrandr.h"
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "wingdi.h"
37 #include "ddrawi.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(xrandr);
41
42 extern int usexrandr;
43
44 static int xrandr_event, xrandr_error, xrandr_major, xrandr_minor;
45
46 static LPDDHALMODEINFO dd_modes;
47 static unsigned int dd_mode_count;
48 static XRRScreenSize *real_xrandr_sizes;
49 static short **real_xrandr_rates;
50 static unsigned int real_xrandr_sizes_count;
51 static int *real_xrandr_rates_count;
52 static unsigned int real_xrandr_modes_count;
53
54 static int XRandRErrorHandler(Display *dpy, XErrorEvent *event, void *arg)
55 {
56     return 1;
57 }
58
59 static Bool in_desktop_mode;
60
61 /* create the mode structures */
62 static void make_modes(void)
63 {
64     int i, j;
65     for (i=0; i<real_xrandr_sizes_count; i++)
66     {
67         if (real_xrandr_rates_count[i])
68         {
69             for (j=0; j < real_xrandr_rates_count[i]; j++)
70             {
71                 X11DRV_Settings_AddOneMode(real_xrandr_sizes[i].width, 
72                                            real_xrandr_sizes[i].height, 
73                                            0, real_xrandr_rates[i][j]);
74             }
75         }
76         else
77         {
78             X11DRV_Settings_AddOneMode(real_xrandr_sizes[i].width, 
79                                        real_xrandr_sizes[i].height, 
80                                        0, 0);
81         }
82     }
83 }
84
85 static int X11DRV_XRandR_GetCurrentMode(void)
86 {
87     SizeID size;
88     Rotation rot;
89     Window root;
90     XRRScreenConfiguration *sc;
91     short rate;
92     int i;
93     int res = -1;
94     
95     wine_tsx11_lock();
96     root = RootWindow (gdi_display, DefaultScreen(gdi_display));
97     sc = XRRGetScreenInfo (gdi_display, root);
98     size = XRRConfigCurrentConfiguration (sc, &rot);
99     rate = XRRConfigCurrentRate (sc);
100     for (i = 0; i < real_xrandr_modes_count; i++)
101     {
102         if ( (dd_modes[i].dwWidth      == real_xrandr_sizes[size].width ) &&
103              (dd_modes[i].dwHeight     == real_xrandr_sizes[size].height) &&
104              (dd_modes[i].wRefreshRate == rate                          ) )
105           {
106               res = i;
107           }
108     }
109     XRRFreeScreenConfigInfo(sc);
110     wine_tsx11_unlock();
111     if (res == -1)
112     {
113         ERR("In unknown mode, returning default\n");
114         res = 0;
115     }
116     return res;
117 }
118
119 static void X11DRV_XRandR_SetCurrentMode(int mode)
120 {
121     SizeID size;
122     Rotation rot;
123     Window root;
124     XRRScreenConfiguration *sc;
125     Status stat = RRSetConfigSuccess;
126     short rate;
127     int i, j;
128     DWORD dwBpp = screen_depth;
129     if (dwBpp == 24) dwBpp = 32;
130     
131     wine_tsx11_lock();
132     root = RootWindow (gdi_display, DefaultScreen(gdi_display));
133     sc = XRRGetScreenInfo (gdi_display, root);
134     size = XRRConfigCurrentConfiguration (sc, &rot);
135     if (dwBpp != dd_modes[mode].dwBPP)
136     {
137         FIXME("Cannot change screen BPP from %ld to %ld\n", dwBpp, dd_modes[mode].dwBPP);
138     }
139     mode = mode%real_xrandr_modes_count;
140     for (i = 0; i < real_xrandr_sizes_count; i++)
141     {
142         if ( (dd_modes[mode].dwWidth  == real_xrandr_sizes[i].width ) && 
143              (dd_modes[mode].dwHeight == real_xrandr_sizes[i].height) )
144         {
145             size = i;
146             if (real_xrandr_rates_count[i])
147             {
148                 for (j=0; j < real_xrandr_rates_count[i]; j++)
149                 {
150                     if (dd_modes[mode].wRefreshRate == real_xrandr_rates[i][j])
151                     {
152                         rate = real_xrandr_rates[i][j];
153                         TRACE("Resizing X display to %ldx%ld @%d Hz\n", 
154                               dd_modes[mode].dwWidth, dd_modes[mode].dwHeight, rate);
155                         stat = XRRSetScreenConfigAndRate (gdi_display, sc, root, 
156                                                           size, rot, rate, CurrentTime);
157                         FIXME("Need to update SYSMETRICS after resizing display (now %ldx%ld)\n",
158                               dd_modes[mode].dwWidth, dd_modes[mode].dwHeight);
159                     }
160                 }
161             }
162             else
163             {
164                 TRACE("Resizing X display to %ldx%ld\n", 
165                       dd_modes[mode].dwWidth, dd_modes[mode].dwHeight);
166                 stat = XRRSetScreenConfig (gdi_display, sc, root, 
167                                            size, rot, CurrentTime);
168                 FIXME("Need to update SYSMETRICS after resizing display (now %ldx%ld)\n",
169                       dd_modes[mode].dwWidth, dd_modes[mode].dwHeight);
170             }
171         }
172     }
173     if (stat != RRSetConfigSuccess)
174     {
175         ERR("Resolution change not successful -- perhaps display has chaned?");
176     }
177     XRRFreeScreenConfigInfo(sc);
178     wine_tsx11_unlock();
179 }
180
181 void X11DRV_XRandR_Init(void)
182 {
183     Bool ok;
184     int nmodes = 0;
185     int i;
186     in_desktop_mode = (root_window != DefaultRootWindow(gdi_display));
187
188     if (xrandr_major) return; /* already initialized? */
189     if (!usexrandr) return; /* disabled in config */
190     if (in_desktop_mode) return; /* not compatible with desktop mode */
191
192     /* see if Xrandr is available */
193     wine_tsx11_lock();
194     ok = XRRQueryExtension(gdi_display, &xrandr_event, &xrandr_error);
195     if (ok)
196     {
197         X11DRV_expect_error(gdi_display, XRandRErrorHandler, NULL);
198         ok = XRRQueryVersion(gdi_display, &xrandr_major, &xrandr_minor);
199         if (X11DRV_check_error()) ok = FALSE;
200     }
201     if (ok)
202     {
203         TRACE("Found XRandR - major: %d, minor: %d\n", xrandr_major, xrandr_minor);
204         /* retrieve modes */
205         real_xrandr_sizes = XRRSizes(gdi_display, DefaultScreen(gdi_display), &real_xrandr_sizes_count);
206         ok = (real_xrandr_sizes_count>0);
207     }
208     if (ok)
209     {
210         real_xrandr_rates = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(short *) * real_xrandr_sizes_count);
211         real_xrandr_rates_count = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int) * real_xrandr_sizes_count);
212         for (i=0; i < real_xrandr_sizes_count; i++)
213         {
214             real_xrandr_rates[i] = XRRRates (gdi_display, DefaultScreen(gdi_display), i, &(real_xrandr_rates_count[i]));
215             if (real_xrandr_rates_count[i])
216             {
217                 nmodes += real_xrandr_rates_count[i];
218             }
219             else
220             {
221                 nmodes++;
222             }
223         }
224     }
225     wine_tsx11_unlock();
226     if (!ok) return;
227
228     real_xrandr_modes_count = nmodes;
229     TRACE("XRandR modes: count=%d\n", nmodes);
230
231     dd_modes = X11DRV_Settings_SetHandlers("XRandR", 
232                                            X11DRV_XRandR_GetCurrentMode, 
233                                            X11DRV_XRandR_SetCurrentMode, 
234                                            nmodes, 1);
235     make_modes();
236     X11DRV_Settings_AddDepthModes();
237     dd_mode_count = X11DRV_Settings_GetModeCount();
238     X11DRV_Settings_SetDefaultMode(0);
239
240     TRACE("Available DD modes: count=%d\n", dd_mode_count);
241     TRACE("Enabling XRandR\n");
242 }
243
244 void X11DRV_XRandR_Cleanup(void)
245 {
246     if (real_xrandr_rates)
247     {
248         HeapFree(GetProcessHeap(), 0, real_xrandr_rates);
249         real_xrandr_rates = NULL;
250     }
251     if (real_xrandr_rates_count)
252     {
253         HeapFree(GetProcessHeap(), 0, real_xrandr_rates_count);
254         real_xrandr_rates_count = NULL;
255     }
256 }
257
258 #endif /* HAVE_LIBXRANDR */