From 3ced1e18f44ed8a60f98743204fc94149e200659 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Thu, 10 May 2018 14:18:59 +0200 Subject: [PATCH] app: fix GimpDeviceManager to not add the same display twice Displays can be opened multiple times, which caused the device manager to try to add their devices multiple times (which gets prevented with warnings), and then remove the devices prematurely when the multiple-opened display gets closed the first time (which is even worse). Add a simple hash that keeps track of how often displays are open, and only add/remove their devices on first open and last close. This actually happened with gtk-inspector on the gtk3-port branch, but there is no reason this can't also happen in stable. --- app/widgets/gimpdevicemanager.c | 48 ++++++++++++++++++++++++++++----- app/widgets/gimpdevicemanager.h | 7 +++-- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/app/widgets/gimpdevicemanager.c b/app/widgets/gimpdevicemanager.c index b952bae115..4598bae270 100644 --- a/app/widgets/gimpdevicemanager.c +++ b/app/widgets/gimpdevicemanager.c @@ -44,18 +44,15 @@ enum }; -typedef struct _GimpDeviceManagerPrivate GimpDeviceManagerPrivate; struct _GimpDeviceManagerPrivate { Gimp *gimp; + GHashTable *displays; GimpDeviceInfo *current_device; }; -#define GET_PRIVATE(manager) \ - G_TYPE_INSTANCE_GET_PRIVATE (manager, \ - GIMP_TYPE_DEVICE_MANAGER, \ - GimpDeviceManagerPrivate) +#define GET_PRIVATE(obj) (((GimpDeviceManager *) (obj))->priv) static void gimp_device_manager_constructed (GObject *object); @@ -126,6 +123,12 @@ gimp_device_manager_class_init (GimpDeviceManagerClass *klass) static void gimp_device_manager_init (GimpDeviceManager *manager) { + manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, + GIMP_TYPE_DEVICE_MANAGER, + GimpDeviceManagerPrivate); + + manager->priv->displays = g_hash_table_new (g_direct_hash, + g_direct_equal); } static void @@ -183,6 +186,10 @@ gimp_device_manager_dispose (GObject *object) static void gimp_device_manager_finalize (GObject *object) { + GimpDeviceManagerPrivate *private = GET_PRIVATE (object); + + g_clear_pointer (&private->displays, g_hash_table_unref); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -297,7 +304,19 @@ gimp_device_manager_display_opened (GdkDisplayManager *disp_manager, GdkDisplay *gdk_display, GimpDeviceManager *manager) { - GList *list; + GimpDeviceManagerPrivate *private = GET_PRIVATE (manager); + GList *list; + gint count; + + count = GPOINTER_TO_INT (g_hash_table_lookup (private->displays, + gdk_display)); + + g_hash_table_insert (private->displays, gdk_display, + GINT_TO_POINTER (count + 1)); + + /* don't add the same display twice */ + if (count > 0) + return; /* create device info structures for present devices */ for (list = gdk_display_list_devices (gdk_display); list; list = list->next) @@ -317,7 +336,22 @@ gimp_device_manager_display_closed (GdkDisplay *gdk_display, gboolean is_error, GimpDeviceManager *manager) { - GList *list; + GimpDeviceManagerPrivate *private = GET_PRIVATE (manager); + GList *list; + gint count; + + count = GPOINTER_TO_INT (g_hash_table_lookup (private->displays, + gdk_display)); + + /* don't remove the same display twice */ + if (count > 1) + { + g_hash_table_insert (private->displays, gdk_display, + GINT_TO_POINTER (count - 1)); + return; + } + + g_hash_table_remove (private->displays, gdk_display); for (list = gdk_display_list_devices (gdk_display); list; list = list->next) { diff --git a/app/widgets/gimpdevicemanager.h b/app/widgets/gimpdevicemanager.h index 8bd723a468..b07eaa8e2e 100644 --- a/app/widgets/gimpdevicemanager.h +++ b/app/widgets/gimpdevicemanager.h @@ -36,11 +36,14 @@ G_BEGIN_DECLS #define GIMP_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DEVICE_MANAGER, GimpDeviceManagerClass)) -typedef struct _GimpDeviceManagerClass GimpDeviceManagerClass; +typedef struct _GimpDeviceManagerPrivate GimpDeviceManagerPrivate; +typedef struct _GimpDeviceManagerClass GimpDeviceManagerClass; struct _GimpDeviceManager { - GimpList parent_instance; + GimpList parent_instance; + + GimpDeviceManagerPrivate *priv; }; struct _GimpDeviceManagerClass