mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
wayland: Handle pointer focus inhibition at the Clutter level
The MetaWaylandPointer used to put this together through MetaCursorTracker cursor visibility, and ClutterSeat-level inhibition API, applying the pointer focus changes due to visibility logically to Wayland clients. In order to make this work over all Clutter widgetry instead of just Wayland clients, make the ClutterSeat-level inhibition API control this feature at the ClutterStage picking level, and leave/enter the seat pointer as appropriate. By default, the seat pointer has (un)focus inhibited. The MetaCursorTracker has been made another player in unfocus inhibition, simply asking for the pointer to get its focus while the cursor is visible. This in practice means that picking code may return a NULL actor, some asserts and preconditions had to be changed to handle this, plus some test code slightly. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3420>
This commit is contained in:
parent
7a2411ce50
commit
09101e36f8
@ -1626,6 +1626,13 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
klass->deactivate = clutter_stage_real_deactivate;
|
||||
}
|
||||
|
||||
static void
|
||||
on_seat_unfocus_inhibited_changed (ClutterStage *stage,
|
||||
ClutterSeat *seat)
|
||||
{
|
||||
clutter_stage_repick_device (stage, clutter_seat_get_pointer (seat));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_init (ClutterStage *self)
|
||||
{
|
||||
@ -1633,6 +1640,7 @@ clutter_stage_init (ClutterStage *self)
|
||||
ClutterStagePrivate *priv;
|
||||
ClutterStageWindow *impl;
|
||||
ClutterBackend *backend;
|
||||
ClutterSeat *seat;
|
||||
GError *error;
|
||||
|
||||
/* a stage is a top-level object */
|
||||
@ -1686,6 +1694,12 @@ clutter_stage_init (ClutterStage *self)
|
||||
clutter_stage_set_title (self, g_get_prgname ());
|
||||
clutter_stage_set_key_focus (self, NULL);
|
||||
clutter_stage_set_viewport (self, geom.width, geom.height);
|
||||
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
g_signal_connect_object (seat, "is-unfocus-inhibited-changed",
|
||||
G_CALLBACK (on_seat_unfocus_inhibited_changed),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3568,29 +3582,37 @@ clutter_stage_pick_and_update_device (ClutterStage *stage,
|
||||
graphene_point_t point,
|
||||
uint32_t time_ms)
|
||||
{
|
||||
ClutterActor *new_actor;
|
||||
ClutterActor *new_actor = NULL;
|
||||
MtkRegion *clear_area = NULL;
|
||||
ClutterSeat *seat;
|
||||
|
||||
if ((flags & CLUTTER_DEVICE_UPDATE_IGNORE_CACHE) == 0)
|
||||
seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (sequence ||
|
||||
device != clutter_seat_get_pointer (seat) ||
|
||||
clutter_seat_is_unfocus_inhibited (seat))
|
||||
{
|
||||
if (clutter_stage_check_in_clear_area (stage, device,
|
||||
sequence, point))
|
||||
if ((flags & CLUTTER_DEVICE_UPDATE_IGNORE_CACHE) == 0)
|
||||
{
|
||||
clutter_stage_set_device_coords (stage, device,
|
||||
sequence, point);
|
||||
return clutter_stage_get_device_actor (stage, device, sequence);
|
||||
if (clutter_stage_check_in_clear_area (stage, device,
|
||||
sequence, point))
|
||||
{
|
||||
clutter_stage_set_device_coords (stage, device,
|
||||
sequence, point);
|
||||
return clutter_stage_get_device_actor (stage, device, sequence);
|
||||
}
|
||||
}
|
||||
|
||||
new_actor = _clutter_stage_do_pick (stage,
|
||||
point.x,
|
||||
point.y,
|
||||
CLUTTER_PICK_REACTIVE,
|
||||
&clear_area);
|
||||
|
||||
/* Picking should never fail, but if it does, we bail out here */
|
||||
g_return_val_if_fail (new_actor != NULL, NULL);
|
||||
}
|
||||
|
||||
new_actor = _clutter_stage_do_pick (stage,
|
||||
point.x,
|
||||
point.y,
|
||||
CLUTTER_PICK_REACTIVE,
|
||||
&clear_area);
|
||||
|
||||
/* Picking should never fail, but if it does, we bail out here */
|
||||
g_return_val_if_fail (new_actor != NULL, NULL);
|
||||
|
||||
clutter_stage_update_device (stage,
|
||||
device, sequence,
|
||||
source_device,
|
||||
@ -4393,7 +4415,9 @@ clutter_stage_emit_event (ClutterStage *self,
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (target_actor != NULL);
|
||||
if (!target_actor)
|
||||
return;
|
||||
|
||||
seat_grab_actor = priv->topmost_grab ? priv->topmost_grab->actor : CLUTTER_ACTOR (self);
|
||||
|
||||
is_sequence_begin =
|
||||
|
@ -55,6 +55,7 @@ typedef struct _MetaCursorTrackerPrivate
|
||||
MetaBackend *backend;
|
||||
|
||||
gboolean is_showing;
|
||||
gboolean pointer_focus;
|
||||
|
||||
int track_position_count;
|
||||
|
||||
@ -531,6 +532,7 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
{
|
||||
MetaCursorTrackerPrivate *priv =
|
||||
meta_cursor_tracker_get_instance_private (tracker);
|
||||
ClutterSeat *seat;
|
||||
|
||||
if (visible == priv->is_showing)
|
||||
return;
|
||||
@ -539,6 +541,13 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
sync_cursor (tracker);
|
||||
|
||||
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
|
||||
if (priv->is_showing)
|
||||
clutter_seat_inhibit_unfocus (seat);
|
||||
else
|
||||
clutter_seat_uninhibit_unfocus (seat);
|
||||
}
|
||||
|
||||
MetaBackend *
|
||||
|
@ -662,6 +662,7 @@ grab_input_only (void)
|
||||
}
|
||||
|
||||
CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/grab/input-only", grab_input_only);
|
||||
CLUTTER_TEST_UNIT ("/grab/grab-under-pointer", grab_under_pointer)
|
||||
CLUTTER_TEST_UNIT ("/grab/grab-under-pointers-parent", grab_under_pointers_parent)
|
||||
CLUTTER_TEST_UNIT ("/grab/grab-outside-pointer", grab_outside_pointer)
|
||||
@ -672,5 +673,4 @@ CLUTTER_TEST_SUITE (
|
||||
CLUTTER_TEST_UNIT ("/grab/grab-unordered-ungrab-2", grab_unordered_ungrab_2)
|
||||
CLUTTER_TEST_UNIT ("/grab/key-focus-in-grab", grab_key_focus_in_grab);
|
||||
CLUTTER_TEST_UNIT ("/grab/key-focus-outside-grab", grab_key_focus_outside_grab);
|
||||
CLUTTER_TEST_UNIT ("/grab/input-only", grab_input_only);
|
||||
)
|
||||
|
@ -302,14 +302,9 @@ static void
|
||||
sync_focus_surface (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaBackend *backend = backend_from_pointer (pointer);
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
|
||||
if (clutter_stage_get_grab_actor (stage) != NULL ||
|
||||
(!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
|
||||
!clutter_seat_is_unfocus_inhibited (clutter_seat)))
|
||||
if (clutter_stage_get_grab_actor (stage) != NULL)
|
||||
{
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
return;
|
||||
@ -457,9 +452,6 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandPointer *pointer = grab->pointer;
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||
MetaBackend *backend = backend_from_pointer (pointer);
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
|
||||
if (!meta_wayland_seat_has_pointer (seat))
|
||||
@ -468,10 +460,6 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (clutter_stage_get_grab_actor (stage) != NULL)
|
||||
return;
|
||||
|
||||
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
|
||||
!clutter_seat_is_unfocus_inhibited (clutter_seat))
|
||||
return;
|
||||
|
||||
if (pointer->button_count > 0)
|
||||
return;
|
||||
|
||||
@ -537,16 +525,6 @@ meta_wayland_pointer_enable (MetaWaylandPointer *pointer)
|
||||
"cursor-changed",
|
||||
G_CALLBACK (meta_wayland_pointer_on_cursor_changed),
|
||||
pointer);
|
||||
|
||||
g_signal_connect_swapped (cursor_tracker,
|
||||
"visibility-changed",
|
||||
G_CALLBACK (sync_focus_surface),
|
||||
pointer);
|
||||
|
||||
g_signal_connect_swapped (clutter_seat,
|
||||
"is-unfocus-inhibited-changed",
|
||||
G_CALLBACK (sync_focus_surface),
|
||||
pointer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -554,8 +532,6 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaBackend *backend = backend_from_pointer (pointer);
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
|
||||
g_hash_table_foreach (pointer->pointer_clients,
|
||||
make_resources_inert_foreach,
|
||||
@ -565,14 +541,6 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
|
||||
(gpointer) meta_wayland_pointer_on_cursor_changed,
|
||||
pointer);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (cursor_tracker,
|
||||
sync_focus_surface,
|
||||
pointer);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (clutter_seat,
|
||||
sync_focus_surface,
|
||||
pointer);
|
||||
|
||||
if (pointer->cursor_surface)
|
||||
{
|
||||
g_clear_signal_handler (&pointer->cursor_surface_destroy_id,
|
||||
|
Loading…
Reference in New Issue
Block a user