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_display_open (const gchar *display_name)
110 if (_gdk_display != NULL)
111 return NULL; /* single display only */
113 _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
114 _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
116 #ifdef HAVE_MONITOR_INFO
117 user32 = GetModuleHandle ("user32.dll");
118 g_assert (user32 != NULL);
120 p_EnumDisplayMonitors = (t_EnumDisplayMonitors) GetProcAddress (user32, "EnumDisplayMonitors");
121 p_GetMonitorInfoA = (t_GetMonitorInfoA) GetProcAddress (user32, "GetMonitorInfoA");
123 if (p_EnumDisplayMonitors != NULL && p_GetMonitorInfoA != NULL)
127 _gdk_num_monitors = 0;
129 (*p_EnumDisplayMonitors) (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
131 _gdk_monitors = g_new (GdkRectangle, _gdk_num_monitors);
133 (*p_EnumDisplayMonitors) (NULL, NULL, enum_monitor, (LPARAM) &index);
135 _gdk_offset_x = G_MININT;
136 _gdk_offset_y = G_MININT;
138 /* Calculate offset */
139 for (i = 0; i < _gdk_num_monitors; i++)
141 _gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].x);
142 _gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].y);
144 GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
145 _gdk_offset_x, _gdk_offset_y));
147 /* Translate monitor coords into GDK coordinate space */
148 for (i = 0; i < _gdk_num_monitors; i++)
150 _gdk_monitors[i].x += _gdk_offset_x;
151 _gdk_monitors[i].y += _gdk_offset_y;
152 GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@+%d+%d\n",
153 i, _gdk_monitors[i].width,
154 _gdk_monitors[i].height,
155 _gdk_monitors[i].x, _gdk_monitors[i].y));
160 #endif /* HAVE_MONITOR_INFO */
162 unsigned int width, height;
164 _gdk_num_monitors = 1;
165 _gdk_monitors = g_new (GdkRectangle, 1);
167 width = GetSystemMetrics (SM_CXSCREEN);
168 height = GetSystemMetrics (SM_CYSCREEN);
170 _gdk_monitors[0].x = 0;
171 _gdk_monitors[0].y = 0;
172 _gdk_monitors[0].width = width;
173 _gdk_monitors[0].height = height;
179 gdk_screen_set_default_colormap (_gdk_screen,
180 gdk_screen_get_system_colormap (_gdk_screen));
181 _gdk_windowing_window_init ();
182 _gdk_windowing_image_init ();
184 _gdk_input_init (_gdk_display);
187 g_signal_emit_by_name (gdk_display_manager_get (),
188 "display_opened", _gdk_display);
193 G_CONST_RETURN gchar *
194 gdk_display_get_name (GdkDisplay *display)
196 return gdk_get_display_arg_name ();
200 gdk_display_get_n_screens (GdkDisplay *display)
206 gdk_display_get_screen (GdkDisplay *display,
213 gdk_display_get_default_screen (GdkDisplay *display)
219 gdk_display_get_default_group (GdkDisplay *display)
221 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
223 g_warning ("gdk_display_get_default_group not yet implemented");
229 gdk_display_supports_selection_notification (GdkDisplay *display)
231 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
236 static HWND _hwnd_next_viewer = NULL;
239 * maybe this should be integrated with the default message loop - or maybe not ;-)
241 static LRESULT CALLBACK
242 _win32_on_clipboard_change (HWND hwnd,
249 case WM_DESTROY : /* remove us from chain */
251 ChangeClipboardChain (hwnd, _hwnd_next_viewer);
254 case WM_CHANGECBCHAIN :
256 HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
257 HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
258 if (hwndRemove == _hwnd_next_viewer)
259 _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
262 case WM_DRAWCLIPBOARD :
264 /* create the appropriate gdk events */
265 HWND hwndOwner = GetClipboardOwner ();
269 if (OpenClipboard (hwnd))
271 for (; 0 != (nFormat = EnumClipboardFormats (nFormat)); )
274 if (GetClipboardFormatName (nFormat, sFormat, 80) > 0)
275 g_print ("%s ", sFormat);
276 n++; /* do something useful ? */
279 g_print ("WM_DRAWCLIPBOARD : formats %d owner %#lx\n", n, hwndOwner));
283 /* XXX: generate the apropriate GdkEventOwnerChange ... */
285 /* don't break the chain */
286 return PostMessage (_hwnd_next_viewer, message, wparam, lparam);
289 return DefWindowProc (hwnd, message, wparam, lparam);
294 * Creates a hidden window and adds it to the clipboard chain
297 _gdk_win32_register_clipboard_notification (void)
303 memset (&wclass, 0, sizeof(WNDCLASS));
304 wclass.lpszClassName = "GdkClipboardNotification";
305 wclass.lpfnWndProc = _win32_on_clipboard_change;
306 wclass.hInstance = _gdk_app_hmodule;
308 klass = RegisterClass (&wclass);
312 hwnd = CreateWindow (MAKEINTRESOURCE(klass),
314 0, 0, 0, 0, NULL, NULL,
315 _gdk_app_hmodule, NULL);
318 UnregisterClass (MAKEINTRESOURCE(klass), _gdk_app_hmodule);
321 _hwnd_next_viewer = SetClipboardViewer (hwnd);
326 * The whole function would only make sense if the gdk/win32 clipboard
327 * model is rewritten to do delayed rendering. Currently this is only
328 * testcode and as noted in
329 * http://mail.gnome.org/archives/gtk-devel-list/2004-May/msg00113.html
330 * probably not worth bothering ;)
333 gdk_display_request_selection_notification (GdkDisplay *display,
337 static HWND hwndViewer = NULL;
338 gboolean ret = FALSE;
341 g_print ("gdk_display_request_selection_notification (..., %s)",
342 gdk_atom_name (selection)));
344 if (GDK_SELECTION_CLIPBOARD == selection)
348 hwndViewer = _gdk_win32_register_clipboard_notification ();
349 GDK_NOTE (DND, g_print (" registered"));
351 ret = (hwndViewer != NULL);
353 else if (GDK_SELECTION_PRIMARY == selection)
355 /* seems to work by default ? */
356 GDK_NOTE (DND, g_print (" by default"));
359 GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));