Fix bugs that crashed gdk_display_close() on x11
* _gdk_device_set_associated_device() did not allow NULL device * GdkDisplay should dispose device manager to avoid devices trying to touch the display in finalize * GdkDeviceManagerXI did not ref devices in id hash * GdkDisplayX11 did not ref devices in ->input_devices
This commit is contained in:
		
				
					committed by
					
						
						Matthias Clasen
					
				
			
			
				
	
			
			
			
						parent
						
							b837ef5a6d
						
					
				
				
					commit
					c7d73ee587
				
			@ -766,7 +766,7 @@ _gdk_device_set_associated_device (GdkDevice *device,
 | 
			
		||||
  GdkDevicePrivate *priv;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (GDK_IS_DEVICE (device));
 | 
			
		||||
  g_return_if_fail (GDK_IS_DEVICE (associated));
 | 
			
		||||
  g_return_if_fail (associated == NULL || GDK_IS_DEVICE (associated));
 | 
			
		||||
 | 
			
		||||
  priv = device->priv;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -278,7 +278,7 @@ gdk_display_dispose (GObject *object)
 | 
			
		||||
 | 
			
		||||
  _gdk_displays = g_slist_remove (_gdk_displays, object);
 | 
			
		||||
 | 
			
		||||
  if (gdk_display_get_default() == display)
 | 
			
		||||
  if (gdk_display_get_default () == display)
 | 
			
		||||
    {
 | 
			
		||||
      if (_gdk_displays)
 | 
			
		||||
        gdk_display_manager_set_default_display (gdk_display_manager_get(),
 | 
			
		||||
@ -289,7 +289,13 @@ gdk_display_dispose (GObject *object)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (device_manager)
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, object);
 | 
			
		||||
    {
 | 
			
		||||
      /* this is to make it drop devices which may require using the X
 | 
			
		||||
       * display and therefore can't be cleaned up in finalize.
 | 
			
		||||
       * It will also disconnect device_removed_cb
 | 
			
		||||
       */
 | 
			
		||||
      g_object_run_dispose (G_OBJECT (display->device_manager));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -53,6 +53,8 @@ _gdk_device_manager_new (GdkDisplay *display)
 | 
			
		||||
            {
 | 
			
		||||
              GdkDeviceManagerXI2 *device_manager_xi2;
 | 
			
		||||
 | 
			
		||||
              GDK_NOTE (INPUT, g_print ("Creating XI2 device manager\n"));
 | 
			
		||||
 | 
			
		||||
              device_manager_xi2 = g_object_new (GDK_TYPE_DEVICE_MANAGER_XI2,
 | 
			
		||||
                                                 "display", display,
 | 
			
		||||
                                                 NULL);
 | 
			
		||||
@ -62,14 +64,20 @@ _gdk_device_manager_new (GdkDisplay *display)
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
#endif /* XINPUT_2 */
 | 
			
		||||
            return g_object_new (GDK_TYPE_DEVICE_MANAGER_XI,
 | 
			
		||||
                                 "display", display,
 | 
			
		||||
                                 "event-base", firstevent,
 | 
			
		||||
                                 NULL);
 | 
			
		||||
            {
 | 
			
		||||
              GDK_NOTE (INPUT, g_print ("Creating XI device manager\n"));
 | 
			
		||||
 | 
			
		||||
              return g_object_new (GDK_TYPE_DEVICE_MANAGER_XI,
 | 
			
		||||
                                   "display", display,
 | 
			
		||||
                                   "event-base", firstevent,
 | 
			
		||||
                                   NULL);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
#endif /* XINPUT_2 || XINPUT_XFREE */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  GDK_NOTE (INPUT, g_print ("Creating core device manager\n"));
 | 
			
		||||
 | 
			
		||||
  return g_object_new (GDK_TYPE_DEVICE_MANAGER_CORE,
 | 
			
		||||
                       "display", display,
 | 
			
		||||
                       NULL);
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@ struct _GdkDeviceManagerXIPrivate
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void gdk_device_manager_xi_constructed  (GObject      *object);
 | 
			
		||||
static void gdk_device_manager_xi_finalize     (GObject      *object);
 | 
			
		||||
static void gdk_device_manager_xi_dispose      (GObject      *object);
 | 
			
		||||
static void gdk_device_manager_xi_set_property (GObject      *object,
 | 
			
		||||
                                                guint         prop_id,
 | 
			
		||||
                                                const GValue *value,
 | 
			
		||||
@ -72,7 +72,7 @@ gdk_device_manager_xi_class_init (GdkDeviceManagerXIClass *klass)
 | 
			
		||||
  GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->constructed = gdk_device_manager_xi_constructed;
 | 
			
		||||
  object_class->finalize = gdk_device_manager_xi_finalize;
 | 
			
		||||
  object_class->dispose = gdk_device_manager_xi_dispose;
 | 
			
		||||
  object_class->set_property = gdk_device_manager_xi_set_property;
 | 
			
		||||
  object_class->get_property = gdk_device_manager_xi_get_property;
 | 
			
		||||
 | 
			
		||||
@ -279,7 +279,7 @@ gdk_device_manager_xi_constructed (GObject *object)
 | 
			
		||||
          priv->devices = g_list_prepend (priv->devices, device);
 | 
			
		||||
          g_hash_table_insert (priv->id_table,
 | 
			
		||||
                               GINT_TO_POINTER (devices[i].id),
 | 
			
		||||
                               device);
 | 
			
		||||
                               g_object_ref (device));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -294,7 +294,7 @@ gdk_device_manager_xi_constructed (GObject *object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_device_manager_xi_finalize (GObject *object)
 | 
			
		||||
gdk_device_manager_xi_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  GdkDeviceManagerXIPrivate *priv;
 | 
			
		||||
 | 
			
		||||
@ -302,12 +302,17 @@ gdk_device_manager_xi_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (priv->devices, (GFunc) g_object_unref, NULL);
 | 
			
		||||
  g_list_free (priv->devices);
 | 
			
		||||
  priv->devices = NULL;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (priv->id_table);
 | 
			
		||||
  if (priv->id_table != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      g_hash_table_destroy (priv->id_table);
 | 
			
		||||
      priv->id_table = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  gdk_window_remove_filter (NULL, window_input_info_filter, object);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->finalize (object);
 | 
			
		||||
  G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void    gdk_device_manager_xi2_constructed (GObject *object);
 | 
			
		||||
static void    gdk_device_manager_xi2_finalize    (GObject *object);
 | 
			
		||||
static void    gdk_device_manager_xi2_dispose     (GObject *object);
 | 
			
		||||
 | 
			
		||||
static GList * gdk_device_manager_xi2_list_devices (GdkDeviceManager *device_manager,
 | 
			
		||||
                                                    GdkDeviceType     type);
 | 
			
		||||
@ -63,7 +63,7 @@ gdk_device_manager_xi2_class_init (GdkDeviceManagerXI2Class *klass)
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->constructed = gdk_device_manager_xi2_constructed;
 | 
			
		||||
  object_class->finalize = gdk_device_manager_xi2_finalize;
 | 
			
		||||
  object_class->dispose = gdk_device_manager_xi2_dispose;
 | 
			
		||||
 | 
			
		||||
  device_manager_class->list_devices = gdk_device_manager_xi2_list_devices;
 | 
			
		||||
  device_manager_class->get_client_pointer = gdk_device_manager_xi2_get_client_pointer;
 | 
			
		||||
@ -258,7 +258,7 @@ add_device (GdkDeviceManagerXI2 *device_manager,
 | 
			
		||||
 | 
			
		||||
  g_hash_table_replace (device_manager->id_table,
 | 
			
		||||
                        GINT_TO_POINTER (dev->deviceid),
 | 
			
		||||
                        device);
 | 
			
		||||
                        g_object_ref (device));
 | 
			
		||||
 | 
			
		||||
  if (dev->use == XIMasterPointer || dev->use == XIMasterKeyboard)
 | 
			
		||||
    device_manager->master_devices = g_list_append (device_manager->master_devices, device);
 | 
			
		||||
@ -373,7 +373,7 @@ gdk_device_manager_xi2_constructed (GObject *object)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
gdk_device_manager_xi2_finalize (GObject *object)
 | 
			
		||||
gdk_device_manager_xi2_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  GdkDeviceManagerXI2 *device_manager_xi2;
 | 
			
		||||
 | 
			
		||||
@ -381,16 +381,23 @@ gdk_device_manager_xi2_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (device_manager_xi2->master_devices, (GFunc) g_object_unref, NULL);
 | 
			
		||||
  g_list_free (device_manager_xi2->master_devices);
 | 
			
		||||
  device_manager_xi2->master_devices = NULL;
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (device_manager_xi2->slave_devices, (GFunc) g_object_unref, NULL);
 | 
			
		||||
  g_list_free (device_manager_xi2->slave_devices);
 | 
			
		||||
  device_manager_xi2->slave_devices = NULL;
 | 
			
		||||
 | 
			
		||||
  g_list_foreach (device_manager_xi2->floating_devices, (GFunc) g_object_unref, NULL);
 | 
			
		||||
  g_list_free (device_manager_xi2->floating_devices);
 | 
			
		||||
  device_manager_xi2->floating_devices = NULL;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (device_manager_xi2->id_table);
 | 
			
		||||
  if (device_manager_xi2->id_table)
 | 
			
		||||
    {
 | 
			
		||||
      g_hash_table_destroy (device_manager_xi2->id_table);
 | 
			
		||||
      device_manager_xi2->id_table = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (gdk_device_manager_xi2_parent_class)->finalize (object);
 | 
			
		||||
  G_OBJECT_CLASS (gdk_device_manager_xi2_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GList *
 | 
			
		||||
 | 
			
		||||
@ -1154,7 +1154,8 @@ _gdk_input_init (GdkDisplay *display)
 | 
			
		||||
      if (device->source == GDK_SOURCE_KEYBOARD)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      display_x11->input_devices = g_list_prepend (display_x11->input_devices, l->data);
 | 
			
		||||
      display_x11->input_devices = g_list_prepend (display_x11->input_devices,
 | 
			
		||||
                                                   g_object_ref (l->data));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (list);
 | 
			
		||||
@ -1176,7 +1177,8 @@ _gdk_input_init (GdkDisplay *display)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Add the core pointer to the devices list */
 | 
			
		||||
  display_x11->input_devices = g_list_prepend (display_x11->input_devices, display->core_pointer);
 | 
			
		||||
  display_x11->input_devices = g_list_prepend (display_x11->input_devices,
 | 
			
		||||
                                               g_object_ref (display->core_pointer));
 | 
			
		||||
 | 
			
		||||
  g_list_free (list);
 | 
			
		||||
}
 | 
			
		||||
@ -1449,8 +1451,7 @@ gdk_display_open (const gchar *display_name)
 | 
			
		||||
    _gdk_x11_screen_setup (display_x11->screens[i]);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit_by_name (display, "opened");
 | 
			
		||||
  g_signal_emit_by_name (gdk_display_manager_get(),
 | 
			
		||||
			 "display_opened", display);
 | 
			
		||||
  g_signal_emit_by_name (gdk_display_manager_get (), "display-opened", display);
 | 
			
		||||
 | 
			
		||||
  return display;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -312,6 +312,11 @@ gdk_event_source_dispatch (GSource     *source,
 | 
			
		||||
static void
 | 
			
		||||
gdk_event_source_finalize (GSource *source)
 | 
			
		||||
{
 | 
			
		||||
  GdkEventSource *event_source = (GdkEventSource *)source;
 | 
			
		||||
 | 
			
		||||
  g_list_free (event_source->translators);
 | 
			
		||||
  event_source->translators = NULL;
 | 
			
		||||
 | 
			
		||||
  event_sources = g_list_remove (event_sources, source);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user