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.
This commit is contained in:
Michael Natterer 2018-05-10 14:18:59 +02:00
parent 577e01d48a
commit 3ced1e18f4
2 changed files with 46 additions and 9 deletions

View File

@ -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)
{

View File

@ -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