[gtk+] GDK: Use GdkCursor objects to keep track of W32 cursors, not HCURSOR



commit 641fbd86d796bb0f7838b1d7387031a106386439
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date:   Sun May 3 21:29:35 2015 +0000

    GDK: Use GdkCursor objects to keep track of W32 cursors, not HCURSOR
    
    In particular this means that cursors are disposed of by the way of
    g_object_unref(), not DestroyCursor (which is documented to not to be
    used on certain kinds of cursors, and we can't tell which is which).
    
    It should also alleviate any concerns about destroying cursors that
    are still in use by other windows, except for cases where we would
    somehow get our hands on a HCURSOR that someone else is using and we
    make a GdkCursor out of it and later unref and finalize it while it
    is still in use.
    
    It also removes the need to call CopyCursor(), which makes animated
    cursors into non-animated ones as a side-effect (supposed to be a bug,
    but try explaining that to MS). Now cursors should be animated (if
    the are set up as such in the OS).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697477

 gdk/win32/gdkdevice-virtual.c |   60 +++++++++++++++--------------------------
 gdk/win32/gdkevents-win32.c   |   26 +++++++++---------
 gdk/win32/gdkprivate-win32.h  |    2 +-
 gdk/win32/gdkwindow-win32.c   |   49 +++++++--------------------------
 gdk/win32/gdkwindow-win32.h   |    2 +-
 5 files changed, 47 insertions(+), 92 deletions(-)
---
diff --git a/gdk/win32/gdkdevice-virtual.c b/gdk/win32/gdkdevice-virtual.c
index 4371c16..2ed341f 100644
--- a/gdk/win32/gdkdevice-virtual.c
+++ b/gdk/win32/gdkdevice-virtual.c
@@ -157,30 +157,23 @@ gdk_device_virtual_set_window_cursor (GdkDevice *device,
                                      GdkWindow *window,
                                      GdkCursor *cursor)
 {
-  GdkWin32Cursor *cursor_private;
   GdkWindow *parent_window;
   GdkWindowImplWin32 *impl;
-  HCURSOR hcursor;
-  HCURSOR hprevcursor;
+  GdkCursor *replacement_cursor;
+  GdkCursor *previous_cursor;
 
   impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
-  cursor_private = (GdkWin32Cursor*) cursor;
 
-  hprevcursor = impl->hcursor;
+  previous_cursor = impl->cursor;
 
-  if (!cursor)
-    hcursor = NULL;
-  else
-    hcursor = cursor_private->hcursor;
-
-  if (hcursor != NULL)
+  if (cursor != NULL && GDK_WIN32_CURSOR (cursor)->hcursor != NULL)
     {
       /* If the pointer is over our window, set new cursor */
       GdkWindow *curr_window = gdk_window_get_device_position (window, device, NULL, NULL, NULL);
 
       if (curr_window == window ||
           (curr_window && window == gdk_window_get_toplevel (curr_window)))
-        SetCursor (hcursor);
+        SetCursor (GDK_WIN32_CURSOR (cursor)->hcursor);
       else
         {
           /* Climb up the tree and find whether our window is the
@@ -188,12 +181,12 @@ gdk_device_virtual_set_window_cursor (GdkDevice *device,
            * new cursor.
            */
           while (curr_window && curr_window->impl &&
-                 !GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->hcursor)
+                 !GDK_WINDOW_IMPL_WIN32 (curr_window->impl)->cursor)
             {
               curr_window = curr_window->parent;
               if (curr_window == GDK_WINDOW (window))
                 {
-                  SetCursor (hcursor);
+                  SetCursor (GDK_WIN32_CURSOR (cursor)->hcursor);
                   break;
                 }
             }
@@ -204,26 +197,26 @@ gdk_device_virtual_set_window_cursor (GdkDevice *device,
    * use before we destroy it, in case we're not over our window but
    * the cursor is still set to our old one.
    */
-  if (hprevcursor != NULL &&
-      GetCursor () == hprevcursor)
+  if (previous_cursor != NULL &&
+      GetCursor () == GDK_WIN32_CURSOR (previous_cursor)->hcursor)
     {
       /* Look for a suitable cursor to use instead */
-      hcursor = NULL;
+      replacement_cursor = NULL;
       parent_window = GDK_WINDOW (window)->parent;
 
-      while (hcursor == NULL)
+      while (replacement_cursor == NULL)
         {
           if (parent_window)
             {
               impl = GDK_WINDOW_IMPL_WIN32 (parent_window->impl);
-              hcursor = impl->hcursor;
+              replacement_cursor = impl->cursor;
               parent_window = parent_window->parent;
             }
           else
-            hcursor = LoadCursor (NULL, IDC_ARROW);
+            replacement_cursor = _gdk_win32_display_get_cursor_for_type (_gdk_display, GDK_LEFT_PTR);
         }
 
-      SetCursor (hcursor);
+      SetCursor (GDK_WIN32_CURSOR (replacement_cursor)->hcursor);
     }
 }
 
@@ -266,31 +259,22 @@ gdk_device_virtual_grab (GdkDevice    *device,
                         guint32       time_)
 {
   GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
-  HCURSOR hcursor;
-  GdkWin32Cursor *cursor_private;
-
-  cursor_private = (GdkWin32Cursor*) cursor;
 
   if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
     {
-      if (!cursor)
-       hcursor = NULL;
-      else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
-       WIN32_API_FAILED ("CopyCursor");
-
       if (_gdk_win32_grab_cursor != NULL)
        {
-         if (GetCursor () == _gdk_win32_grab_cursor)
+         if (GetCursor () == GDK_WIN32_CURSOR (_gdk_win32_grab_cursor)->hcursor)
            SetCursor (NULL);
-         DestroyCursor (_gdk_win32_grab_cursor);
+         g_clear_object (&_gdk_win32_grab_cursor);
        }
 
-      _gdk_win32_grab_cursor = hcursor;
+      _gdk_win32_grab_cursor = cursor;
 
       if (_gdk_win32_grab_cursor != NULL)
-       SetCursor (_gdk_win32_grab_cursor);
-      else if (impl->hcursor != NULL)
-       SetCursor (impl->hcursor);
+       SetCursor (GDK_WIN32_CURSOR (_gdk_win32_grab_cursor)->hcursor);
+      else if (impl->cursor != NULL)
+       SetCursor (GDK_WIN32_CURSOR (impl->cursor)->hcursor);
       else
        SetCursor (LoadCursor (NULL, IDC_ARROW));
 
@@ -317,9 +301,9 @@ gdk_device_virtual_ungrab (GdkDevice *device,
     {
       if (_gdk_win32_grab_cursor != NULL)
        {
-         if (GetCursor () == _gdk_win32_grab_cursor)
+         if (GetCursor () == GDK_WIN32_CURSOR (_gdk_win32_grab_cursor)->hcursor)
            SetCursor (NULL);
-         DestroyCursor (_gdk_win32_grab_cursor);
+         g_clear_object (&_gdk_win32_grab_cursor);
        }
       _gdk_win32_grab_cursor = NULL;
 
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index dc18405..eed1bc6 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -106,7 +106,7 @@ static gboolean gdk_event_dispatch (GSource     *source,
 static GList *client_filters;  /* Filters for client messages */
 extern gint       _gdk_input_ignore_core;
 
-HCURSOR _gdk_win32_grab_cursor;
+GdkCursor *_gdk_win32_grab_cursor;
 
 static GSourceFuncs event_funcs = {
   gdk_event_prepare,
@@ -1840,7 +1840,7 @@ gdk_event_translate (MSG  *msg,
   MINMAXINFO *mmi;
   LONG style;
   HWND hwnd;
-  HCURSOR hcursor;
+  GdkCursor *cursor;
   BYTE key_state[256];
   HIMC himc;
   WINDOWPOS *windowpos;
@@ -2633,19 +2633,19 @@ gdk_event_translate (MSG  *msg,
        break;
 
       if (grab_window != NULL && _gdk_win32_grab_cursor != NULL)
-       hcursor = _gdk_win32_grab_cursor;
-      else if (!GDK_WINDOW_DESTROYED (window))
-       hcursor = GDK_WINDOW_IMPL_WIN32 (window->impl)->hcursor;
+       cursor = _gdk_win32_grab_cursor;
+      else if (!GDK_WINDOW_DESTROYED (window) && GDK_WINDOW_IMPL_WIN32 (window->impl)->cursor != NULL)
+       cursor = GDK_WINDOW_IMPL_WIN32 (window->impl)->cursor;
       else
-       hcursor = NULL;
+       cursor = NULL;
 
-      if (hcursor != NULL)
-       {
-         GDK_NOTE (EVENTS, g_print (" (SetCursor(%p)", hcursor));
-         SetCursor (hcursor);
-         return_val = TRUE;
-         *ret_valp = TRUE;
-       }
+      if (cursor != NULL)
+        {
+         GDK_NOTE (EVENTS, g_print (" (SetCursor(%p)", cursor));
+         SetCursor (GDK_WIN32_CURSOR (cursor)->hcursor);
+          return_val = TRUE;
+          *ret_valp = TRUE;
+        }
       break;
 
     case WM_SYSCOMMAND:
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index 93166a9..98b64a3 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -361,7 +361,7 @@ extern GHashTable   *_format_atom_table;
 /* Hold the result of a delayed rendering */
 extern HGLOBAL         _delayed_rendering_data;
 
-extern HCURSOR _gdk_win32_grab_cursor;
+extern GdkCursor *_gdk_win32_grab_cursor;
 
 HGLOBAL _gdk_win32_selection_convert_to_dib (HGLOBAL  hdata,
                                             GdkAtom  target);
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 43fb2d0..765ae01 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -132,7 +132,7 @@ static void
 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
 {
   impl->toplevel_window_type = -1;
-  impl->hcursor = NULL;
+  impl->cursor = NULL;
   impl->hicon_big = NULL;
   impl->hicon_small = NULL;
   impl->hint_flags = 0;
@@ -160,14 +160,7 @@ gdk_window_impl_win32_finalize (GObject *object)
       gdk_win32_handle_table_remove (window_impl->handle);
     }
 
-  if (window_impl->hcursor != NULL)
-    {
-      if (GetCursor () == window_impl->hcursor)
-       SetCursor (NULL);
-
-      GDI_CALL (DestroyCursor, (window_impl->hcursor));
-      window_impl->hcursor = NULL;
-    }
+  g_clear_object (&window_impl->cursor);
 
   if (window_impl->hicon_big != NULL)
     {
@@ -1957,55 +1950,33 @@ gdk_win32_window_set_device_cursor (GdkWindow *window,
                                     GdkCursor *cursor)
 {
   GdkWindowImplWin32 *impl;
-  GdkWin32Cursor *cursor_private;
-  HCURSOR hcursor;
-  HCURSOR hprevcursor;
+  GdkCursor *previous_cursor;
 
   impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
-  cursor_private = (GdkWin32Cursor*) cursor;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (!cursor)
-    hcursor = NULL;
-  else
-    hcursor = cursor_private->hcursor;
-
   GDK_NOTE (MISC, g_print ("gdk_win32_window_set_cursor: %p: %p\n",
                           GDK_WINDOW_HWND (window),
-                          hcursor));
+                          cursor));
 
   /* First get the old cursor, if any (we wait to free the old one
    * since it may be the current cursor set in the Win32 API right
    * now).
    */
-  hprevcursor = impl->hcursor;
+  previous_cursor = impl->cursor;
 
   GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
 
-  if (hcursor == NULL)
-    impl->hcursor = NULL;
+  if (cursor)
+    impl->cursor = g_object_ref (cursor);
   else
-    {
-      /* We must copy the cursor as it is OK to destroy the GdkCursor
-       * while still in use for some window. See for instance
-       * gimp_change_win_cursor() which calls gdk_window_set_cursor
-       * (win, cursor), and immediately afterwards gdk_cursor_destroy
-       * (cursor).
-       */
-      if ((impl->hcursor = CopyCursor (hcursor)) == NULL)
-       WIN32_API_FAILED ("CopyCursor");
-      GDK_NOTE (MISC, g_print ("... CopyCursor (%p) = %p\n",
-                              hcursor, impl->hcursor));
-    }
+    impl->cursor = NULL;
 
   /* Destroy the previous cursor */
-  if (hprevcursor != NULL)
-    {
-      GDK_NOTE (MISC, g_print ("... DestroyCursor (%p)\n", hprevcursor));
-      API_CALL (DestroyCursor, (hprevcursor));
-    }
+  if (previous_cursor != NULL)
+    g_object_unref (previous_cursor);
 }
 
 static void
diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h
index bc1575c..8f17ead 100644
--- a/gdk/win32/gdkwindow-win32.h
+++ b/gdk/win32/gdkwindow-win32.h
@@ -55,7 +55,7 @@ struct _GdkWindowImplWin32
 
   gint8 toplevel_window_type;
 
-  HCURSOR hcursor;
+  GdkCursor *cursor;
   HICON   hicon_big;
   HICON   hicon_small;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]