Skip to content

Commit b15de53

Browse files
authored
Fix segfault during Alt-Tab when window focus mode is either 'Sloppy' or 'Mouse' (gdb backtrace attached) (#680)
(gdb) bt #\0 meta_wayland_surface_get_relative_coordinates (surface=0x0, abs_x=719, abs_y=405, sx=0x7ffe15cea768, sy=0x7ffe15cea76c) at ../src/wayland/meta-wayland-surface.c:1569 #\1 0x00007fba6070ec62 in meta_wayland_pointer_get_relative_coordinates (pointer=pointer@entry=0x564387be1670, surface=surface@entry=0x0, sx=sx@entry=0x7ffe15cea7a8, sy=sy@entry=0x7ffe15cea7ac) at ../src/wayland/meta-wayland-pointer.c:1061 #\2 0x00007fba6070ef13 in meta_wayland_pointer_send_enter (surface=0x0, serial=38, pointer_resource=0x56438b2179e0, pointer=0x564387be1670) at ../src/wayland/meta-wayland-pointer.c:850 #\3 meta_wayland_pointer_broadcast_enter (surface=0x0, serial=38, pointer=0x564387be1670) at ../src/wayland/meta-wayland-pointer.c:875 #\4 meta_wayland_pointer_set_focus (pointer=0x564387be1670, surface=<optimized out>) at ../src/wayland/meta-wayland-pointer.c:967 #\5 0x00007fba6070f573 in repick_for_event (pointer=0x564387be1670, for_event=<optimized out>) at ../src/wayland/meta-wayland-pointer.c:640 #\6 0x00007fba6070f6df in meta_wayland_pointer_repick (pointer=<optimized out>) at ../src/wayland/meta-wayland-pointer.c:1048 #\7 0x00007fba60712799 in meta_wayland_seat_repick (seat=<optimized out>) at ../src/wayland/meta-wayland-seat.c:441 #\8 0x00007fba606b09a0 in meta_display_sync_wayland_input_focus (display=<optimized out>) at ../src/core/display.c:1457 #\9 0x00007fba606942a0 in meta_end_modal_for_plugin (compositor=0x564387f6fe10, plugin=0x564387beeae0, timestamp=140036) at ../src/compositor/compositor.c:495 #\10 0x00007fba6069bef8 in meta_plugin_end_modal (plugin=<optimized out>, timestamp=<optimized out>) at ../src/compositor/meta-plugin.c:187 #\11 0x00007fba60e719eb in cinnamon_global_end_modal (global=0x564387fef940, timestamp=140036) at ../src/cinnamon-global.c:1000 Soft rebase from Mutter 40.10: * Adding clutter_stage_get_device_coords() * Adding PointerDeviceEntry struct * Updating _ClutterStagePrivate struct * Cherry-pick for repick_for_event() * Cherry-pick and adding null-pointer check for meta_wayland_pointer_set_focus() * Cherry-pick for meta_wayland_pointer_get_relative_coordinates() * Add null checks for meta_wayland_surface_get_relative_coordinates() Fix meson.build warning: * path() -> full_path()
1 parent 28be835 commit b15de53

File tree

6 files changed

+116
-12
lines changed

6 files changed

+116
-12
lines changed

clutter/clutter/clutter-mutter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ void clutter_stage_update_resource_scales (ClutterStage *stage);
7878
CLUTTER_EXPORT
7979
gboolean clutter_actor_has_damage (ClutterActor *actor);
8080

81+
CLUTTER_EXPORT
82+
void clutter_stage_get_device_coords (ClutterStage *stage,
83+
ClutterInputDevice *device,
84+
ClutterEventSequence *sequence,
85+
graphene_point_t *coords);
8186
#undef __CLUTTER_H_INSIDE__
8287

8388
#endif /* __CLUTTER_MUTTER_H__ */

clutter/clutter/clutter-stage.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ typedef struct _PickClipRecord
9999
graphene_point_t vertex[4];
100100
} PickClipRecord;
101101

102+
typedef struct _PointerDeviceEntry
103+
{
104+
ClutterStage *stage;
105+
ClutterInputDevice *device;
106+
ClutterEventSequence *sequence;
107+
graphene_point_t coords;
108+
ClutterActor *current_actor;
109+
} PointerDeviceEntry;
110+
102111
struct _ClutterStagePrivate
103112
{
104113
/* the stage implementation */
@@ -147,6 +156,9 @@ struct _ClutterStagePrivate
147156

148157
gboolean needs_update;
149158

159+
GHashTable *pointer_devices;
160+
GHashTable *touch_sequences;
161+
150162
guint redraw_pending : 1;
151163
guint is_cursor_visible : 1;
152164
guint throttle_motion_events : 1;
@@ -195,6 +207,7 @@ static const ClutterColor default_stage_color = { 255, 255, 255, 255 };
195207

196208
static void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
197209
static void free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry);
210+
static void free_pointer_device_entry (PointerDeviceEntry *entry);
198211
static void capture_view_into (ClutterStage *stage,
199212
gboolean paint,
200213
ClutterStageView *view,
@@ -2010,6 +2023,9 @@ clutter_stage_finalize (GObject *object)
20102023
g_queue_foreach (priv->event_queue, (GFunc) clutter_event_free, NULL);
20112024
g_queue_free (priv->event_queue);
20122025

2026+
g_hash_table_destroy (priv->pointer_devices);
2027+
g_hash_table_destroy (priv->touch_sequences);
2028+
20132029
g_free (priv->title);
20142030

20152031
g_array_free (priv->paint_volume_stack, TRUE);
@@ -2387,6 +2403,13 @@ clutter_stage_init (ClutterStage *self)
23872403
priv->sync_delay = -1;
23882404
priv->motion_events_enabled = TRUE;
23892405

2406+
priv->pointer_devices =
2407+
g_hash_table_new_full (NULL, NULL,
2408+
NULL, (GDestroyNotify) free_pointer_device_entry);
2409+
priv->touch_sequences =
2410+
g_hash_table_new_full (NULL, NULL,
2411+
NULL, (GDestroyNotify) free_pointer_device_entry);
2412+
23902413
clutter_actor_set_background_color (CLUTTER_ACTOR (self),
23912414
&default_stage_color);
23922415

@@ -4796,3 +4819,69 @@ _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
47964819
*view_scale = scale;
47974820
return TRUE;
47984821
}
4822+
4823+
static void
4824+
on_device_actor_reactive_changed (ClutterActor *actor,
4825+
GParamSpec *pspec,
4826+
PointerDeviceEntry *entry)
4827+
{
4828+
}
4829+
4830+
static void
4831+
on_device_actor_destroyed (ClutterActor *actor,
4832+
PointerDeviceEntry *entry)
4833+
{
4834+
/* Simply unset the current_actor pointer here, there's no need to
4835+
* unset has_pointer or to disconnect any signals because the actor
4836+
* is gone anyway.
4837+
* Also, as soon as the next repaint happens, a repick should be triggered
4838+
* and the PointerDeviceEntry will get updated again, so no need to
4839+
* trigger a repick here.
4840+
*/
4841+
entry->current_actor = NULL;
4842+
}
4843+
4844+
4845+
static void
4846+
free_pointer_device_entry (PointerDeviceEntry *entry)
4847+
{
4848+
if (entry->current_actor)
4849+
{
4850+
ClutterActor *actor = entry->current_actor;
4851+
4852+
g_signal_handlers_disconnect_by_func (actor,
4853+
G_CALLBACK (on_device_actor_reactive_changed),
4854+
entry);
4855+
g_signal_handlers_disconnect_by_func (actor,
4856+
G_CALLBACK (on_device_actor_destroyed),
4857+
entry);
4858+
4859+
_clutter_actor_set_has_pointer (actor, FALSE);
4860+
}
4861+
4862+
g_free (entry);
4863+
}
4864+
4865+
/**
4866+
* clutter_stage_get_device_coords: (skip):
4867+
*/
4868+
void
4869+
clutter_stage_get_device_coords (ClutterStage *stage,
4870+
ClutterInputDevice *device,
4871+
ClutterEventSequence *sequence,
4872+
graphene_point_t *coords)
4873+
{
4874+
ClutterStagePrivate *priv = stage->priv;
4875+
PointerDeviceEntry *entry = NULL;
4876+
4877+
g_return_if_fail (CLUTTER_IS_STAGE (stage));
4878+
g_return_if_fail (device != NULL);
4879+
4880+
if (sequence != NULL)
4881+
entry = g_hash_table_lookup (priv->touch_sequences, sequence);
4882+
else
4883+
entry = g_hash_table_lookup (priv->pointer_devices, device);
4884+
4885+
if (entry && coords)
4886+
*coords = entry->coords;
4887+
}

debian/libmuffin0.symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,7 @@ libmuffin-clutter-0.so.0 libmuffin0 #MINVER#
11151115
clutter_stage_get_capture_final_size@Base 5.3.0
11161116
clutter_stage_get_color@Base 5.3.0
11171117
clutter_stage_get_default@Base 5.3.0
1118+
clutter_stage_get_device_coords@Base 6.0.1
11181119
clutter_stage_get_frame_counter@Base 5.3.0
11191120
clutter_stage_get_key_focus@Base 5.3.0
11201121
clutter_stage_get_minimum_size@Base 5.3.0

meson.build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ if have_wayland
388388
if xwayland_dep.found()
389389
xwayland_path = xwayland_dep.get_pkgconfig_variable('xwayland')
390390
else
391-
xwayland_path = find_program('Xwayland').path()
391+
xwayland_path = find_program('Xwayland').full_path()
392392
endif
393393
endif
394394
cdata.set_quoted('XWAYLAND_PATH', xwayland_path)

src/wayland/meta-wayland-pointer.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,10 +618,13 @@ repick_for_event (MetaWaylandPointer *pointer,
618618
ClutterActor *actor;
619619
MetaWaylandSurface *surface;
620620

621-
if (for_event)
622-
actor = clutter_event_get_source (for_event);
621+
if (!for_event)
622+
return;
623+
624+
if (clutter_event_type (for_event) == CLUTTER_LEAVE)
625+
actor = clutter_event_get_related (for_event);
623626
else
624-
actor = clutter_input_device_get_pointer_actor (pointer->device);
627+
actor = clutter_event_get_source (for_event);
625628

626629
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
627630
{
@@ -938,6 +941,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
938941

939942
if (surface != NULL)
940943
{
944+
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
941945
struct wl_client *client = wl_resource_get_client (surface->resource);
942946
graphene_point_t pos;
943947
MetaWindow *focus_window;
@@ -949,7 +953,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
949953
G_CALLBACK (focus_surface_destroyed),
950954
pointer);
951955

952-
clutter_input_device_get_coords (pointer->device, NULL, &pos);
956+
clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos);
953957

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

961965
pointer->focus_client =
962966
meta_wayland_pointer_get_pointer_client (pointer, client);
963-
if (pointer->focus_client)
967+
if (pointer->focus_client && pointer->focus_surface)
964968
{
965969
pointer->focus_serial =
966970
meta_wayland_input_device_next_serial (input_device);
@@ -1054,10 +1058,12 @@ meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
10541058
wl_fixed_t *sx,
10551059
wl_fixed_t *sy)
10561060
{
1061+
MetaBackend *backend = meta_get_backend ();
1062+
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
10571063
float xf = 0.0f, yf = 0.0f;
10581064
graphene_point_t pos;
10591065

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

10631069
*sx = wl_fixed_from_double (xf);

src/wayland/meta-wayland-surface.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,12 +1566,15 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
15661566
float *sx,
15671567
float *sy)
15681568
{
1569-
MetaWaylandSurfaceRoleClass *surface_role_class =
1570-
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role);
1569+
if (surface != NULL && surface->role)
1570+
{
1571+
MetaWaylandSurfaceRoleClass *surface_role_class =
1572+
META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role);
15711573

1572-
surface_role_class->get_relative_coordinates (surface->role,
1573-
abs_x, abs_y,
1574-
sx, sy);
1574+
surface_role_class->get_relative_coordinates (surface->role,
1575+
abs_x, abs_y,
1576+
sx, sy);
1577+
}
15751578
}
15761579

15771580
void

0 commit comments

Comments
 (0)