1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2002,2005 Hans Breuer
3 * Copyright (C) 2003 Tor Lillqvist
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.
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.
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.
23 #include "gdkprivate-win32.h"
25 #define HAVE_MONITOR_INFO
27 #if defined(_MSC_VER) && (WINVER < 0x500) && (WINVER > 0x0400)
29 #elif defined(_MSC_VER) && (WINVER <= 0x0400)
30 #undef HAVE_MONITOR_INFO
33 #ifdef HAVE_MONITOR_INFO
34 typedef BOOL (WINAPI *t_EnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
35 typedef BOOL (WINAPI *t_GetMonitorInfoA)(HMONITOR, LPMONITORINFO);
37 static t_EnumDisplayMonitors p_EnumDisplayMonitors = NULL;
38 static t_GetMonitorInfoA p_GetMonitorInfoA = NULL;
42 _gdk_windowing_set_default_display (GdkDisplay *display)
44 g_assert (_gdk_display == display);
47 #ifdef HAVE_MONITOR_INFO
49 count_monitor (HMONITOR hmonitor,
54 gint *n = (gint *) data;
62 enum_monitor (HMONITOR hmonitor,
67 MONITORINFOEX monitor_info;
69 gint *index = (gint *) data;
70 GdkRectangle *monitor;
72 g_assert (*index < _gdk_num_monitors);
74 monitor = _gdk_monitors + *index;
76 monitor_info.cbSize = sizeof (MONITORINFOEX);
77 (*p_GetMonitorInfoA) (hmonitor, (MONITORINFO *) &monitor_info);
79 #ifndef MONITORINFOF_PRIMARY
80 #define MONITORINFOF_PRIMARY 1
83 monitor->x = monitor_info.rcMonitor.left;
84 monitor->y = monitor_info.rcMonitor.top;
85 monitor->width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
86 monitor->height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
88 if (monitor_info.dwFlags & MONITORINFOF_PRIMARY &&
91 /* Put primary monitor at index 0, just in case somebody needs
92 * to know which one is the primary.
94 GdkRectangle temp = *monitor;
95 *monitor = _gdk_monitors[0];
96 _gdk_monitors[0] = temp;
103 #endif /* HAVE_MONITOR_INFO */
106 _gdk_monitor_init (void)
108 #ifdef HAVE_MONITOR_INFO
109 static HMODULE user32 = NULL;
113 user32 = GetModuleHandle ("user32.dll");
115 g_assert (user32 != NULL);
117 p_EnumDisplayMonitors = (t_EnumDisplayMonitors) GetProcAddress (user32, "EnumDisplayMonitors");
118 p_GetMonitorInfoA = (t_GetMonitorInfoA) GetProcAddress (user32, "GetMonitorInfoA");
121 if (p_EnumDisplayMonitors != NULL && p_GetMonitorInfoA != NULL)
125 _gdk_num_monitors = 0;
127 (*p_EnumDisplayMonitors) (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
129 _gdk_monitors = g_renew (GdkRectangle, _gdk_monitors, _gdk_num_monitors);
132 (*p_EnumDisplayMonitors) (NULL, NULL, enum_monitor, (LPARAM) &index);
134 _gdk_offset_x = G_MININT;
135 _gdk_offset_y = G_MININT;
137 /* Calculate offset */
138 for (i = 0; i < _gdk_num_monitors; i++)
140 _gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].x);
141 _gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].y);
143 GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
144 _gdk_offset_x, _gdk_offset_y));
146 /* Translate monitor coords into GDK coordinate space */
147 for (i = 0; i < _gdk_num_monitors; i++)
149 _gdk_monitors[i].x += _gdk_offset_x;
150 _gdk_monitors[i].y += _gdk_offset_y;
151 GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@%+d%+d\n",
152 i, _gdk_monitors[i].width,
153 _gdk_monitors[i].height,
154 _gdk_monitors[i].x, _gdk_monitors[i].y));
158 #endif /* HAVE_MONITOR_INFO */
160 unsigned int width, height;
162 _gdk_num_monitors = 1;
163 _gdk_monitors = g_renew (GdkRectangle, _gdk_monitors, 1);
165 width = GetSystemMetrics (SM_CXSCREEN);
166 height = GetSystemMetrics (SM_CYSCREEN);
168 _gdk_monitors[0].x = 0;
169 _gdk_monitors[0].y = 0;
170 _gdk_monitors[0].width = width;
171 _gdk_monitors[0].height = height;
179 * Dynamic version of ProcessIdToSessionId() form Terminal Service.
180 * It is only returning something else than 0 when running under
181 * Terminal Service, available since NT4 SP4 and not for win9x
184 get_session_id (void)
186 typedef BOOL (WINAPI *t_ProcessIdToSessionId) (DWORD, DWORD*);
187 static t_ProcessIdToSessionId p_ProcessIdToSessionId = NULL;
188 static HMODULE kernel32 = NULL;
191 if (kernel32 == NULL)
193 kernel32 = GetModuleHandle ("kernel32.dll");
195 g_assert (kernel32 != NULL);
197 p_ProcessIdToSessionId = (t_ProcessIdToSessionId) GetProcAddress (kernel32, "ProcessIdToSessionId");
199 if (p_ProcessIdToSessionId)
200 p_ProcessIdToSessionId (GetCurrentProcessId (), &id); /* got it (or not ;) */
206 gdk_display_open (const gchar *display_name)
208 GDK_NOTE (MISC, g_print ("gdk_display_open: %s\n", (display_name ? display_name : "NULL")));
210 if (display_name == NULL ||
211 g_ascii_strcasecmp (display_name,
212 gdk_display_get_name (_gdk_display)) == 0)
214 if (_gdk_display != NULL)
216 GDK_NOTE (MISC, g_print ("... return _gdk_display\n"));
222 GDK_NOTE (MISC, g_print ("... return NULL\n"));
226 _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
227 _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
229 _gdk_monitor_init ();
231 gdk_screen_set_default_colormap (_gdk_screen,
232 gdk_screen_get_system_colormap (_gdk_screen));
233 _gdk_windowing_window_init ();
234 _gdk_windowing_image_init ();
236 _gdk_input_init (_gdk_display);
239 /* Precalculate display name */
240 (void) gdk_display_get_name (_gdk_display);
242 g_signal_emit_by_name (gdk_display_manager_get (),
243 "display_opened", _gdk_display);
245 GDK_NOTE (MISC, g_print ("... _gdk_display now set up\n"));
250 G_CONST_RETURN gchar *
251 gdk_display_get_name (GdkDisplay *display)
253 HDESK hdesk = GetThreadDesktop (GetCurrentThreadId ());
256 HWINSTA hwinsta = GetProcessWindowStation ();
257 char *window_station_name;
260 static const char *display_name_cache = NULL;
262 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
264 if (display_name_cache != NULL)
265 return display_name_cache;
268 GetUserObjectInformation (hdesk, UOI_NAME, &dummy, 0, &n);
270 desktop_name = "Default";
274 desktop_name = g_alloca (n + 1);
275 memset (desktop_name, 0, n + 1);
277 if (!GetUserObjectInformation (hdesk, UOI_NAME, desktop_name, n, &n))
278 desktop_name = "Default";
282 GetUserObjectInformation (hwinsta, UOI_NAME, &dummy, 0, &n);
284 window_station_name = "WinSta0";
288 window_station_name = g_alloca (n + 1);
289 memset (window_station_name, 0, n + 1);
291 if (!GetUserObjectInformation (hwinsta, UOI_NAME, window_station_name, n, &n))
292 window_station_name = "WinSta0";
295 display_name = g_strdup_printf ("%d\\%s\\%s",
296 get_session_id (), window_station_name,
299 GDK_NOTE (MISC, g_print ("gdk_display_get_name: %s\n", display_name));
301 display_name_cache = display_name;
303 return display_name_cache;
307 gdk_display_get_n_screens (GdkDisplay *display)
309 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
315 gdk_display_get_screen (GdkDisplay *display,
318 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
319 g_return_val_if_fail (screen_num != 0, NULL);
325 gdk_display_get_default_screen (GdkDisplay *display)
327 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
333 gdk_display_get_default_group (GdkDisplay *display)
335 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
337 g_warning ("gdk_display_get_default_group not yet implemented");
343 gdk_display_supports_selection_notification (GdkDisplay *display)
345 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
350 static HWND _hwnd_next_viewer = NULL;
353 * maybe this should be integrated with the default message loop - or maybe not ;-)
355 static LRESULT CALLBACK
356 _win32_on_clipboard_change (HWND hwnd,
363 case WM_DESTROY : /* remove us from chain */
365 ChangeClipboardChain (hwnd, _hwnd_next_viewer);
368 case WM_CHANGECBCHAIN :
370 HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
371 HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
372 if (hwndRemove == _hwnd_next_viewer)
373 _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
376 case WM_DRAWCLIPBOARD :
378 /* Create the appropriate gdk events */
380 #ifdef G_ENABLE_DEBUG
381 if ((_gdk_debug_flags & GDK_DEBUG_DND) &&
382 OpenClipboard (hwnd))
384 HWND hwndOwner = GetClipboardOwner ();
387 g_print ("WM_DRAWCLIPBOARD: owner:%p formats: ", hwndOwner);
388 for (; 0 != (nFormat = EnumClipboardFormats (nFormat));)
390 g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
396 /* XXX: generate the apropriate GdkEventOwnerChange ... */
398 /* don't break the chain */
399 return PostMessage (_hwnd_next_viewer, message, wparam, lparam);
402 return DefWindowProc (hwnd, message, wparam, lparam);
407 * Creates a hidden window and adds it to the clipboard chain
410 _gdk_win32_register_clipboard_notification (void)
416 memset (&wclass, 0, sizeof(WNDCLASS));
417 wclass.lpszClassName = "GdkClipboardNotification";
418 wclass.lpfnWndProc = _win32_on_clipboard_change;
419 wclass.hInstance = _gdk_app_hmodule;
421 klass = RegisterClass (&wclass);
425 hwnd = CreateWindow (MAKEINTRESOURCE(klass),
427 0, 0, 0, 0, NULL, NULL,
428 _gdk_app_hmodule, NULL);
431 UnregisterClass (MAKEINTRESOURCE(klass), _gdk_app_hmodule);
434 _hwnd_next_viewer = SetClipboardViewer (hwnd);
439 * The whole function would only make sense if the gdk/win32 clipboard
440 * model is rewritten to do delayed rendering. Currently this is only
441 * testcode and as noted in
442 * http://mail.gnome.org/archives/gtk-devel-list/2004-May/msg00113.html
443 * probably not worth bothering ;)
446 gdk_display_request_selection_notification (GdkDisplay *display,
450 static HWND hwndViewer = NULL;
451 gboolean ret = FALSE;
454 g_print ("gdk_display_request_selection_notification (..., %s)",
455 gdk_atom_name (selection)));
457 if (GDK_SELECTION_CLIPBOARD == selection)
461 hwndViewer = _gdk_win32_register_clipboard_notification ();
462 GDK_NOTE (DND, g_print (" registered"));
464 ret = (hwndViewer != NULL);
466 else if (GDK_SELECTION_PRIMARY == selection)
468 /* seems to work by default ? */
469 GDK_NOTE (DND, g_print (" by default"));
472 GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));
477 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
483 gdk_display_store_clipboard (GdkDisplay *display,
484 GdkWindow *clipboard_window,
489 /* XXX: implement it (or maybe not as long as we don't support delayed rendering?) */