mutter/src/backends/meta-input-capture.c
Jonas Ådahl 2fb3bdf774 input-capture: Hook up capturing of events to active session
This adds the actual input capturing rerouting that takes events and
first hands them to the input capture session, would it be active.
Events are right now not actually processed in any way, but will
eventually be passed to a libei client using libeis.

A key binding for allowing cancelling the capture session is added
(defaults to <Super><Shift>Escape) to avoid getting stuck in case the client
doesn't even terminate the session.

The added test case makes sure that the pointer moves again after
pressing the keybinding.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2628>
2023-07-14 22:23:45 +00:00

230 lines
7.7 KiB
C

/*
* Copyright (C) 2022 Red Hat Inc.
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include "config.h"
#include "backends/meta-input-capture-private.h"
#include "backends/meta-input-capture-session.h"
#include "backends/meta-backend-private.h"
#include "backends/meta-monitor-manager-private.h"
#include "clutter/clutter.h"
#include "meta-dbus-input-capture.h"
#define META_INPUT_CAPTURE_DBUS_SERVICE "org.gnome.Mutter.InputCapture"
#define META_INPUT_CAPTURE_DBUS_PATH "/org/gnome/Mutter/InputCapture"
enum
{
CANCELLED,
};
typedef enum _MetaInputCaptureCapabilities
{
META_INPUT_CAPTURE_CAPABILITY_NONE = 1 << 0,
META_INPUT_CAPTURE_CAPABILITY_KEYBOARD = 1 << 1,
META_INPUT_CAPTURE_CAPABILITY_POINTER = 1 << 2,
META_INPUT_CAPTURE_CAPABILITY_TOUCH = 1 << 3,
} MetaInputCaptureCapabilities;
struct _MetaInputCapture
{
MetaDbusSessionManager parent;
struct {
MetaInputCaptureEnable enable;
MetaInputCaptureDisable disable;
gpointer user_data;
} event_router;
MetaInputCaptureSession *active_session;
};
G_DEFINE_TYPE (MetaInputCapture, meta_input_capture,
META_TYPE_DBUS_SESSION_MANAGER)
static gboolean
handle_create_session (MetaDBusInputCapture *skeleton,
GDBusMethodInvocation *invocation,
uint32_t capabilities,
MetaInputCapture *input_capture)
{
MetaDbusSessionManager *session_manager =
META_DBUS_SESSION_MANAGER (input_capture);
MetaDbusSession *dbus_session;
MetaInputCaptureSession *session;
g_autoptr (GError) error = NULL;
char *session_path;
dbus_session =
meta_dbus_session_manager_create_session (session_manager,
invocation,
&error,
NULL);
if (!dbus_session)
{
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
error->message);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
session = META_INPUT_CAPTURE_SESSION (dbus_session);
session_path = meta_input_capture_session_get_object_path (session);
meta_dbus_input_capture_complete_create_session (skeleton,
invocation,
session_path);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}
static void
meta_input_capture_constructed (GObject *object)
{
MetaInputCapture *input_capture = META_INPUT_CAPTURE (object);
MetaDbusSessionManager *session_manager =
META_DBUS_SESSION_MANAGER (input_capture);
GDBusInterfaceSkeleton *interface_skeleton =
meta_dbus_session_manager_get_interface_skeleton (session_manager);
g_signal_connect (interface_skeleton, "handle-create-session",
G_CALLBACK (handle_create_session), input_capture);
G_OBJECT_CLASS (meta_input_capture_parent_class)->constructed (object);
}
static void
meta_input_capture_class_init (MetaInputCaptureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_input_capture_constructed;
}
static void
meta_input_capture_init (MetaInputCapture *input_capture)
{
}
static MetaInputCaptureCapabilities
calculate_supported_capabilities (MetaInputCapture *input_capture)
{
MetaDbusSessionManager *session_manager =
META_DBUS_SESSION_MANAGER (input_capture);
MetaBackend *backend =
meta_dbus_session_manager_get_backend (session_manager);
ClutterSeat *seat = meta_backend_get_default_seat (backend);
ClutterVirtualDeviceType device_types;
MetaInputCaptureCapabilities supported_capabilities =
META_INPUT_CAPTURE_CAPABILITY_NONE;
device_types =
clutter_seat_get_supported_virtual_device_types (seat);
if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD)
supported_capabilities |= META_INPUT_CAPTURE_CAPABILITY_KEYBOARD;
if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER)
supported_capabilities |= META_INPUT_CAPTURE_CAPABILITY_POINTER;
if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN)
supported_capabilities |= META_INPUT_CAPTURE_CAPABILITY_TOUCH;
return supported_capabilities;
}
MetaInputCapture *
meta_input_capture_new (MetaBackend *backend)
{
MetaInputCapture *input_capture;
g_autoptr (MetaDBusInputCapture) skeleton = NULL;
skeleton = meta_dbus_input_capture_skeleton_new ();
input_capture = g_object_new (META_TYPE_INPUT_CAPTURE,
"backend", backend,
"service-name", META_INPUT_CAPTURE_DBUS_SERVICE,
"service-path", META_INPUT_CAPTURE_DBUS_PATH,
"session-gtype", META_TYPE_INPUT_CAPTURE_SESSION,
"interface-skeleton", skeleton,
NULL);
meta_dbus_input_capture_set_supported_capabilities (
META_DBUS_INPUT_CAPTURE (skeleton),
calculate_supported_capabilities (input_capture));
return input_capture;
}
void
meta_input_capture_set_event_router (MetaInputCapture *input_capture,
MetaInputCaptureEnable enable,
MetaInputCaptureDisable disable,
gpointer user_data)
{
g_warn_if_fail (!input_capture->event_router.enable &&
!input_capture->event_router.disable &&
!input_capture->event_router.user_data);
input_capture->event_router.enable = enable;
input_capture->event_router.disable = disable;
input_capture->event_router.user_data = user_data;
}
void
meta_input_capture_activate (MetaInputCapture *input_capture,
MetaInputCaptureSession *session)
{
g_return_if_fail (input_capture->event_router.enable);
meta_topic (META_DEBUG_INPUT, "Activating input capturing");
input_capture->active_session = session;
input_capture->event_router.enable (input_capture,
input_capture->event_router.user_data);
}
void
meta_input_capture_deactivate (MetaInputCapture *input_capture,
MetaInputCaptureSession *session)
{
g_return_if_fail (input_capture->event_router.disable);
meta_topic (META_DEBUG_INPUT, "Deactivating input capturing");
input_capture->event_router.disable (input_capture,
input_capture->event_router.user_data);
input_capture->active_session = NULL;
}
void
meta_input_capture_notify_cancelled (MetaInputCapture *input_capture)
{
g_return_if_fail (input_capture->active_session);
meta_input_capture_session_notify_cancelled (input_capture->active_session);
}
gboolean
meta_input_capture_process_event (MetaInputCapture *input_capture,
const ClutterEvent *event)
{
g_return_val_if_fail (input_capture->active_session, FALSE);
return meta_input_capture_session_process_event (input_capture->active_session,
event);
}