wayland: Don't broadcast selection owner changes
When receiving a selection or when a drag icon enter a window, it was targeted at a specific window. Lets emit the GDK_OWNER_CHANGE event only for this window, instead of broadcasting. Broadcasting has some nasty side effects. For example, if there was n GdkWindows, and one would for every "owner-change" signal handler receive n signals about the owner being changed. An example of where this went a bit out of hand was gnome-terminal, which added one listener per terminal window. This meant that if one had m number of terminal windows, each time any one would loose or gain keyboard focus, O(m^2) owner-change events would be emitted. https://bugzilla.gnome.org/show_bug.cgi?id=754158
This commit is contained in:
		| @ -75,6 +75,7 @@ struct _GdkWaylandDeviceData | ||||
|   GdkModifierType button_modifiers; | ||||
|   GdkWindow *pointer_focus; | ||||
|   GdkWindow *keyboard_focus; | ||||
|   GdkAtom pending_selection; | ||||
|   struct wl_data_device *data_device; | ||||
|   double surface_x, surface_y; | ||||
|   uint32_t time; | ||||
| @ -669,21 +670,6 @@ emit_selection_owner_change (GdkWindow *window, | ||||
|   gdk_event_free (event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| emit_selection_owner_change_forall (GdkAtom atom) | ||||
| { | ||||
|   GdkDisplay *display = gdk_display_get_default (); | ||||
|   GdkScreen *screen = GDK_WAYLAND_DISPLAY (display)->screen; | ||||
|   GList *windows, *l; | ||||
|  | ||||
|   windows = gdk_screen_get_toplevel_windows (screen); | ||||
|  | ||||
|   for (l = windows; l; l = l->next) | ||||
|     emit_selection_owner_change (l->data, atom); | ||||
|  | ||||
|   g_list_free (windows); | ||||
| } | ||||
|  | ||||
| static void | ||||
| data_device_data_offer (void                  *data, | ||||
|                         struct wl_data_device *data_device, | ||||
| @ -744,7 +730,8 @@ data_device_enter (void                  *data, | ||||
|                                         GDK_CURRENT_TIME); | ||||
|  | ||||
|   gdk_wayland_selection_set_offer (device->display, selection, offer); | ||||
|   emit_selection_owner_change_forall (selection); | ||||
|  | ||||
|   emit_selection_owner_change (dest_window, selection); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @ -827,7 +814,16 @@ data_device_selection (void                  *data, | ||||
|  | ||||
|   selection = gdk_atom_intern_static_string ("CLIPBOARD"); | ||||
|   gdk_wayland_selection_set_offer (device->display, selection, offer); | ||||
|   emit_selection_owner_change_forall (selection); | ||||
|  | ||||
|   /* If we already have keyboard focus, the selection was targeted at the | ||||
|    * focused surface. If we don't we will receive keyboard focus directly after | ||||
|    * this, so lets wait and find out what window will get the focus before | ||||
|    * emitting the owner-changed event. | ||||
|    */ | ||||
|   if (device->keyboard_focus) | ||||
|     emit_selection_owner_change (device->keyboard_focus, selection); | ||||
|   else | ||||
|     device->pending_selection = selection; | ||||
| } | ||||
|  | ||||
| static const struct wl_data_device_listener data_device_listener = { | ||||
| @ -1163,6 +1159,13 @@ keyboard_handle_enter (void               *data, | ||||
|                        device, device->keyboard_focus)); | ||||
|  | ||||
|   _gdk_wayland_display_deliver_event (device->display, event); | ||||
|  | ||||
|   if (device->pending_selection != GDK_NONE) | ||||
|     { | ||||
|       emit_selection_owner_change (device->keyboard_focus, | ||||
|                                    device->pending_selection); | ||||
|       device->pending_selection = GDK_NONE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void stop_key_repeat (GdkWaylandDeviceData *device); | ||||
| @ -2231,6 +2234,8 @@ _gdk_wayland_device_manager_add_seat (GdkDeviceManager *device_manager, | ||||
|   device->foreign_dnd_window = create_foreign_dnd_window (display); | ||||
|   device->wl_seat = wl_seat; | ||||
|  | ||||
|   device->pending_selection = GDK_NONE; | ||||
|  | ||||
|   wl_seat_add_listener (device->wl_seat, &seat_listener, device); | ||||
|   wl_seat_set_user_data (device->wl_seat, device); | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jonas Ådahl
					Jonas Ådahl