Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix segfault in Wayland session during Alt-Tab when window focus mode is either 'Sloppy' or 'Mouse' (gdb backtrace attached) #680

Merged
merged 1 commit into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clutter/clutter/clutter-mutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ void clutter_stage_update_resource_scales (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_actor_has_damage (ClutterActor *actor);

CLUTTER_EXPORT
void clutter_stage_get_device_coords (ClutterStage *stage,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t *coords);
#undef __CLUTTER_H_INSIDE__

#endif /* __CLUTTER_MUTTER_H__ */
89 changes: 89 additions & 0 deletions clutter/clutter/clutter-stage.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ typedef struct _PickClipRecord
graphene_point_t vertex[4];
} PickClipRecord;

typedef struct _PointerDeviceEntry
{
ClutterStage *stage;
ClutterInputDevice *device;
ClutterEventSequence *sequence;
graphene_point_t coords;
ClutterActor *current_actor;
} PointerDeviceEntry;

struct _ClutterStagePrivate
{
/* the stage implementation */
Expand Down Expand Up @@ -147,6 +156,9 @@ struct _ClutterStagePrivate

gboolean needs_update;

GHashTable *pointer_devices;
GHashTable *touch_sequences;

guint redraw_pending : 1;
guint is_cursor_visible : 1;
guint throttle_motion_events : 1;
Expand Down Expand Up @@ -195,6 +207,7 @@ static const ClutterColor default_stage_color = { 255, 255, 255, 255 };

static void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
static void free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry);
static void free_pointer_device_entry (PointerDeviceEntry *entry);
static void capture_view_into (ClutterStage *stage,
gboolean paint,
ClutterStageView *view,
Expand Down Expand Up @@ -2010,6 +2023,9 @@ clutter_stage_finalize (GObject *object)
g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL);
g_queue_free (priv->event_queue);

g_hash_table_destroy (priv->pointer_devices);
g_hash_table_destroy (priv->touch_sequences);

g_free (priv->title);

g_array_free (priv->paint_volume_stack, TRUE);
Expand Down Expand Up @@ -2387,6 +2403,13 @@ clutter_stage_init (ClutterStage *self)
priv->sync_delay = -1;
priv->motion_events_enabled = TRUE;

priv->pointer_devices =
g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify) free_pointer_device_entry);
priv->touch_sequences =
g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify) free_pointer_device_entry);

clutter_actor_set_background_color (CLUTTER_ACTOR (self),
&default_stage_color);

Expand Down Expand Up @@ -4796,3 +4819,69 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
*view_scale = scale;
return TRUE;
}

static void
on_device_actor_reactive_changed (ClutterActor *actor,
GParamSpec *pspec,
PointerDeviceEntry *entry)
{
}

static void
on_device_actor_destroyed (ClutterActor *actor,
PointerDeviceEntry *entry)
{
/* Simply unset the current_actor pointer here, there's no need to
* unset has_pointer or to disconnect any signals because the actor
* is gone anyway.
* Also, as soon as the next repaint happens, a repick should be triggered
* and the PointerDeviceEntry will get updated again, so no need to
* trigger a repick here.
*/
entry->current_actor = NULL;
}


static void
free_pointer_device_entry (PointerDeviceEntry *entry)
{
if (entry->current_actor)
{
ClutterActor *actor = entry->current_actor;

g_signal_handlers_disconnect_by_func (actor,
G_CALLBACK (on_device_actor_reactive_changed),
entry);
g_signal_handlers_disconnect_by_func (actor,
G_CALLBACK (on_device_actor_destroyed),
entry);

_clutter_actor_set_has_pointer (actor, FALSE);
}

g_free (entry);
}

/**
* clutter_stage_get_device_coords: (skip):
*/
void
clutter_stage_get_device_coords (ClutterStage *stage,
ClutterInputDevice *device,
ClutterEventSequence *sequence,
graphene_point_t *coords)
{
ClutterStagePrivate *priv = stage->priv;
PointerDeviceEntry *entry = NULL;

g_return_if_fail (CLUTTER_IS_STAGE (stage));
g_return_if_fail (device != NULL);

if (sequence != NULL)
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
else
entry = g_hash_table_lookup (priv->pointer_devices, device);

if (entry && coords)
*coords = entry->coords;
}
1 change: 1 addition & 0 deletions debian/libmuffin0.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,7 @@ libmuffin-clutter-0.so.0 libmuffin0 #MINVER#
clutter_stage_get_capture_final_size@Base 5.3.0
clutter_stage_get_color@Base 5.3.0
clutter_stage_get_default@Base 5.3.0
clutter_stage_get_device_coords@Base 6.0.1
clutter_stage_get_frame_counter@Base 5.3.0
clutter_stage_get_key_focus@Base 5.3.0
clutter_stage_get_minimum_size@Base 5.3.0
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ if have_wayland
if xwayland_dep.found()
xwayland_path = xwayland_dep.get_pkgconfig_variable('xwayland')
else
xwayland_path = find_program('Xwayland').path()
xwayland_path = find_program('Xwayland').full_path()
endif
endif
cdata.set_quoted('XWAYLAND_PATH', xwayland_path)
Expand Down
18 changes: 12 additions & 6 deletions src/wayland/meta-wayland-pointer.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,10 +618,13 @@ repick_for_event (MetaWaylandPointer *pointer,
ClutterActor *actor;
MetaWaylandSurface *surface;

if (for_event)
actor = clutter_event_get_source (for_event);
if (!for_event)
return;

if (clutter_event_type (for_event) == CLUTTER_LEAVE)
actor = clutter_event_get_related (for_event);
else
actor = clutter_input_device_get_pointer_actor (pointer->device);
actor = clutter_event_get_source (for_event);

if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
{
Expand Down Expand Up @@ -938,6 +941,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,

if (surface != NULL)
{
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
struct wl_client *client = wl_resource_get_client (surface->resource);
graphene_point_t pos;
MetaWindow *focus_window;
Expand All @@ -949,7 +953,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
G_CALLBACK (focus_surface_destroyed),
pointer);

clutter_input_device_get_coords (pointer->device, NULL, &pos);
clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos);

focus_window = meta_wayland_surface_get_window (pointer->focus_surface);
if (focus_window)
Expand All @@ -960,7 +964,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,

pointer->focus_client =
meta_wayland_pointer_get_pointer_client (pointer, client);
if (pointer->focus_client)
if (pointer->focus_client && pointer->focus_surface)
{
pointer->focus_serial =
meta_wayland_input_device_next_serial (input_device);
Expand Down Expand Up @@ -1054,10 +1058,12 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
wl_fixed_t *sx,
wl_fixed_t *sy)
{
MetaBackend *backend = meta_get_backend ();
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
float xf = 0.0f, yf = 0.0f;
graphene_point_t pos;

clutter_input_device_get_coords (pointer->device, NULL, &pos);
clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos);
meta_wayland_surface_get_relative_coordinates (surface, pos.x, pos.y, &xf, &yf);

*sx = wl_fixed_from_double (xf);
Expand Down
13 changes: 8 additions & 5 deletions src/wayland/meta-wayland-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,12 +1566,15 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
float *sx,
float *sy)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role);
if (surface != NULL && surface->role)
{
MetaWaylandSurfaceRoleClass *surface_role_class =
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role);

surface_role_class->get_relative_coordinates (surface->role,
abs_x, abs_y,
sx, sy);
surface_role_class->get_relative_coordinates (surface->role,
abs_x, abs_y,
sx, sy);
}
}

void
Expand Down
Loading