2014-03-20 15:29:30 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Havoc Pennington
|
|
|
|
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
|
|
|
|
* Copyright (C) 2003, 2004 Rob Adams
|
|
|
|
* Copyright (C) 2004-2006 Elijah Newren
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "core/events.h"
|
2014-08-05 08:11:59 -04:00
|
|
|
|
2014-10-09 04:40:26 -04:00
|
|
|
#include "backends/meta-cursor-tracker-private.h"
|
2022-02-23 10:09:28 -05:00
|
|
|
#include "backends/meta-dnd-private.h"
|
2021-04-19 09:22:57 -04:00
|
|
|
#include "backends/meta-idle-manager.h"
|
2021-11-17 17:31:11 -05:00
|
|
|
#include "compositor/compositor-private.h"
|
2019-06-13 14:18:27 -04:00
|
|
|
#include "compositor/meta-window-actor-private.h"
|
2018-07-10 04:36:24 -04:00
|
|
|
#include "core/display-private.h"
|
|
|
|
#include "core/window-private.h"
|
|
|
|
#include "meta/meta-backend.h"
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2022-06-01 04:06:55 -04:00
|
|
|
#ifdef HAVE_X11_CLIENT
|
|
|
|
#include "backends/x11/meta-backend-x11.h"
|
|
|
|
#include "backends/x11/meta-input-device-x11.h"
|
|
|
|
#endif
|
|
|
|
|
2014-06-11 16:08:33 -04:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
|
|
|
#include "backends/native/meta-backend-native.h"
|
|
|
|
#endif
|
2014-03-20 15:54:16 -04:00
|
|
|
|
2014-08-13 20:19:35 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
2014-06-11 16:08:33 -04:00
|
|
|
#include "wayland/meta-wayland-private.h"
|
2014-08-13 20:19:35 -04:00
|
|
|
#endif
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2015-07-01 09:49:33 -04:00
|
|
|
#define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \
|
|
|
|
(e)->type == CLUTTER_TOUCHPAD_PINCH || \
|
2021-04-16 02:57:55 -04:00
|
|
|
(e)->type == CLUTTER_TOUCHPAD_HOLD || \
|
2015-07-01 09:49:33 -04:00
|
|
|
(e)->type == CLUTTER_TOUCH_BEGIN || \
|
|
|
|
(e)->type == CLUTTER_TOUCH_UPDATE || \
|
|
|
|
(e)->type == CLUTTER_TOUCH_END || \
|
|
|
|
(e)->type == CLUTTER_TOUCH_CANCEL)
|
|
|
|
|
2016-03-10 11:51:46 -05:00
|
|
|
#define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \
|
|
|
|
(e)->type == CLUTTER_KEY_RELEASE)
|
|
|
|
|
2019-10-02 10:49:28 -04:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
EVENTS_UNFREEZE_SYNC,
|
|
|
|
EVENTS_UNFREEZE_REPLAY,
|
|
|
|
} EventsUnfreezeMethod;
|
|
|
|
|
2016-03-10 11:51:46 -05:00
|
|
|
static gboolean
|
2022-04-27 06:12:33 -04:00
|
|
|
stage_has_key_focus (MetaDisplay *display)
|
2016-03-10 11:51:46 -05:00
|
|
|
{
|
2022-04-27 06:12:33 -04:00
|
|
|
MetaContext *context = meta_display_get_context (display);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2016-03-10 11:51:46 -05:00
|
|
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
|
|
|
|
|
|
|
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == stage;
|
|
|
|
}
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
static gboolean
|
|
|
|
stage_has_grab (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
MetaContext *context = meta_display_get_context (display);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
|
|
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
|
|
|
|
|
|
|
return clutter_stage_get_grab_actor (CLUTTER_STAGE (stage)) != NULL;
|
|
|
|
}
|
|
|
|
|
2014-06-11 16:08:33 -04:00
|
|
|
static MetaWindow *
|
|
|
|
get_window_for_event (MetaDisplay *display,
|
2022-03-05 17:46:24 -05:00
|
|
|
const ClutterEvent *event,
|
|
|
|
ClutterActor *event_actor)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2022-10-21 06:56:24 -04:00
|
|
|
MetaWindowActor *window_actor;
|
|
|
|
|
|
|
|
if (stage_has_grab (display))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* Always use the key focused window for key events. */
|
|
|
|
if (IS_KEY_EVENT (event))
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2022-10-21 06:56:24 -04:00
|
|
|
return stage_has_key_focus (display) ? display->focus_window
|
|
|
|
: NULL;
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
2022-10-21 06:56:24 -04:00
|
|
|
|
|
|
|
window_actor = meta_window_actor_from_actor (event_actor);
|
|
|
|
if (window_actor)
|
|
|
|
return meta_window_actor_get_meta_window (window_actor);
|
|
|
|
else
|
|
|
|
return NULL;
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
|
|
|
|
2014-03-30 20:50:03 -04:00
|
|
|
static void
|
2022-04-27 06:12:33 -04:00
|
|
|
handle_idletime_for_event (MetaDisplay *display,
|
|
|
|
const ClutterEvent *event)
|
2014-03-30 20:50:03 -04:00
|
|
|
{
|
2022-04-27 06:12:33 -04:00
|
|
|
MetaContext *context = meta_display_get_context (display);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2021-04-19 09:22:57 -04:00
|
|
|
MetaIdleManager *idle_manager;
|
2014-03-30 20:50:03 -04:00
|
|
|
|
2020-02-05 10:42:26 -05:00
|
|
|
if (clutter_event_get_device (event) == NULL)
|
2018-03-20 05:59:04 -04:00
|
|
|
return;
|
2015-04-27 13:01:51 -04:00
|
|
|
|
2018-03-20 05:59:04 -04:00
|
|
|
if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
|
|
|
|
event->type == CLUTTER_ENTER ||
|
2020-12-07 21:38:14 -05:00
|
|
|
event->type == CLUTTER_LEAVE)
|
2018-03-20 05:59:04 -04:00
|
|
|
return;
|
2014-05-29 12:06:09 -04:00
|
|
|
|
2021-04-19 09:22:57 -04:00
|
|
|
idle_manager = meta_backend_get_idle_manager (backend);
|
|
|
|
meta_idle_manager_reset_idle_time (idle_manager);
|
2014-03-30 20:50:03 -04:00
|
|
|
}
|
|
|
|
|
2014-07-21 19:14:14 -04:00
|
|
|
static gboolean
|
|
|
|
sequence_is_pointer_emulated (MetaDisplay *display,
|
|
|
|
const ClutterEvent *event)
|
|
|
|
{
|
|
|
|
ClutterEventSequence *sequence;
|
|
|
|
|
|
|
|
sequence = clutter_event_get_event_sequence (event);
|
|
|
|
|
|
|
|
if (!sequence)
|
|
|
|
return FALSE;
|
|
|
|
|
2023-07-21 12:44:17 -04:00
|
|
|
if (clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_POINTER_EMULATED)
|
2014-07-21 19:14:14 -04:00
|
|
|
return TRUE;
|
|
|
|
|
2014-07-24 14:52:04 -04:00
|
|
|
#ifdef HAVE_NATIVE_BACKEND
|
2022-04-27 06:12:33 -04:00
|
|
|
MetaContext *context = meta_display_get_context (display);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2014-07-21 19:14:14 -04:00
|
|
|
|
|
|
|
/* When using Clutter's native input backend there is no concept of
|
|
|
|
* pointer emulating sequence, we still must make up our own to be
|
|
|
|
* able to implement single-touch (hence pointer alike) behavior.
|
|
|
|
*
|
|
|
|
* This is implemented similarly to X11, where only the first touch
|
|
|
|
* on screen gets the "pointer emulated" flag, and it won't get assigned
|
|
|
|
* to another sequence until the next first touch on an idle touchscreen.
|
|
|
|
*/
|
|
|
|
if (META_IS_BACKEND_NATIVE (backend))
|
|
|
|
{
|
|
|
|
MetaGestureTracker *tracker;
|
|
|
|
|
|
|
|
tracker = meta_display_get_gesture_tracker (display);
|
|
|
|
|
|
|
|
if (event->type == CLUTTER_TOUCH_BEGIN &&
|
|
|
|
meta_gesture_tracker_get_n_current_touches (tracker) == 0)
|
|
|
|
return TRUE;
|
|
|
|
}
|
2014-07-24 14:52:04 -04:00
|
|
|
#endif /* HAVE_NATIVE_BACKEND */
|
2014-07-21 19:14:14 -04:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2022-06-01 04:06:55 -04:00
|
|
|
#ifdef HAVE_X11_CLIENT
|
2019-10-02 10:49:28 -04:00
|
|
|
static void
|
|
|
|
maybe_unfreeze_pointer_events (MetaBackend *backend,
|
|
|
|
const ClutterEvent *event,
|
|
|
|
EventsUnfreezeMethod unfreeze_method)
|
|
|
|
{
|
2020-11-17 08:49:31 -05:00
|
|
|
ClutterInputDevice *device;
|
2019-10-02 10:49:28 -04:00
|
|
|
Display *xdisplay;
|
|
|
|
int event_mode;
|
|
|
|
int device_id;
|
|
|
|
|
|
|
|
if (event->type != CLUTTER_BUTTON_PRESS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!META_IS_BACKEND_X11 (backend))
|
|
|
|
return;
|
|
|
|
|
2020-11-17 08:49:31 -05:00
|
|
|
device = clutter_event_get_device (event);
|
2020-11-17 08:59:42 -05:00
|
|
|
device_id = meta_input_device_x11_get_device_id (device);
|
2019-10-02 10:49:28 -04:00
|
|
|
switch (unfreeze_method)
|
|
|
|
{
|
|
|
|
case EVENTS_UNFREEZE_SYNC:
|
|
|
|
event_mode = XISyncDevice;
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_verbose ("Syncing events time %u device %i",
|
2019-10-02 10:49:28 -04:00
|
|
|
(unsigned int) event->button.time, device_id);
|
|
|
|
break;
|
|
|
|
case EVENTS_UNFREEZE_REPLAY:
|
|
|
|
event_mode = XIReplayDevice;
|
2020-10-02 11:47:22 -04:00
|
|
|
meta_verbose ("Replaying events time %u device %i",
|
2019-10-02 10:49:28 -04:00
|
|
|
(unsigned int) event->button.time, device_id);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
|
|
|
XIAllowEvents (xdisplay, device_id, event_mode, event->button.time);
|
|
|
|
}
|
2022-06-01 04:06:55 -04:00
|
|
|
#endif
|
2019-10-02 10:49:28 -04:00
|
|
|
|
2014-03-20 15:29:30 -04:00
|
|
|
static gboolean
|
|
|
|
meta_display_handle_event (MetaDisplay *display,
|
2022-03-05 17:43:29 -05:00
|
|
|
const ClutterEvent *event,
|
|
|
|
ClutterActor *event_actor)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2022-04-27 06:12:33 -04:00
|
|
|
MetaContext *context = meta_display_get_context (display);
|
|
|
|
MetaBackend *backend = meta_context_get_backend (context);
|
2022-10-21 06:56:24 -04:00
|
|
|
MetaCompositor *compositor = meta_display_get_compositor (display);
|
2022-04-27 06:12:33 -04:00
|
|
|
ClutterInputDevice *device;
|
2021-09-03 17:38:12 -04:00
|
|
|
MetaWindow *window = NULL;
|
2014-08-13 20:19:35 -04:00
|
|
|
gboolean bypass_clutter = FALSE;
|
|
|
|
G_GNUC_UNUSED gboolean bypass_wayland = FALSE;
|
2016-11-29 07:22:02 -05:00
|
|
|
MetaGestureTracker *gesture_tracker;
|
2014-10-13 10:20:28 -04:00
|
|
|
ClutterEventSequence *sequence;
|
2021-11-17 17:31:11 -05:00
|
|
|
gboolean has_grab;
|
2022-05-27 16:27:07 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
MetaWaylandCompositor *wayland_compositor;
|
2023-06-07 06:58:36 -04:00
|
|
|
MetaWaylandTextInput *wayland_text_input = NULL;
|
2022-05-27 16:27:07 -04:00
|
|
|
#endif
|
2021-11-17 17:31:11 -05:00
|
|
|
|
2022-02-23 10:13:17 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
2022-05-27 16:27:07 -04:00
|
|
|
wayland_compositor = meta_context_get_wayland_compositor (context);
|
2023-06-07 06:58:36 -04:00
|
|
|
if (wayland_compositor)
|
|
|
|
{
|
|
|
|
wayland_text_input =
|
|
|
|
meta_wayland_compositor_get_text_input (wayland_compositor);
|
|
|
|
}
|
2022-02-23 10:13:17 -05:00
|
|
|
#endif
|
|
|
|
|
2022-12-20 05:28:06 -05:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaDisplayHandleEvent,
|
|
|
|
"MetaDisplay (handle event)");
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
has_grab = stage_has_grab (display);
|
|
|
|
|
|
|
|
if (display->grabbed_in_clutter != has_grab)
|
|
|
|
{
|
|
|
|
if (!display->grabbed_in_clutter && has_grab)
|
|
|
|
{
|
|
|
|
display->grabbed_in_clutter = TRUE;
|
|
|
|
meta_compositor_grab_begin (compositor);
|
|
|
|
}
|
|
|
|
else if (display->grabbed_in_clutter && !has_grab)
|
|
|
|
{
|
|
|
|
display->grabbed_in_clutter = FALSE;
|
|
|
|
meta_compositor_grab_end (compositor);
|
|
|
|
}
|
|
|
|
}
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2022-04-27 04:50:43 -04:00
|
|
|
if (meta_display_process_captured_input (display, event))
|
|
|
|
{
|
|
|
|
bypass_clutter = TRUE;
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2022-04-27 06:12:33 -04:00
|
|
|
device = clutter_event_get_device (event);
|
|
|
|
clutter_input_pointer_a11y_update (device, event);
|
|
|
|
|
2014-10-13 10:20:28 -04:00
|
|
|
sequence = clutter_event_get_event_sequence (event);
|
|
|
|
|
|
|
|
/* Set the pointer emulating sequence on touch begin, if eligible */
|
2015-10-16 09:13:40 -04:00
|
|
|
if (event->type == CLUTTER_TOUCH_BEGIN)
|
|
|
|
{
|
|
|
|
if (sequence_is_pointer_emulated (display, event))
|
|
|
|
{
|
|
|
|
/* This is the new pointer emulating sequence */
|
|
|
|
display->pointer_emulating_sequence = sequence;
|
|
|
|
}
|
|
|
|
else if (display->pointer_emulating_sequence == sequence)
|
|
|
|
{
|
|
|
|
/* This sequence was "pointer emulating" in a prior incarnation,
|
|
|
|
* but now it isn't. We unset the pointer emulating sequence at
|
|
|
|
* this point so the current sequence is not mistaken as pointer
|
|
|
|
* emulating, while we've ensured that it's been deemed
|
|
|
|
* "pointer emulating" throughout all of the event processing
|
|
|
|
* of the previous incarnation.
|
|
|
|
*/
|
|
|
|
display->pointer_emulating_sequence = NULL;
|
|
|
|
}
|
|
|
|
}
|
2014-07-21 19:14:14 -04:00
|
|
|
|
2014-08-13 20:19:35 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
2023-06-07 06:58:36 -04:00
|
|
|
if (wayland_text_input &&
|
|
|
|
!has_grab &&
|
|
|
|
!meta_compositor_get_current_window_drag (compositor) &&
|
|
|
|
meta_wayland_text_input_update (wayland_text_input, event))
|
|
|
|
{
|
|
|
|
bypass_wayland = bypass_clutter = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2022-02-23 10:13:17 -05:00
|
|
|
if (wayland_compositor)
|
|
|
|
meta_wayland_compositor_update (wayland_compositor, event);
|
2014-08-13 20:19:35 -04:00
|
|
|
#endif
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2019-12-16 07:53:26 -05:00
|
|
|
if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
|
|
|
event->type == CLUTTER_PAD_RING ||
|
|
|
|
event->type == CLUTTER_PAD_STRIP)
|
2016-10-25 11:01:37 -04:00
|
|
|
{
|
2019-12-16 07:53:26 -05:00
|
|
|
gboolean handle_pad_event;
|
|
|
|
gboolean is_mode_switch = FALSE;
|
|
|
|
|
|
|
|
if (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE)
|
|
|
|
{
|
|
|
|
ClutterInputDevice *pad;
|
|
|
|
uint32_t button;
|
|
|
|
|
|
|
|
pad = clutter_event_get_source_device (event);
|
|
|
|
button = clutter_event_get_button (event);
|
|
|
|
|
|
|
|
is_mode_switch =
|
|
|
|
clutter_input_device_get_mode_switch_button_group (pad, button) >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
handle_pad_event = !display->current_pad_osd || is_mode_switch;
|
|
|
|
|
|
|
|
if (handle_pad_event &&
|
2020-07-15 16:38:00 -04:00
|
|
|
meta_pad_action_mapper_handle_event (display->pad_action_mapper, event))
|
2016-10-25 11:01:37 -04:00
|
|
|
{
|
|
|
|
bypass_wayland = bypass_clutter = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-25 12:49:19 -04:00
|
|
|
if (event->type != CLUTTER_DEVICE_ADDED &&
|
|
|
|
event->type != CLUTTER_DEVICE_REMOVED)
|
2022-04-27 06:12:33 -04:00
|
|
|
handle_idletime_for_event (display, event);
|
2015-02-11 09:03:25 -05:00
|
|
|
|
2022-06-19 05:28:21 -04:00
|
|
|
if (event->type == CLUTTER_MOTION)
|
2014-08-21 16:57:27 -04:00
|
|
|
{
|
2020-07-13 08:09:44 -04:00
|
|
|
ClutterInputDevice *device;
|
2015-01-09 11:31:02 -05:00
|
|
|
|
2020-07-13 08:09:44 -04:00
|
|
|
device = clutter_event_get_device (event);
|
2022-09-15 04:02:08 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (wayland_compositor)
|
|
|
|
{
|
|
|
|
MetaCursorRenderer *cursor_renderer =
|
|
|
|
meta_backend_get_cursor_renderer_for_device (backend, device);
|
|
|
|
|
|
|
|
if (cursor_renderer)
|
|
|
|
meta_cursor_renderer_update_position (cursor_renderer);
|
|
|
|
}
|
|
|
|
#endif
|
2015-01-09 11:31:02 -05:00
|
|
|
|
2020-07-13 08:09:44 -04:00
|
|
|
if (device == clutter_seat_get_pointer (clutter_input_device_get_seat (device)))
|
2015-01-09 11:31:02 -05:00
|
|
|
{
|
2016-11-29 07:30:22 -05:00
|
|
|
MetaCursorTracker *cursor_tracker =
|
|
|
|
meta_backend_get_cursor_tracker (backend);
|
2016-11-29 07:22:02 -05:00
|
|
|
|
2020-07-13 08:09:44 -04:00
|
|
|
meta_cursor_tracker_invalidate_position (cursor_tracker);
|
2015-01-09 11:31:02 -05:00
|
|
|
}
|
2014-08-21 16:57:27 -04:00
|
|
|
}
|
|
|
|
|
2022-03-05 17:46:24 -05:00
|
|
|
window = get_window_for_event (display, event, event_actor);
|
2014-03-20 15:29:30 -04:00
|
|
|
|
|
|
|
display->current_time = event->any.time;
|
|
|
|
|
|
|
|
if (window && !window->override_redirect &&
|
2014-06-19 16:23:00 -04:00
|
|
|
(event->type == CLUTTER_KEY_PRESS ||
|
|
|
|
event->type == CLUTTER_BUTTON_PRESS ||
|
|
|
|
event->type == CLUTTER_TOUCH_BEGIN))
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2017-08-26 16:24:21 -04:00
|
|
|
if (META_CURRENT_TIME == display->current_time)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
|
|
|
/* We can't use missing (i.e. invalid) timestamps to set user time,
|
|
|
|
* nor do we want to use them to sanity check other timestamps.
|
|
|
|
* See bug 313490 for more details.
|
|
|
|
*/
|
|
|
|
meta_warning ("Event has no timestamp! You may be using a broken "
|
|
|
|
"program such as xse. Please ask the authors of that "
|
2020-10-02 11:47:22 -04:00
|
|
|
"program to fix it.");
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_window_set_user_time (window, display->current_time);
|
|
|
|
meta_display_sanity_check_timestamps (display, display->current_time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-29 07:22:02 -05:00
|
|
|
gesture_tracker = meta_display_get_gesture_tracker (display);
|
2014-06-19 17:10:33 -04:00
|
|
|
|
2016-11-29 07:22:02 -05:00
|
|
|
if (meta_gesture_tracker_handle_event (gesture_tracker, event))
|
2014-06-19 17:10:33 -04:00
|
|
|
{
|
2022-04-03 21:22:12 -04:00
|
|
|
bypass_wayland = TRUE;
|
|
|
|
bypass_clutter = FALSE;
|
2014-06-19 17:10:33 -04:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2014-05-08 14:53:50 -04:00
|
|
|
/* For key events, it's important to enforce single-handling, or
|
|
|
|
* we can get into a confused state. So if a keybinding is
|
|
|
|
* handled (because it's one of our hot-keys, or because we are
|
|
|
|
* in a keyboard-grabbed mode like moving a window, we don't
|
|
|
|
* want to pass the key event to the compositor or Wayland at all.
|
|
|
|
*/
|
2022-10-21 06:56:24 -04:00
|
|
|
if (!meta_compositor_get_current_window_drag (compositor) &&
|
|
|
|
meta_keybindings_process_event (display, window, event))
|
2014-05-08 14:53:50 -04:00
|
|
|
{
|
|
|
|
bypass_clutter = TRUE;
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2016-03-10 11:51:46 -05:00
|
|
|
/* Do not pass keyboard events to Wayland if key focus is not on the
|
|
|
|
* stage in normal mode (e.g. during keynav in the panel)
|
|
|
|
*/
|
2022-10-21 06:56:24 -04:00
|
|
|
if (!has_grab)
|
2016-03-10 11:51:46 -05:00
|
|
|
{
|
2022-04-27 06:12:33 -04:00
|
|
|
if (IS_KEY_EVENT (event) && !stage_has_key_focus (display))
|
2016-03-10 11:51:46 -05:00
|
|
|
{
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-07 16:40:33 -04:00
|
|
|
if (meta_is_wayland_compositor () &&
|
|
|
|
event->type == CLUTTER_SCROLL &&
|
|
|
|
meta_prefs_get_mouse_button_mods () > 0)
|
2021-01-30 06:25:26 -05:00
|
|
|
{
|
|
|
|
ClutterModifierType grab_mods;
|
|
|
|
|
|
|
|
grab_mods = meta_display_get_compositor_modifiers (display);
|
|
|
|
if ((clutter_event_get_state (event) & grab_mods) != 0)
|
|
|
|
{
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-29 07:51:55 -04:00
|
|
|
if (display->current_pad_osd)
|
|
|
|
{
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
if (stage_has_grab (display))
|
|
|
|
{
|
2022-02-23 10:09:28 -05:00
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
if (wayland_compositor)
|
|
|
|
meta_dnd_wayland_maybe_handle_event (meta_backend_get_dnd (backend), event);
|
|
|
|
#endif
|
|
|
|
|
2021-11-17 17:31:11 -05:00
|
|
|
bypass_wayland = TRUE;
|
|
|
|
bypass_clutter = FALSE;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2014-05-08 15:12:58 -04:00
|
|
|
if (window)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2015-07-01 09:49:33 -04:00
|
|
|
/* Events that are likely to trigger compositor gestures should
|
|
|
|
* be known to clutter so they can propagate along the hierarchy.
|
|
|
|
* Gesture-wise, there's two groups of events we should be getting
|
|
|
|
* here:
|
|
|
|
* - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted
|
|
|
|
* by the gesture tracker, these might trigger gesture actions
|
|
|
|
* into recognition. Already accepted touch sequences are handled
|
|
|
|
* directly by meta_gesture_tracker_handle_event().
|
|
|
|
* - CLUTTER_TOUCHPAD_* events over windows. These can likewise
|
|
|
|
* trigger ::captured-event handlers along the way.
|
|
|
|
*/
|
|
|
|
bypass_clutter = !IS_GESTURE_EVENT (event);
|
x11: Integrate frames client into Mutter
Replace the in-process implementation of frames with the external
frames client.
When a client window is created and managed by Mutter, Mutter will
determine whether it is a window that requires decorations and
hint the creation of a frame for it by setting the _MUTTER_NEEDS_FRAME
property on the client window.
After the frames client created a window that has the _MUTTER_FRAME_FOR
property, Mutter will proceed to reparent the client window on the
frame window, and show them as a single unit.
Rendering and event handling on the frame window will be performed by
the external client, Mutter is still responsible for everything else,
namely resizing client and frame window in synchronization, and
managing updates on the MetaWindowActor.
In order to let the frame be managed by the external client, Mutter
needs to change the way some properties are forwarded to the client
and/or frame windows. Some properties are necessary to keep propagating
to the client window only, some others need to happen on the frame
window now, and some others needs to be propagated on both so they
are synchronized about the behavior.
Also, some events that were previously totally unexpected in frame
windows are now susceptible to happen, so must be allowed now.
MetaFrame in src/core/frame.c now acts as the wrapper of foreign
windows created by the frames client, from the Mutter side. Location,
size, and lifetime are still largely in control of Mutter, some
details like visible/invisible borders are obtained from the client
instead (through the _MUTTER_FRAME_EXTENTS and _GTK_FRAME_EXTENTS
properties, respectively).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2175>
2022-09-08 04:35:47 -04:00
|
|
|
bypass_wayland = meta_window_has_modals (window);
|
2022-09-28 08:03:05 -04:00
|
|
|
|
2022-09-29 09:19:24 -04:00
|
|
|
if (
|
|
|
|
#ifdef HAVE_WAYLAND
|
|
|
|
(!wayland_compositor ||
|
|
|
|
!meta_wayland_compositor_is_grabbed (wayland_compositor)) &&
|
|
|
|
#endif
|
|
|
|
!meta_display_is_grabbed (display))
|
2022-09-28 08:03:05 -04:00
|
|
|
meta_window_handle_ungrabbed_event (window, event);
|
2014-08-15 08:29:16 -04:00
|
|
|
|
|
|
|
/* This might start a grab op. If it does, then filter out the
|
|
|
|
* event, and if it doesn't, replay the event to release our
|
|
|
|
* own sync grab. */
|
|
|
|
|
2022-10-21 06:56:24 -04:00
|
|
|
if (meta_compositor_get_current_window_drag (compositor))
|
2014-05-08 15:09:20 -04:00
|
|
|
{
|
2014-08-15 08:29:16 -04:00
|
|
|
bypass_clutter = TRUE;
|
2014-05-08 15:05:25 -04:00
|
|
|
bypass_wayland = TRUE;
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
2014-08-15 08:29:16 -04:00
|
|
|
else
|
2014-05-08 15:09:20 -04:00
|
|
|
{
|
2014-08-15 08:29:16 -04:00
|
|
|
/* Only replay button press events, since that's where we
|
|
|
|
* have the synchronous grab. */
|
2022-06-01 04:06:55 -04:00
|
|
|
#ifdef HAVE_X11_CLIENT
|
2019-10-02 10:49:28 -04:00
|
|
|
maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY);
|
2022-06-01 04:06:55 -04:00
|
|
|
#endif
|
2017-05-27 12:42:39 -04:00
|
|
|
/* If the focus window has an active close dialog let clutter
|
|
|
|
* events go through, so fancy clutter dialogs can get to handle
|
|
|
|
* all events.
|
|
|
|
*/
|
|
|
|
if (window->close_dialog &&
|
|
|
|
meta_close_dialog_is_visible (window->close_dialog))
|
|
|
|
{
|
|
|
|
bypass_wayland = TRUE;
|
|
|
|
bypass_clutter = FALSE;
|
|
|
|
}
|
2014-05-08 15:09:20 -04:00
|
|
|
}
|
2014-05-08 15:12:58 -04:00
|
|
|
|
|
|
|
goto out;
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
2019-10-02 10:49:28 -04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* We could not match the event with a window, make sure we sync
|
|
|
|
* the pointer to discard the sequence and don't keep events frozen.
|
|
|
|
*/
|
2022-06-01 04:06:55 -04:00
|
|
|
#ifdef HAVE_X11_CLIENT
|
|
|
|
maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC);
|
|
|
|
#endif
|
2019-10-02 10:49:28 -04:00
|
|
|
}
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2014-04-21 11:21:19 -04:00
|
|
|
out:
|
2022-09-29 09:32:23 -04:00
|
|
|
#ifdef HAVE_WAYLAND
|
2014-03-20 15:29:30 -04:00
|
|
|
/* If a Wayland client has a grab, don't pass that through to Clutter */
|
2022-09-29 09:32:23 -04:00
|
|
|
if (wayland_compositor && meta_wayland_compositor_is_grabbed (wayland_compositor))
|
2022-02-04 10:34:06 -05:00
|
|
|
bypass_clutter = !bypass_wayland;
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2022-02-23 10:13:17 -05:00
|
|
|
if (wayland_compositor && !bypass_wayland)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
2021-09-03 17:38:12 -04:00
|
|
|
if (window && event->type == CLUTTER_MOTION &&
|
|
|
|
event->any.time != CLUTTER_CURRENT_TIME)
|
|
|
|
meta_window_check_alive_on_event (window, event->any.time);
|
|
|
|
|
2022-02-23 10:13:17 -05:00
|
|
|
if (meta_wayland_compositor_handle_event (wayland_compositor, event))
|
2014-03-20 15:29:30 -04:00
|
|
|
bypass_clutter = TRUE;
|
|
|
|
}
|
2014-08-13 20:19:35 -04:00
|
|
|
#endif
|
2014-03-20 15:29:30 -04:00
|
|
|
|
2017-08-26 16:24:21 -04:00
|
|
|
display->current_time = META_CURRENT_TIME;
|
2014-03-20 15:29:30 -04:00
|
|
|
return bypass_clutter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
event_callback (const ClutterEvent *event,
|
2022-03-05 17:43:29 -05:00
|
|
|
ClutterActor *event_actor,
|
2014-03-20 15:29:30 -04:00
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
MetaDisplay *display = data;
|
|
|
|
|
2022-03-05 17:43:29 -05:00
|
|
|
return meta_display_handle_event (display, event, event_actor);
|
2014-03-20 15:29:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-08-15 13:47:57 -04:00
|
|
|
meta_display_init_events (MetaDisplay *display)
|
2014-03-20 15:29:30 -04:00
|
|
|
{
|
|
|
|
display->clutter_event_filter = clutter_event_add_filter (NULL,
|
|
|
|
event_callback,
|
|
|
|
NULL,
|
|
|
|
display);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_display_free_events (MetaDisplay *display)
|
|
|
|
{
|
|
|
|
clutter_event_remove_filter (display->clutter_event_filter);
|
|
|
|
display->clutter_event_filter = 0;
|
|
|
|
}
|