1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 2002 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 gdk_display_open (const gchar *display_name)
181 if (_gdk_display != NULL)
182 return NULL; /* single display only */
184 _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
185 _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
187 _gdk_monitor_init ();
189 gdk_screen_set_default_colormap (_gdk_screen,
190 gdk_screen_get_system_colormap (_gdk_screen));
191 _gdk_windowing_window_init ();
192 _gdk_windowing_image_init ();
194 _gdk_input_init (_gdk_display);
197 g_signal_emit_by_name (gdk_display_manager_get (),
198 "display_opened", _gdk_display);
203 G_CONST_RETURN gchar *
204 gdk_display_get_name (GdkDisplay *display)
206 return gdk_get_display_arg_name ();
210 gdk_display_get_n_screens (GdkDisplay *display)
216 gdk_display_get_screen (GdkDisplay *display,
223 gdk_display_get_default_screen (GdkDisplay *display)
229 gdk_display_get_default_group (GdkDisplay *display)
231 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
233 g_warning ("gdk_display_get_default_group not yet implemented");
239 gdk_display_supports_selection_notification (GdkDisplay *display)
241 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
246 static HWND _hwnd_next_viewer = NULL;
249 * maybe this should be integrated with the default message loop - or maybe not ;-)
251 static LRESULT CALLBACK
252 _win32_on_clipboard_change (HWND hwnd,
259 case WM_DESTROY : /* remove us from chain */
261 ChangeClipboardChain (hwnd, _hwnd_next_viewer);
264 case WM_CHANGECBCHAIN :
266 HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
267 HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
268 if (hwndRemove == _hwnd_next_viewer)
269 _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
272 case WM_DRAWCLIPBOARD :
274 /* Create the appropriate gdk events */
276 #ifdef G_ENABLE_DEBUG
277 if ((_gdk_debug_flags & GDK_DEBUG_DND) &&
278 OpenClipboard (hwnd))
280 HWND hwndOwner = GetClipboardOwner ();
283 g_print ("WM_DRAWCLIPBOARD: owner:%p formats: ", hwndOwner);
284 for (; 0 != (nFormat = EnumClipboardFormats (nFormat));)
287 if (GetClipboardFormatName (nFormat, sFormat, G_N_ELEMENTS (sFormat)) > 0)
288 g_print ("%s ", sFormat);
294 /* XXX: generate the apropriate GdkEventOwnerChange ... */
296 /* don't break the chain */
297 return PostMessage (_hwnd_next_viewer, message, wparam, lparam);
300 return DefWindowProc (hwnd, message, wparam, lparam);
305 * Creates a hidden window and adds it to the clipboard chain
308 _gdk_win32_register_clipboard_notification (void)
314 memset (&wclass, 0, sizeof(WNDCLASS));
315 wclass.lpszClassName = "GdkClipboardNotification";
316 wclass.lpfnWndProc = _win32_on_clipboard_change;
317 wclass.hInstance = _gdk_app_hmodule;
319 klass = RegisterClass (&wclass);
323 hwnd = CreateWindow (MAKEINTRESOURCE(klass),
325 0, 0, 0, 0, NULL, NULL,
326 _gdk_app_hmodule, NULL);
329 UnregisterClass (MAKEINTRESOURCE(klass), _gdk_app_hmodule);
332 _hwnd_next_viewer = SetClipboardViewer (hwnd);
337 * The whole function would only make sense if the gdk/win32 clipboard
338 * model is rewritten to do delayed rendering. Currently this is only
339 * testcode and as noted in
340 * http://mail.gnome.org/archives/gtk-devel-list/2004-May/msg00113.html
341 * probably not worth bothering ;)
344 gdk_display_request_selection_notification (GdkDisplay *display,
348 static HWND hwndViewer = NULL;
349 gboolean ret = FALSE;
352 g_print ("gdk_display_request_selection_notification (..., %s)",
353 gdk_atom_name (selection)));
355 if (GDK_SELECTION_CLIPBOARD == selection)
359 hwndViewer = _gdk_win32_register_clipboard_notification ();
360 GDK_NOTE (DND, g_print (" registered"));
362 ret = (hwndViewer != NULL);
364 else if (GDK_SELECTION_PRIMARY == selection)
366 /* seems to work by default ? */
367 GDK_NOTE (DND, g_print (" by default"));
370 GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));
375 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
381 gdk_display_store_clipboard (GdkDisplay *display,
382 GdkWindow *clipboard_window,
387 /* XXX: implement it (or maybe not as long as we don't support delayed rendering?) */