core: Move window enter/leave to display

The following commits will make it possible to pass a NULL window to
display_handle_window_enter/leave to represent the cursor entering the
desktop. This means it can't be a method of the window class anymore.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3258>
This commit is contained in:
Sebastian Wick 2023-09-13 16:19:38 +02:00 committed by Marge Bot
parent c73e178a2d
commit 5a33b0075a
6 changed files with 172 additions and 167 deletions

View File

@ -353,3 +353,12 @@ gboolean meta_display_process_captured_input (MetaDisplay *display,
const ClutterEvent *event); const ClutterEvent *event);
void meta_display_cancel_input_capture (MetaDisplay *display); void meta_display_cancel_input_capture (MetaDisplay *display);
void meta_display_handle_window_enter (MetaDisplay *display,
MetaWindow *window,
uint32_t timestamp_ms,
int root_x,
int root_y);
void meta_display_handle_window_leave (MetaDisplay *display,
MetaWindow *window);

View File

@ -3803,3 +3803,156 @@ meta_display_flush_queued_window (MetaDisplay *display,
window_queue_func[queue_idx] (display, windows); window_queue_func[queue_idx] (display, windows);
} }
} }
typedef struct
{
MetaWindow *window;
int pointer_x;
int pointer_y;
} MetaFocusData;
static void
focus_mouse_mode (MetaWindow *window,
uint32_t timestamp_ms)
{
MetaDisplay *display = window->display;
if (window->override_redirect)
return;
if (window->type != META_WINDOW_DESKTOP)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s at time %u.", window->desc, timestamp_ms);
meta_window_focus (window, timestamp_ms);
if (meta_prefs_get_auto_raise ())
meta_display_queue_autoraise_callback (display, window);
else
meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled");
}
else
{
/* In mouse focus mode, we defocus when the mouse *enters*
* the DESKTOP window, instead of defocusing on LeaveNotify.
* This is because having the mouse enter override-redirect
* child windows unfortunately causes LeaveNotify events that
* we can't distinguish from the mouse actually leaving the
* toplevel window as we expect. But, since we filter out
* EnterNotify events on override-redirect windows, this
* alternative mechanism works great.
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE &&
display->focus_window != NULL)
{
meta_topic (META_DEBUG_FOCUS,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window",
display->focus_window->desc);
meta_display_unset_input_focus (display, timestamp_ms);
}
}
}
static gboolean
focus_on_pointer_rest_callback (gpointer data)
{
MetaFocusData *focus_data = data;
MetaWindow *window = focus_data->window;
MetaDisplay *display = window->display;
MetaBackend *backend = backend_from_display (display);
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
graphene_point_t point;
uint32_t timestamp_ms;
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
goto out;
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
if ((int) point.x != focus_data->pointer_x ||
(int) point.y != focus_data->pointer_y)
{
focus_data->pointer_x = point.x;
focus_data->pointer_y = point.y;
return G_SOURCE_CONTINUE;
}
if (!meta_window_has_pointer (window))
goto out;
timestamp_ms = meta_display_get_current_time_roundtrip (display);
focus_mouse_mode (window, timestamp_ms);
out:
display->focus_timeout_id = 0;
return G_SOURCE_REMOVE;
}
/* The interval, in milliseconds, we use in focus-follows-mouse
* mode to check whether the pointer has stopped moving after a
* crossing event.
*/
#define FOCUS_TIMEOUT_DELAY 25
static void
queue_pointer_rest_callback (MetaDisplay *display,
MetaWindow *window,
int pointer_x,
int pointer_y)
{
MetaFocusData *focus_data;
focus_data = g_new (MetaFocusData, 1);
focus_data->window = window;
focus_data->pointer_x = pointer_x;
focus_data->pointer_y = pointer_y;
g_clear_handle_id (&display->focus_timeout_id, g_source_remove);
display->focus_timeout_id =
g_timeout_add_full (G_PRIORITY_DEFAULT,
FOCUS_TIMEOUT_DELAY,
focus_on_pointer_rest_callback,
focus_data,
g_free);
g_source_set_name_by_id (display->focus_timeout_id,
"[mutter] focus_on_pointer_rest_callback");
}
void
meta_display_handle_window_enter (MetaDisplay *display,
MetaWindow *window,
uint32_t timestamp_ms,
int root_x,
int root_y)
{
switch (meta_prefs_get_focus_mode ())
{
case G_DESKTOP_FOCUS_MODE_SLOPPY:
case G_DESKTOP_FOCUS_MODE_MOUSE:
display->mouse_mode = TRUE;
if (window->type != META_WINDOW_DOCK)
{
if (meta_prefs_get_focus_change_on_pointer_rest())
queue_pointer_rest_callback (display, window, root_x, root_y);
else
focus_mouse_mode (window, timestamp_ms);
}
break;
case G_DESKTOP_FOCUS_MODE_CLICK:
break;
}
if (window->type == META_WINDOW_DOCK)
meta_window_raise (window);
}
void
meta_display_handle_window_leave (MetaDisplay *display,
MetaWindow *window)
{
if (window->type == META_WINDOW_DOCK && !window->has_focus)
meta_window_lower (window);
}

View File

@ -807,12 +807,6 @@ void meta_window_set_transient_for (MetaWindow *window,
void meta_window_set_opacity (MetaWindow *window, void meta_window_set_opacity (MetaWindow *window,
guint8 opacity); guint8 opacity);
void meta_window_handle_enter (MetaWindow *window,
guint32 timestamp,
guint root_x,
guint root_y);
void meta_window_handle_leave (MetaWindow *window);
void meta_window_handle_ungrabbed_event (MetaWindow *window, void meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event); const ClutterEvent *event);

View File

@ -7409,57 +7409,6 @@ meta_window_set_opacity (MetaWindow *window,
meta_compositor_window_opacity_changed (window->display->compositor, window); meta_compositor_window_opacity_changed (window->display->compositor, window);
} }
typedef struct
{
MetaWindow *window;
int pointer_x;
int pointer_y;
} MetaFocusData;
static void
mouse_mode_focus (MetaWindow *window,
guint32 timestamp)
{
MetaDisplay *display = window->display;
if (window->override_redirect)
return;
if (window->type != META_WINDOW_DESKTOP)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s at time %u.", window->desc, timestamp);
meta_window_focus (window, timestamp);
if (meta_prefs_get_auto_raise ())
meta_display_queue_autoraise_callback (display, window);
else
meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled");
}
else
{
/* In mouse focus mode, we defocus when the mouse *enters*
* the DESKTOP window, instead of defocusing on LeaveNotify.
* This is because having the mouse enter override-redirect
* child windows unfortunately causes LeaveNotify events that
* we can't distinguish from the mouse actually leaving the
* toplevel window as we expect. But, since we filter out
* EnterNotify events on override-redirect windows, this
* alternative mechanism works great.
*/
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
display->focus_window != NULL)
{
meta_topic (META_DEBUG_FOCUS,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window",
display->focus_window->desc);
meta_display_unset_input_focus (display, timestamp);
}
}
}
static gboolean static gboolean
window_has_pointer_wayland (MetaWindow *window) window_has_pointer_wayland (MetaWindow *window)
{ {
@ -7509,108 +7458,6 @@ meta_window_has_pointer (MetaWindow *window)
return window_has_pointer_x11 (window); return window_has_pointer_x11 (window);
} }
static gboolean
window_focus_on_pointer_rest_callback (gpointer data)
{
MetaFocusData *focus_data = data;
MetaWindow *window = focus_data->window;
MetaDisplay *display = window->display;
MetaBackend *backend = backend_from_window (window);
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
graphene_point_t point;
guint32 timestamp;
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
goto out;
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
if ((int) point.x != focus_data->pointer_x ||
(int) point.y != focus_data->pointer_y)
{
focus_data->pointer_x = point.x;
focus_data->pointer_y = point.y;
return G_SOURCE_CONTINUE;
}
if (!meta_window_has_pointer (window))
goto out;
timestamp = meta_display_get_current_time_roundtrip (display);
mouse_mode_focus (window, timestamp);
out:
display->focus_timeout_id = 0;
return G_SOURCE_REMOVE;
}
/* The interval, in milliseconds, we use in focus-follows-mouse
* mode to check whether the pointer has stopped moving after a
* crossing event.
*/
#define FOCUS_TIMEOUT_DELAY 25
static void
queue_focus_callback (MetaDisplay *display,
MetaWindow *window,
int pointer_x,
int pointer_y)
{
MetaFocusData *focus_data;
focus_data = g_new (MetaFocusData, 1);
focus_data->window = window;
focus_data->pointer_x = pointer_x;
focus_data->pointer_y = pointer_y;
g_clear_handle_id (&display->focus_timeout_id, g_source_remove);
display->focus_timeout_id =
g_timeout_add_full (G_PRIORITY_DEFAULT,
FOCUS_TIMEOUT_DELAY,
window_focus_on_pointer_rest_callback,
focus_data,
g_free);
g_source_set_name_by_id (display->focus_timeout_id,
"[mutter] window_focus_on_pointer_rest_callback");
}
void
meta_window_handle_enter (MetaWindow *window,
guint32 timestamp,
guint root_x,
guint root_y)
{
MetaDisplay *display = window->display;
switch (meta_prefs_get_focus_mode ())
{
case G_DESKTOP_FOCUS_MODE_SLOPPY:
case G_DESKTOP_FOCUS_MODE_MOUSE:
display->mouse_mode = TRUE;
if (window->type != META_WINDOW_DOCK)
{
if (meta_prefs_get_focus_change_on_pointer_rest())
queue_focus_callback (display, window, root_x, root_y);
else
mouse_mode_focus (window, timestamp);
}
break;
case G_DESKTOP_FOCUS_MODE_CLICK:
break;
}
if (window->type == META_WINDOW_DOCK)
meta_window_raise (window);
}
void
meta_window_handle_leave (MetaWindow *window)
{
if (window->type == META_WINDOW_DOCK && !window->has_focus)
meta_window_lower (window);
}
void void
meta_window_handle_ungrabbed_event (MetaWindow *window, meta_window_handle_ungrabbed_event (MetaWindow *window,
const ClutterEvent *event) const ClutterEvent *event)

View File

@ -713,7 +713,8 @@ meta_wayland_pointer_update (MetaWaylandPointer *pointer,
graphene_point_t pos; graphene_point_t pos;
clutter_event_get_coords (event, &pos.x, &pos.y); clutter_event_get_coords (event, &pos.x, &pos.y);
meta_window_handle_enter (focus_window, meta_display_handle_window_enter (focus_window->display,
focus_window,
clutter_event_get_time (event), clutter_event_get_time (event),
pos.x, pos.y); pos.x, pos.y);
} }

View File

@ -969,7 +969,8 @@ handle_input_xevent (MetaX11Display *x11_display,
!meta_is_wayland_compositor () && !meta_is_wayland_compositor () &&
enter_event->sourceid != enter_event->deviceid) enter_event->sourceid != enter_event->deviceid)
{ {
meta_window_handle_enter (window, meta_display_handle_window_enter (display,
window,
enter_event->time, enter_event->time,
enter_event->root_x, enter_event->root_x,
enter_event->root_y); enter_event->root_y);
@ -983,7 +984,7 @@ handle_input_xevent (MetaX11Display *x11_display,
enter_event->mode != XINotifyGrab && enter_event->mode != XINotifyGrab &&
enter_event->mode != XINotifyUngrab) enter_event->mode != XINotifyUngrab)
{ {
meta_window_handle_leave (window); meta_display_handle_window_leave (display, window);
} }
break; break;
case XI_FocusIn: case XI_FocusIn: