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