]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkdisplay-win32.c
Change FSF Address
[~andy/gtk] / gdk / win32 / gdkdisplay-win32.c
index e2527d2ef3def91158e1a48114480cf5ced67a08..6428f3325d9639f3bef22a668c3ca30ce1dfeca7 100644 (file)
@@ -1,5 +1,5 @@
 /* GDK - The GIMP Drawing Kit
- * Copyright (C) 2002 Hans Breuer
+ * Copyright (C) 2002,2005 Hans Breuer
  * Copyright (C) 2003 Tor Lillqvist
  *
  * This library is free software; you can redistribute it and/or
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include "config.h"
 #include "gdk.h"
 #include "gdkprivate-win32.h"
+#include "gdkdisplayprivate.h"
+#include "gdkwin32display.h"
+#include "gdkwin32screen.h"
+#include "gdkwin32window.h"
+#include "gdkwin32.h"
 
 #define HAVE_MONITOR_INFO
 
 #undef HAVE_MONITOR_INFO
 #endif
 
-#ifdef HAVE_MONITOR_INFO
-typedef BOOL (WINAPI *t_EnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
-typedef BOOL (WINAPI *t_GetMonitorInfoA)(HMONITOR, LPMONITORINFO);
-
-static t_EnumDisplayMonitors p_EnumDisplayMonitors = NULL;
-static t_GetMonitorInfoA p_GetMonitorInfoA = NULL;
-#endif
-
 void
 _gdk_windowing_set_default_display (GdkDisplay *display)
 {
-  g_assert (_gdk_display == display);
+  g_assert (display == NULL || _gdk_display == display);
+}
+
+static gulong
+gdk_win32_display_get_next_serial (GdkDisplay *display)
+{
+       return 0;
 }
 
 #ifdef HAVE_MONITOR_INFO
@@ -64,26 +65,46 @@ enum_monitor (HMONITOR hmonitor,
              LPRECT   rect,
              LPARAM   data)
 {
-  MONITORINFOEX monitor_info;
+  /* The struct MONITORINFOEX definition is for some reason different
+   * in the winuser.h bundled with mingw64 from that in MSDN and the
+   * official 32-bit mingw (the MONITORINFO part is in a separate "mi"
+   * member). So to keep this easily compileable with either, repeat
+   * the MSDN definition it here.
+   */
+  typedef struct tagMONITORINFOEXA2 {
+    DWORD cbSize;
+    RECT  rcMonitor;
+    RECT  rcWork;
+    DWORD dwFlags;
+    CHAR szDevice[CCHDEVICENAME];
+  } MONITORINFOEXA2;
+
+  MONITORINFOEXA2 monitor_info;
+  HDC hDC;
 
   gint *index = (gint *) data;
-  GdkRectangle *monitor;
+  GdkWin32Monitor *monitor;
 
   g_assert (*index < _gdk_num_monitors);
 
   monitor = _gdk_monitors + *index;
 
   monitor_info.cbSize = sizeof (MONITORINFOEX);
-  (*p_GetMonitorInfoA) (hmonitor, (MONITORINFO *) &monitor_info);
+  GetMonitorInfoA (hmonitor, (MONITORINFO *) &monitor_info);
 
 #ifndef MONITORINFOF_PRIMARY
 #define MONITORINFOF_PRIMARY 1
 #endif
 
-  monitor->x = monitor_info.rcMonitor.left;
-  monitor->y = monitor_info.rcMonitor.top;
-  monitor->width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
-  monitor->height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
+  monitor->name = g_strdup (monitor_info.szDevice);
+  hDC = CreateDCA ("DISPLAY", monitor_info.szDevice, NULL, NULL);
+  monitor->width_mm = GetDeviceCaps (hDC, HORZSIZE);
+  monitor->height_mm = GetDeviceCaps (hDC, VERTSIZE);
+  DeleteDC (hDC);
+  monitor->rect.x = monitor_info.rcMonitor.left;
+  monitor->rect.y = monitor_info.rcMonitor.top;
+  monitor->rect.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
+  monitor->rect.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
 
   if (monitor_info.dwFlags & MONITORINFOF_PRIMARY &&
       *index != 0)
@@ -91,7 +112,7 @@ enum_monitor (HMONITOR hmonitor,
       /* Put primary monitor at index 0, just in case somebody needs
        * to know which one is the primary.
        */
-      GdkRectangle temp = *monitor;
+      GdkWin32Monitor temp = *monitor;
       *monitor = _gdk_monitors[0];
       _gdk_monitors[0] = temp;
     }
@@ -106,127 +127,206 @@ void
 _gdk_monitor_init (void)
 {
 #ifdef HAVE_MONITOR_INFO
-  static HMODULE user32 = NULL;
+  gint i, index;
 
-  if (user32 == NULL)
-    {
-      user32 = GetModuleHandle ("user32.dll");
+  _gdk_num_monitors = 0;
 
-      g_assert (user32 != NULL);
+  EnumDisplayMonitors (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
 
-      p_EnumDisplayMonitors = (t_EnumDisplayMonitors) GetProcAddress (user32, "EnumDisplayMonitors");
-      p_GetMonitorInfoA = (t_GetMonitorInfoA) GetProcAddress (user32, "GetMonitorInfoA");
-    }
+  _gdk_monitors = g_renew (GdkWin32Monitor, _gdk_monitors, _gdk_num_monitors);
 
-  if (p_EnumDisplayMonitors != NULL && p_GetMonitorInfoA != NULL)
-    {
-      gint i, index;
+  index = 0;
+  EnumDisplayMonitors (NULL, NULL, enum_monitor, (LPARAM) &index);
 
-      _gdk_num_monitors = 0;
+  _gdk_offset_x = G_MININT;
+  _gdk_offset_y = G_MININT;
 
-      (*p_EnumDisplayMonitors) (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
-
-      _gdk_monitors = g_renew (GdkRectangle, _gdk_monitors, _gdk_num_monitors);
-
-      index = 0;
-      (*p_EnumDisplayMonitors) (NULL, NULL, enum_monitor, (LPARAM) &index);
+  /* Calculate offset */
+  for (i = 0; i < _gdk_num_monitors; i++)
+    {
+      _gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].rect.x);
+      _gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].rect.y);
+    }
+  GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
+                          _gdk_offset_x, _gdk_offset_y));
 
-      _gdk_offset_x = G_MININT;
-      _gdk_offset_y = G_MININT;
+  /* Translate monitor coords into GDK coordinate space */
+  for (i = 0; i < _gdk_num_monitors; i++)
+    {
+      _gdk_monitors[i].rect.x += _gdk_offset_x;
+      _gdk_monitors[i].rect.y += _gdk_offset_y;
+      GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@%+d%+d\n",
+                              i, _gdk_monitors[i].rect.width,
+                              _gdk_monitors[i].rect.height,
+                              _gdk_monitors[i].rect.x,
+                              _gdk_monitors[i].rect.y));
+    }
+#else
+  HDC hDC;
+
+  _gdk_num_monitors = 1;
+  _gdk_monitors = g_renew (GdkWin32Monitor, _gdk_monitors, 1);
+
+  _gdk_monitors[0].name = g_strdup ("DISPLAY");
+  hDC = GetDC (NULL);
+  _gdk_monitors[0].width_mm = GetDeviceCaps (hDC, HORZSIZE);
+  _gdk_monitors[0].height_mm = GetDeviceCaps (hDC, VERTSIZE);
+  ReleaseDC (NULL, hDC);
+  _gdk_monitors[0].rect.x = 0;
+  _gdk_monitors[0].rect.y = 0;
+  _gdk_monitors[0].rect.width = GetSystemMetrics (SM_CXSCREEN);
+  _gdk_monitors[0].rect.height = GetSystemMetrics (SM_CYSCREEN);
+  _gdk_offset_x = 0;
+  _gdk_offset_y = 0;
+#endif
+}
 
-      /* Calculate offset */
-      for (i = 0; i < _gdk_num_monitors; i++)
-       {
-         _gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].x);
-         _gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].y);
-       }
-      GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
-                              _gdk_offset_x, _gdk_offset_y));
+GdkDisplay *
+_gdk_win32_display_open (const gchar *display_name)
+{
+  GDK_NOTE (MISC, g_print ("gdk_display_open: %s\n", (display_name ? display_name : "NULL")));
 
-      /* Translate monitor coords into GDK coordinate space */
-      for (i = 0; i < _gdk_num_monitors; i++)
+  if (display_name == NULL ||
+      g_ascii_strcasecmp (display_name,
+                         gdk_display_get_name (_gdk_display)) == 0)
+    {
+      if (_gdk_display != NULL)
        {
-         _gdk_monitors[i].x += _gdk_offset_x;
-         _gdk_monitors[i].y += _gdk_offset_y;
-         GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@+%d+%d\n",
-                                  i, _gdk_monitors[i].width,
-                                  _gdk_monitors[i].height,
-                                  _gdk_monitors[i].x, _gdk_monitors[i].y));
+         GDK_NOTE (MISC, g_print ("... return _gdk_display\n"));
+         return _gdk_display;
        }
     }
   else
-#endif /* HAVE_MONITOR_INFO */
     {
-      unsigned int width, height;
-
-      _gdk_num_monitors = 1;
-      _gdk_monitors = g_renew (GdkRectangle, _gdk_monitors, 1);
-
-      width = GetSystemMetrics (SM_CXSCREEN);
-      height = GetSystemMetrics (SM_CYSCREEN);
-
-      _gdk_monitors[0].x = 0;
-      _gdk_monitors[0].y = 0;
-      _gdk_monitors[0].width = width;
-      _gdk_monitors[0].height = height;
-      _gdk_offset_x = 0;
-      _gdk_offset_y = 0;
+      GDK_NOTE (MISC, g_print ("... return NULL\n"));
+      return NULL;
     }
 
-}
-
-GdkDisplay *
-gdk_display_open (const gchar *display_name)
-{
-  if (_gdk_display != NULL)
-    return NULL; /* single display only */
-
-  _gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
-  _gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
+  _gdk_display = g_object_new (GDK_TYPE_WIN32_DISPLAY, NULL);
+  _gdk_screen = g_object_new (GDK_TYPE_WIN32_SCREEN, NULL);
 
   _gdk_monitor_init ();
   _gdk_visual_init ();
-  gdk_screen_set_default_colormap (_gdk_screen,
-                                   gdk_screen_get_system_colormap (_gdk_screen));
-  _gdk_windowing_window_init ();
-  _gdk_windowing_image_init ();
+  _gdk_windowing_window_init (_gdk_screen);
   _gdk_events_init ();
   _gdk_input_init (_gdk_display);
   _gdk_dnd_init ();
 
+  /* Precalculate display name */
+  (void) gdk_display_get_name (_gdk_display);
+
   g_signal_emit_by_name (gdk_display_manager_get (),
                         "display_opened", _gdk_display);
 
+  GDK_NOTE (MISC, g_print ("... _gdk_display now set up\n"));
+
   return _gdk_display;
 }
 
-G_CONST_RETURN gchar *
-gdk_display_get_name (GdkDisplay *display)
+struct _GdkWin32Display
+{
+  GdkDisplay display;
+};
+
+struct _GdkWin32DisplayClass
+{
+  GdkDisplayClass display_class;
+};
+
+G_DEFINE_TYPE (GdkWin32Display, gdk_win32_display, GDK_TYPE_DISPLAY)
+
+static const gchar *
+gdk_win32_display_get_name (GdkDisplay *display)
 {
-  return gdk_get_display_arg_name ();
+  HDESK hdesk = GetThreadDesktop (GetCurrentThreadId ());
+  char dummy;
+  char *desktop_name;
+  HWINSTA hwinsta = GetProcessWindowStation ();
+  char *window_station_name;
+  DWORD n;
+  DWORD session_id;
+  char *display_name;
+  static const char *display_name_cache = NULL;
+  typedef BOOL (WINAPI *PFN_ProcessIdToSessionId) (DWORD, DWORD *);
+  PFN_ProcessIdToSessionId processIdToSessionId;
+
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
+  if (display_name_cache != NULL)
+    return display_name_cache;
+
+  n = 0;
+  GetUserObjectInformation (hdesk, UOI_NAME, &dummy, 0, &n);
+  if (n == 0)
+    desktop_name = "Default";
+  else
+    {
+      n++;
+      desktop_name = g_alloca (n + 1);
+      memset (desktop_name, 0, n + 1);
+
+      if (!GetUserObjectInformation (hdesk, UOI_NAME, desktop_name, n, &n))
+       desktop_name = "Default";
+    }
+
+  n = 0;
+  GetUserObjectInformation (hwinsta, UOI_NAME, &dummy, 0, &n);
+  if (n == 0)
+    window_station_name = "WinSta0";
+  else
+    {
+      n++;
+      window_station_name = g_alloca (n + 1);
+      memset (window_station_name, 0, n + 1);
+
+      if (!GetUserObjectInformation (hwinsta, UOI_NAME, window_station_name, n, &n))
+       window_station_name = "WinSta0";
+    }
+
+  processIdToSessionId = (PFN_ProcessIdToSessionId) GetProcAddress (GetModuleHandle ("kernel32.dll"), "ProcessIdToSessionId");
+  if (!processIdToSessionId || !processIdToSessionId (GetCurrentProcessId (), &session_id))
+    session_id = 0;
+
+  display_name = g_strdup_printf ("%ld\\%s\\%s",
+                                 session_id,
+                                 window_station_name,
+                                 desktop_name);
+
+  GDK_NOTE (MISC, g_print ("gdk_win32_display_get_name: %s\n", display_name));
+
+  display_name_cache = display_name;
+
+  return display_name_cache;
 }
 
-gint
-gdk_display_get_n_screens (GdkDisplay *display)
+static gint
+gdk_win32_display_get_n_screens (GdkDisplay *display)
 {
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
+
   return 1;
 }
 
-GdkScreen *
-gdk_display_get_screen (GdkDisplay *display,
-                       gint        screen_num)
+static GdkScreen *
+gdk_win32_display_get_screen (GdkDisplay *display,
+                             gint        screen_num)
 {
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+  g_return_val_if_fail (screen_num == 0, NULL);
+
   return _gdk_screen;
 }
 
-GdkScreen *
-gdk_display_get_default_screen (GdkDisplay *display)
+static GdkScreen *
+gdk_win32_display_get_default_screen (GdkDisplay *display)
 {
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
+
   return _gdk_screen;
 }
 
-GdkWindow *
-gdk_display_get_default_group (GdkDisplay *display)
+static GdkWindow *
+gdk_win32_display_get_default_group (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
@@ -235,8 +335,8 @@ gdk_display_get_default_group (GdkDisplay *display)
   return NULL;
 }
 
-gboolean 
-gdk_display_supports_selection_notification (GdkDisplay *display)
+static gboolean
+gdk_win32_display_supports_selection_notification (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
 
@@ -244,114 +344,174 @@ gdk_display_supports_selection_notification (GdkDisplay *display)
 }
 
 static HWND _hwnd_next_viewer = NULL;
+static int debug_indent = 0;
 
 /*
  * maybe this should be integrated with the default message loop - or maybe not ;-)
  */
 static LRESULT CALLBACK
-_win32_on_clipboard_change (HWND   hwnd,
-                            UINT   message,
-                            WPARAM wparam,
-                            LPARAM lparam)
+inner_clipboard_window_procedure (HWND   hwnd,
+                                  UINT   message,
+                                  WPARAM wparam,
+                                  LPARAM lparam)
 {
   switch (message)
     {
-    case WM_DESTROY : /* remove us from chain */
+    case WM_DESTROY: /* remove us from chain */
       {
         ChangeClipboardChain (hwnd, _hwnd_next_viewer);
-        return 0; 
+        PostQuitMessage (0);
+        return 0;
       }
-    case WM_CHANGECBCHAIN :
+    case WM_CHANGECBCHAIN:
       {
         HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
         HWND hwndNext   = (HWND) lparam; /* handle of next window in chain */
+
         if (hwndRemove == _hwnd_next_viewer)
           _hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
+        else if (_hwnd_next_viewer != NULL)
+          return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
+
         return 0;
       }
-    case WM_DRAWCLIPBOARD :
+#ifdef WM_CLIPBOARDUPDATE
+    case WM_CLIPBOARDUPDATE:
+#endif
+    case WM_DRAWCLIPBOARD:
       {
-        /* create the appropriate gdk events */
-        HWND hwndOwner = GetClipboardOwner ();
+        int success;
+        HWND hwndOwner;
+#ifdef G_ENABLE_DEBUG
         UINT nFormat = 0;
-        int n = 0;
-
-        if (OpenClipboard (hwnd))
-          { 
-            for (; 0 != (nFormat = EnumClipboardFormats (nFormat)); )
-              {
-                char sFormat[80];
-                if (GetClipboardFormatName (nFormat, sFormat, 80) > 0)
-                  g_print ("%s ", sFormat);
-                n++; /* do something useful ? */
-              }
-            GDK_NOTE (DND, 
-                      g_print ("WM_DRAWCLIPBOARD :  formats %d owner %#lx\n", n, hwndOwner));
-
-            CloseClipboard ();
+#endif
+        GdkEvent *event;
+        GdkWindow *owner;
+
+        success = OpenClipboard (hwnd);
+        g_return_val_if_fail (success, 0);
+        hwndOwner = GetClipboardOwner ();
+        owner = gdk_win32_window_lookup_for_display (_gdk_display, hwndOwner);
+        if (owner == NULL)
+          owner = gdk_win32_window_foreign_new_for_display (_gdk_display, hwndOwner);
+
+        GDK_NOTE (DND, g_print (" drawclipboard owner: %p", hwndOwner));
+
+#ifdef G_ENABLE_DEBUG
+        if (_gdk_debug_flags & GDK_DEBUG_DND)
+          {
+            while ((nFormat = EnumClipboardFormats (nFormat)) != 0)
+              g_print ("%s ", _gdk_win32_cf_to_string (nFormat));
           }
-        /* XXX: generate the apropriate GdkEventOwnerChange ... */
+#endif
+
+        GDK_NOTE (DND, g_print (" \n"));
+
+
+        event = gdk_event_new (GDK_OWNER_CHANGE);
+        event->owner_change.window = _gdk_root;
+        event->owner_change.owner = owner;
+        event->owner_change.reason = GDK_OWNER_CHANGE_NEW_OWNER;
+        event->owner_change.selection = GDK_SELECTION_CLIPBOARD;
+        event->owner_change.time = _gdk_win32_get_next_tick (0);
+        event->owner_change.selection_time = GDK_CURRENT_TIME;
+        _gdk_win32_append_event (event);
 
-        /* don't break the chain */
-        return PostMessage (_hwnd_next_viewer, message, wparam, lparam);
+        CloseClipboard ();
+
+        if (_hwnd_next_viewer != NULL)
+          return SendMessage (_hwnd_next_viewer, message, wparam, lparam);
+
+        /* clear error to avoid confusing SetClipboardViewer() return */
+        SetLastError (0);
+        return 0;
       }
-    default :
+    default:
+      /* Otherwise call DefWindowProcW(). */
+      GDK_NOTE (EVENTS, g_print (" DefWindowProcW"));
       return DefWindowProc (hwnd, message, wparam, lparam);
     }
 }
 
+static LRESULT CALLBACK
+_clipboard_window_procedure (HWND   hwnd,
+                             UINT   message,
+                             WPARAM wparam,
+                             LPARAM lparam)
+{
+  LRESULT retval;
+
+  GDK_NOTE (EVENTS, g_print ("%s%*s%s %p",
+                            (debug_indent > 0 ? "\n" : ""),
+                            debug_indent, "",
+                            _gdk_win32_message_to_string (message), hwnd));
+  debug_indent += 2;
+  retval = inner_clipboard_window_procedure (hwnd, message, wparam, lparam);
+  debug_indent -= 2;
+
+  GDK_NOTE (EVENTS, g_print (" => %I64d%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
+
+  return retval;
+}
+
 /*
  * Creates a hidden window and adds it to the clipboard chain
  */
-HWND
+static HWND
 _gdk_win32_register_clipboard_notification (void)
 {
-  WNDCLASS wclass;
+  WNDCLASS wclass = { 0, };
   HWND     hwnd;
   ATOM     klass;
 
-  memset (&wclass, 0, sizeof(WNDCLASS));
   wclass.lpszClassName = "GdkClipboardNotification";
-  wclass.lpfnWndProc   = _win32_on_clipboard_change;
+  wclass.lpfnWndProc   = _clipboard_window_procedure;
   wclass.hInstance     = _gdk_app_hmodule;
 
   klass = RegisterClass (&wclass);
   if (!klass)
     return NULL;
 
-  hwnd = CreateWindow (MAKEINTRESOURCE(klass),
+  hwnd = CreateWindow (MAKEINTRESOURCE (klass),
                        NULL, WS_POPUP,
                        0, 0, 0, 0, NULL, NULL,
                        _gdk_app_hmodule, NULL);
   if (!hwnd)
-    {
-      UnregisterClass (MAKEINTRESOURCE(klass), _gdk_app_hmodule);
-      return NULL;
-    }
+    goto failed;
+
+  SetLastError (0);
   _hwnd_next_viewer = SetClipboardViewer (hwnd);
+
+  if (_hwnd_next_viewer == NULL && GetLastError() != 0)
+    goto failed;
+
+  /* FIXME: http://msdn.microsoft.com/en-us/library/ms649033(v=VS.85).aspx */
+  /* This is only supported by Vista, and not yet by mingw64 */
+  /* if (AddClipboardFormatListener (hwnd) == FALSE) */
+  /*   goto failed; */
+
   return hwnd;
+
+failed:
+  g_critical ("Failed to install clipboard viewer");
+  UnregisterClass (MAKEINTRESOURCE (klass), _gdk_app_hmodule);
+  return NULL;
 }
 
-/*
- * The whole function would only make sense if the gdk/win32 clipboard
- * model is rewritten to do delayed rendering. Currently this is only
- * testcode and as noted in
- * http://mail.gnome.org/archives/gtk-devel-list/2004-May/msg00113.html
- * probably not worth bothering ;)
- */
-gboolean 
-gdk_display_request_selection_notification (GdkDisplay *display,
-                                            GdkAtom     selection)
+static gboolean 
+gdk_win32_display_request_selection_notification (GdkDisplay *display,
+                                                 GdkAtom     selection)
 
 {
   static HWND hwndViewer = NULL;
   gboolean ret = FALSE;
 
-  GDK_NOTE (DND, 
+  GDK_NOTE (DND,
             g_print ("gdk_display_request_selection_notification (..., %s)",
                      gdk_atom_name (selection)));
 
-  if (GDK_SELECTION_CLIPBOARD == selection)
+  if (selection == GDK_SELECTION_CLIPBOARD ||
+      selection == GDK_SELECTION_PRIMARY)
     {
       if (!hwndViewer)
         {
@@ -360,28 +520,193 @@ gdk_display_request_selection_notification (GdkDisplay *display,
         }
       ret = (hwndViewer != NULL);
     }
-  else if (GDK_SELECTION_PRIMARY == selection)
+  else
     {
-      /* seems to work by default ? */
-      GDK_NOTE (DND, g_print (" by default"));
-      ret = TRUE;
+      GDK_NOTE (DND, g_print (" unsupported"));
+      ret = FALSE;
     }
+
   GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));
   return ret;
 }
 
-gboolean
-gdk_display_supports_clipboard_persistence (GdkDisplay *display)
+static gboolean
+gdk_win32_display_supports_clipboard_persistence (GdkDisplay *display)
 {
   return FALSE;
 }
 
-void
-gdk_display_store_clipboard (GdkDisplay *display,
-                            GdkWindow  *clipboard_window,
-                            guint32     time_,
-                            GdkAtom    *targets,
-                            gint        n_targets)
+static void
+gdk_win32_display_store_clipboard (GdkDisplay    *display,
+                            GdkWindow     *clipboard_window,
+                            guint32        time_,
+                            const GdkAtom *targets,
+                            gint           n_targets)
+{
+}
+
+static gboolean 
+gdk_win32_display_supports_shapes (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  return TRUE;
+}
+
+static gboolean
+gdk_win32_display_supports_input_shapes (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  /* Not yet implemented. See comment in
+   * gdk_window_input_shape_combine_mask().
+   */
+
+  return FALSE;
+}
+
+static gboolean
+gdk_win32_display_supports_composite (GdkDisplay *display)
+{
+  return FALSE;
+}
+
+static void
+gdk_win32_display_beep (GdkDisplay *display)
+{
+  g_return_if_fail (display == gdk_display_get_default());
+  if (!MessageBeep (-1))
+    Beep(1000, 50);
+}
+
+static void
+gdk_win32_display_flush (GdkDisplay * display)
+{
+  g_return_if_fail (display == _gdk_display);
+
+  GdiFlush ();
+}
+
+
+static void
+gdk_win32_display_sync (GdkDisplay * display)
+{
+  g_return_if_fail (display == _gdk_display);
+
+  GdiFlush ();
+}
+
+static void
+gdk_win32_display_dispose (GObject *object)
+{
+}
+
+static void
+gdk_win32_display_finalize (GObject *object)
+{
+}
+
+static void
+gdk_win32_display_init(GdkWin32Display *display)
+{
+}
+
+static void
+gdk_win32_display_before_process_all_updates (GdkDisplay  *display)
+{
+  /* nothing */
+}
+static void
+gdk_win32_display_after_process_all_updates (GdkDisplay  *display)
+{
+  /* nothing */
+}
+static void
+gdk_win32_display_notify_startup_complete (GdkDisplay  *display,
+                                           const gchar *startup_id)
+{
+  /* nothing */
+}
+static void
+gdk_win32_display_event_data_copy (GdkDisplay    *display,
+                                   const GdkEvent *src,
+                                   GdkEvent       *dst)
+{
+  /* nothing */
+}
+static void
+gdk_win32_display_event_data_free (GdkDisplay *display,
+                                   GdkEvent *event)
+{
+  /* nothing */
+}
+static void
+gdk_win32_display_push_error_trap (GdkDisplay *display)
+{
+  /* nothing */
+}
+static gint
+gdk_win32_display_pop_error_trap (GdkDisplay *display,
+                                 gboolean    ignored)
+{
+  return 0;
+}
+static void
+gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
 {
-  /* XXX: implement it (or maybe not as long as we don't support delayed rendering?) */
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (klass);
+
+  object_class->dispose = gdk_win32_display_dispose;
+  object_class->finalize = gdk_win32_display_finalize;
+
+  display_class->window_type = GDK_TYPE_WIN32_WINDOW;
+
+  display_class->get_name = gdk_win32_display_get_name;
+  display_class->get_n_screens = gdk_win32_display_get_n_screens;
+  display_class->get_screen = gdk_win32_display_get_screen;
+  display_class->get_default_screen = gdk_win32_display_get_default_screen;
+  display_class->beep = gdk_win32_display_beep;
+  display_class->sync = gdk_win32_display_sync;
+  display_class->flush = gdk_win32_display_flush;
+  display_class->has_pending = _gdk_win32_display_has_pending;
+  display_class->queue_events = _gdk_win32_display_queue_events;
+  display_class->get_default_group = gdk_win32_display_get_default_group;
+
+  display_class->supports_selection_notification = gdk_win32_display_supports_selection_notification;
+  display_class->request_selection_notification = gdk_win32_display_request_selection_notification;
+  display_class->supports_clipboard_persistence = gdk_win32_display_supports_clipboard_persistence;
+  display_class->store_clipboard = gdk_win32_display_store_clipboard;
+  display_class->supports_shapes = gdk_win32_display_supports_shapes;
+  display_class->supports_input_shapes = gdk_win32_display_supports_input_shapes;
+  display_class->supports_composite = gdk_win32_display_supports_composite;
+
+  display_class->list_devices = _gdk_win32_display_list_devices;
+  //? display_class->get_app_launch_context = _gdk_win32_display_get_app_launch_context;
+  display_class->get_cursor_for_type = _gdk_win32_display_get_cursor_for_type;
+  display_class->get_cursor_for_name = _gdk_win32_display_get_cursor_for_name;
+  display_class->get_cursor_for_pixbuf = _gdk_win32_display_get_cursor_for_pixbuf;
+  display_class->get_default_cursor_size = _gdk_win32_display_get_default_cursor_size;
+  display_class->get_maximal_cursor_size = _gdk_win32_display_get_maximal_cursor_size;
+  display_class->supports_cursor_alpha = _gdk_win32_display_supports_cursor_alpha;
+  display_class->supports_cursor_color = _gdk_win32_display_supports_cursor_color;
+
+  display_class->before_process_all_updates = gdk_win32_display_before_process_all_updates;
+  display_class->after_process_all_updates = gdk_win32_display_after_process_all_updates;
+  display_class->get_next_serial = gdk_win32_display_get_next_serial;
+  display_class->notify_startup_complete = gdk_win32_display_notify_startup_complete;
+  display_class->event_data_copy = gdk_win32_display_event_data_copy;
+  display_class->event_data_free = gdk_win32_display_event_data_free;
+  display_class->create_window_impl = _gdk_win32_display_create_window_impl;
+
+  display_class->get_keymap = _gdk_win32_display_get_keymap;
+  display_class->push_error_trap = gdk_win32_display_push_error_trap;
+  display_class->pop_error_trap = gdk_win32_display_pop_error_trap;
+  display_class->get_selection_owner = _gdk_win32_display_get_selection_owner;
+  display_class->set_selection_owner = _gdk_win32_display_set_selection_owner;
+  display_class->send_selection_notify = _gdk_win32_display_send_selection_notify;
+  display_class->get_selection_property = _gdk_win32_display_get_selection_property;
+  display_class->convert_selection = _gdk_win32_display_convert_selection;
+  display_class->text_property_to_utf8_list = _gdk_win32_display_text_property_to_utf8_list;
+  display_class->utf8_to_string_target = _gdk_win32_display_utf8_to_string_target;
 }