]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkdisplay-win32.c
Merge branch 'master' into client-side-windows
[~andy/gtk] / gdk / win32 / gdkdisplay-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 2002,2005 Hans Breuer
3  * Copyright (C) 2003 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22 #include "gdk.h"
23 #include "gdkprivate-win32.h"
24
25 #define HAVE_MONITOR_INFO
26
27 #if defined(_MSC_VER) && (WINVER < 0x500) && (WINVER > 0x0400)
28 #include <multimon.h>
29 #elif defined(_MSC_VER) && (WINVER <= 0x0400)
30 #undef HAVE_MONITOR_INFO
31 #endif
32
33 void
34 _gdk_windowing_set_default_display (GdkDisplay *display)
35 {
36   g_assert (display == NULL || _gdk_display == display);
37 }
38
39 gulong
40 _gdk_windowing_window_get_next_serial (GdkDisplay *display)
41 {
42         return 0;
43 }
44
45 #ifdef HAVE_MONITOR_INFO
46 static BOOL CALLBACK
47 count_monitor (HMONITOR hmonitor,
48                HDC      hdc,
49                LPRECT   rect,
50                LPARAM   data)
51 {
52   gint *n = (gint *) data;
53
54   (*n)++;
55
56   return TRUE;
57 }
58
59 static BOOL CALLBACK
60 enum_monitor (HMONITOR hmonitor,
61               HDC      hdc,
62               LPRECT   rect,
63               LPARAM   data)
64 {
65   /* The struct MONITORINFOEX definition is for some reason different
66    * in the winuser.h bundled with mingw64 from that in MSDN and the
67    * official 32-bit mingw (the MONITORINFO part is in a separate "mi"
68    * member). So to keep this easily compileable with either, repeat
69    * the MSDN definition it here.
70    */
71   typedef struct tagMONITORINFOEXA2 {
72     DWORD cbSize;
73     RECT  rcMonitor;
74     RECT  rcWork;
75     DWORD dwFlags;
76     CHAR szDevice[CCHDEVICENAME];
77   } MONITORINFOEXA2;
78   
79   MONITORINFOEXA2 monitor_info;
80   HDC hDC;
81
82   gint *index = (gint *) data;
83   GdkWin32Monitor *monitor;
84
85   g_assert (*index < _gdk_num_monitors);
86
87   monitor = _gdk_monitors + *index;
88
89   monitor_info.cbSize = sizeof (MONITORINFOEX);
90   GetMonitorInfoA (hmonitor, (MONITORINFO *) &monitor_info);
91
92 #ifndef MONITORINFOF_PRIMARY
93 #define MONITORINFOF_PRIMARY 1
94 #endif
95
96   monitor->name = g_strdup (monitor_info.szDevice);
97   hDC = CreateDCA ("DISPLAY", monitor_info.szDevice, NULL, NULL);
98   monitor->width_mm = GetDeviceCaps (hDC, HORZSIZE);
99   monitor->height_mm = GetDeviceCaps (hDC, VERTSIZE);
100   DeleteDC (hDC);
101   monitor->rect.x = monitor_info.rcMonitor.left;
102   monitor->rect.y = monitor_info.rcMonitor.top;
103   monitor->rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
104   monitor->rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
105
106   if (monitor_info.dwFlags & MONITORINFOF_PRIMARY &&
107       *index != 0)
108     {
109       /* Put primary monitor at index 0, just in case somebody needs
110        * to know which one is the primary.
111        */
112       GdkWin32Monitor temp = *monitor;
113       *monitor = _gdk_monitors[0];
114       _gdk_monitors[0] = temp;
115     }
116
117   (*index)++;
118
119   return TRUE;
120 }
121 #endif /* HAVE_MONITOR_INFO */
122
123 void
124 _gdk_monitor_init (void)
125 {
126 #ifdef HAVE_MONITOR_INFO
127   gint i, index;
128
129   _gdk_num_monitors = 0;
130
131   EnumDisplayMonitors (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
132
133   _gdk_monitors = g_renew (GdkWin32Monitor, _gdk_monitors, _gdk_num_monitors);
134
135   index = 0;
136   EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &index);
137
138   _gdk_offset_x = G_MININT;
139   _gdk_offset_y = G_MININT;
140
141   /* Calculate offset */
142   for (i = 0; i < _gdk_num_monitors; i++)
143     {
144       _gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].rect.x);
145       _gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].rect.y);
146     }
147   GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
148                            _gdk_offset_x, _gdk_offset_y));
149
150   /* Translate monitor coords into GDK coordinate space */
151   for (i = 0; i < _gdk_num_monitors; i++)
152     {
153       _gdk_monitors[i].rect.x += _gdk_offset_x;
154       _gdk_monitors[i].rect.y += _gdk_offset_y;
155       GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@%+d%+d\n",
156                                i, _gdk_monitors[i].rect.width,
157                                _gdk_monitors[i].rect.height,
158                                _gdk_monitors[i].rect.x,
159                                _gdk_monitors[i].rect.y));
160     }
161 #else
162   HDC hDC;
163
164   _gdk_num_monitors = 1;
165   _gdk_monitors = g_renew (GdkWin32Monitor, _gdk_monitors, 1);
166
167   _gdk_monitors[0].name = g_strdup ("DISPLAY");
168   hDC = GetDC (NULL);
169   _gdk_monitors[0].width_mm = GetDeviceCaps (hDC, HORZSIZE);
170   _gdk_monitors[0].height_mm = GetDeviceCaps (hDC, VERTSIZE);
171   ReleaseDC (NULL, hDC);
172   _gdk_monitors[0].rect.x = 0;
173   _gdk_monitors[0].rect.y = 0;
174   _gdk_monitors[0].rect.width = GetSystemMetrics (SM_CXSCREEN);
175   _gdk_monitors[0].rect.height = GetSystemMetrics (SM_CYSCREEN);
176   _gdk_offset_x = 0;
177   _gdk_offset_y = 0;
178 #endif
179 }
180
181 GdkDisplay *
182 gdk_display_open (const gchar *display_name)
183 {
184   GDK_NOTE (MISC, g_print ("gdk_display_open: %s\n", (display_name ? display_name : "NULL")));
185
186   if (display_name == NULL ||
187       g_ascii_strcasecmp (display_name,
188                           gdk_display_get_name (_gdk_display)) == 0)
189     {
190       if (_gdk_display != NULL)
191         {
192           GDK_NOTE (MISC, g_print ("... return _gdk_display\n"));
193           return _gdk_display;
194         }
195     }
196   else
197     {
198       GDK_NOTE (MISC, g_print ("... return NULL\n"));
199       return NULL;
200     }
201
202   _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
203   _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
204
205   _gdk_monitor_init ();
206   _gdk_visual_init ();
207   gdk_screen_set_default_colormap (_gdk_screen,
208                                    gdk_screen_get_system_colormap (_gdk_screen));
209   _gdk_windowing_window_init (_gdk_screen);
210   _gdk_windowing_image_init ();
211   _gdk_events_init ();
212   _gdk_input_init (_gdk_display);
213   _gdk_dnd_init ();
214
215   /* Precalculate display name */
216   (void) gdk_display_get_name (_gdk_display);
217
218   g_signal_emit_by_name (gdk_display_manager_get (),
219                          "display_opened", _gdk_display);
220
221   GDK_NOTE (MISC, g_print ("... _gdk_display now set up\n"));
222
223   return _gdk_display;
224 }
225
226 G_CONST_RETURN gchar *
227 gdk_display_get_name (GdkDisplay *display)
228 {
229   HDESK hdesk = GetThreadDesktop (GetCurrentThreadId ());
230   char dummy;
231   char *desktop_name;
232   HWINSTA hwinsta = GetProcessWindowStation ();
233   char *window_station_name;
234   DWORD n;
235   DWORD session_id;
236   char *display_name;
237   static const char *display_name_cache = NULL;
238   typedef BOOL (WINAPI *PFN_ProcessIdToSessionId) (DWORD, DWORD *);
239   PFN_ProcessIdToSessionId processIdToSessionId;
240
241   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
242   
243   if (display_name_cache != NULL)
244     return display_name_cache;
245
246   n = 0;
247   GetUserObjectInformation (hdesk, UOI_NAME, &dummy, 0, &n);
248   if (n == 0)
249     desktop_name = "Default";
250   else
251     {
252       n++;
253       desktop_name = g_alloca (n + 1);
254       memset (desktop_name, 0, n + 1);
255
256       if (!GetUserObjectInformation (hdesk, UOI_NAME, desktop_name, n, &n))
257         desktop_name = "Default";
258     }
259
260   n = 0;
261   GetUserObjectInformation (hwinsta, UOI_NAME, &dummy, 0, &n);
262   if (n == 0)
263     window_station_name = "WinSta0";
264   else
265     {
266       n++;
267       window_station_name = g_alloca (n + 1);
268       memset (window_station_name, 0, n + 1);
269
270       if (!GetUserObjectInformation (hwinsta, UOI_NAME, window_station_name, n, &n))
271         window_station_name = "WinSta0";
272     }
273
274   processIdToSessionId = (PFN_ProcessIdToSessionId) GetProcAddress (GetModuleHandle ("kernel32.dll"), "ProcessIdToSessionId");
275   if (!processIdToSessionId || !processIdToSessionId (GetCurrentProcessId (), &session_id))
276     session_id = 0;
277
278   display_name = g_strdup_printf ("%ld\\%s\\%s",
279                                   session_id,
280                                   window_station_name,
281                                   desktop_name);
282
283   GDK_NOTE (MISC, g_print ("gdk_display_get_name: %s\n", display_name));
284
285   display_name_cache = display_name;
286
287   return display_name_cache;
288 }
289
290 gint
291 gdk_display_get_n_screens (GdkDisplay *display)
292 {
293   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
294   
295   return 1;
296 }
297
298 GdkScreen *
299 gdk_display_get_screen (GdkDisplay *display,
300                         gint        screen_num)
301 {
302   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
303   g_return_val_if_fail (screen_num == 0, NULL);
304
305   return _gdk_screen;
306 }
307
308 GdkScreen *
309 gdk_display_get_default_screen (GdkDisplay *display)
310 {
311   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
312
313   return _gdk_screen;
314 }
315
316 GdkWindow *
317 gdk_display_get_default_group (GdkDisplay *display)
318 {
319   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
320
321   g_warning ("gdk_display_get_default_group not yet implemented");
322
323   return NULL;
324 }
325
326 gboolean 
327 gdk_display_supports_selection_notification (GdkDisplay *display)
328 {
329   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
330
331   return FALSE;
332 }
333
334 gboolean 
335 gdk_display_request_selection_notification (GdkDisplay *display,
336                                             GdkAtom     selection)
337
338 {
339   return FALSE;
340 }
341
342 gboolean
343 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
344 {
345   return FALSE;
346 }
347
348 void
349 gdk_display_store_clipboard (GdkDisplay    *display,
350                              GdkWindow     *clipboard_window,
351                              guint32        time_,
352                              const GdkAtom *targets,
353                              gint           n_targets)
354 {
355 }
356
357 gboolean 
358 gdk_display_supports_shapes (GdkDisplay *display)
359 {
360   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
361
362   return TRUE;
363 }
364
365 gboolean 
366 gdk_display_supports_input_shapes (GdkDisplay *display)
367 {
368   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
369
370   /* Not yet implemented. See comment in
371    * gdk_window_input_shape_combine_mask().
372    */
373
374   return FALSE;
375 }
376
377 gboolean
378 gdk_display_supports_composite (GdkDisplay *display)
379 {
380   return FALSE;
381 }