diff --git a/src/core/display-private.h b/src/core/display-private.h index b22e1f772..eaa9d1fb6 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -32,6 +32,7 @@ #include "core/keybindings-private.h" #include "core/meta-gesture-tracker-private.h" #include "core/meta-pad-action-mapper.h" +#include "core/meta-tool-action-mapper.h" #include "core/stack-tracker.h" #include "core/startup-notification-private.h" #include "meta/barrier.h" @@ -141,6 +142,7 @@ struct _MetaDisplay ClutterActor *current_pad_osd; MetaPadActionMapper *pad_action_mapper; + MetaToolActionMapper *tool_action_mapper; MetaStartupNotification *startup_notification; diff --git a/src/core/display.c b/src/core/display.c index bd09082ed..8c0364621 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -996,6 +996,7 @@ meta_display_new (MetaContext *context, display, G_CONNECT_SWAPPED); display->pad_action_mapper = meta_pad_action_mapper_new (monitor_manager); + display->tool_action_mapper = meta_tool_action_mapper_new (backend); input_capture = meta_backend_get_input_capture (backend); meta_input_capture_set_event_router (input_capture, diff --git a/src/core/events.c b/src/core/events.c index 26f0c1295..fb4c7574c 100644 --- a/src/core/events.c +++ b/src/core/events.c @@ -328,7 +328,10 @@ meta_display_handle_event (MetaDisplay *display, else if (event_type == CLUTTER_BUTTON_PRESS || event_type == CLUTTER_BUTTON_RELEASE) { - if (clutter_event_get_button (event) == 0) + mapper = META_TABLET_ACTION_MAPPER (display->tool_action_mapper); + if (((clutter_input_device_get_capabilities (device) & CLUTTER_INPUT_CAPABILITY_TABLET_TOOL) && + meta_tablet_action_mapper_handle_event (mapper, event)) || + clutter_event_get_button (event) == 0) return CLUTTER_EVENT_STOP; } diff --git a/src/core/meta-tool-action-mapper.c b/src/core/meta-tool-action-mapper.c new file mode 100644 index 000000000..b707f309b --- /dev/null +++ b/src/core/meta-tool-action-mapper.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014-2020 Red Hat + * + * 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 . + * + */ + +#include "config.h" + +#include +#include + +#ifdef HAVE_LIBWACOM +#include +#endif + +#include "core/meta-tool-action-mapper.h" +#include "backends/meta-input-device-private.h" +#include "core/display-private.h" + +struct _MetaToolActionMapper +{ + GObject parent_class; + MetaInputSettings *input_settings; +}; + +G_DEFINE_TYPE (MetaToolActionMapper, meta_tool_action_mapper, META_TYPE_TABLET_ACTION_MAPPER); + +static gboolean +meta_tool_action_mapper_handle_event (MetaTabletActionMapper *mapper, + const ClutterEvent *event); + +static void +meta_tool_action_mapper_finalize (GObject *object) +{ + MetaToolActionMapper *mapper = META_TOOL_ACTION_MAPPER (object); + + g_clear_object (&mapper->input_settings); + + G_OBJECT_CLASS (meta_tool_action_mapper_parent_class)->finalize (object); +} + +static void +meta_tool_action_mapper_class_init (MetaToolActionMapperClass *klass) +{ + G_OBJECT_CLASS (klass)->finalize = meta_tool_action_mapper_finalize; +} + +static void +meta_tool_action_mapper_init (MetaToolActionMapper *mapper) +{ + g_signal_connect (mapper, "input-event", G_CALLBACK (meta_tool_action_mapper_handle_event), NULL); +} + +MetaToolActionMapper * +meta_tool_action_mapper_new (MetaBackend *backend) +{ + MetaToolActionMapper *action_mapper; + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + + action_mapper = g_object_new (META_TYPE_TOOL_ACTION_MAPPER, + "monitor-manager", monitor_manager, + NULL); + action_mapper->input_settings = g_object_ref (meta_backend_get_input_settings (backend)); + + return action_mapper; +} + +static gboolean +meta_tool_action_mapper_handle_button (MetaToolActionMapper *mapper, + ClutterInputDevice *device, + const ClutterEvent *event) +{ + MetaTabletActionMapper *tablet_mapper = META_TABLET_ACTION_MAPPER (mapper); + MetaTabletActionMapperClass *tablet_klass = META_TABLET_ACTION_MAPPER_GET_CLASS (mapper); + GDesktopStylusButtonAction action; + gboolean is_press; + g_autofree char *accel = NULL; + uint32_t button, evcode; + ClutterInputDeviceTool *tool; + + g_return_val_if_fail (clutter_event_type (event) == CLUTTER_BUTTON_PRESS || + clutter_event_type (event) == CLUTTER_BUTTON_RELEASE, FALSE); + + if ((clutter_input_device_get_capabilities (device) & CLUTTER_INPUT_CAPABILITY_TABLET_TOOL) == 0) + return FALSE; + + tool = clutter_event_get_device_tool (event); + evcode = clutter_event_get_event_code (event); + button = meta_evdev_tool_button_to_clutter (evcode); + is_press = clutter_event_type (event) == CLUTTER_BUTTON_PRESS; + + action = meta_input_settings_get_tool_button_action (mapper->input_settings, + device, tool, button, &accel); + switch (action) + { + case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT: + case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE: + case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT: + case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK: + case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD: + /* These are handled as normal button events, nothing to do here */ + return FALSE; + case G_DESKTOP_STYLUS_BUTTON_ACTION_SWITCH_MONITOR: + if (is_press) + tablet_klass->cycle_tablet_output (tablet_mapper, device); + return TRUE; + case G_DESKTOP_STYLUS_BUTTON_ACTION_KEYBINDING: + if (accel) + tablet_klass->emulate_keybinding (tablet_mapper, accel, is_press); + return TRUE; + default: + g_warn_if_reached (); + return FALSE; + } +} + +gboolean +meta_tool_action_mapper_handle_event (MetaTabletActionMapper *tablet_mapper, + const ClutterEvent *event) +{ + MetaToolActionMapper *mapper = META_TOOL_ACTION_MAPPER (tablet_mapper); + ClutterInputDevice *tool; + + tool = clutter_event_get_source_device ((ClutterEvent *) event); + + switch (clutter_event_type (event)) + { + case CLUTTER_BUTTON_PRESS: + case CLUTTER_BUTTON_RELEASE: + return meta_tool_action_mapper_handle_button (mapper, tool, event); + default: + break; + } + + return CLUTTER_EVENT_PROPAGATE; +} diff --git a/src/core/meta-tool-action-mapper.h b/src/core/meta-tool-action-mapper.h new file mode 100644 index 000000000..6136a662a --- /dev/null +++ b/src/core/meta-tool-action-mapper.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 Red Hat + * + * 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 . + * + */ + +#pragma once + +#include "clutter/clutter.h" +#include "meta/display.h" +#include "meta/meta-monitor-manager.h" +#include "core/meta-tablet-action-mapper.h" + +#define META_TYPE_TOOL_ACTION_MAPPER (meta_tool_action_mapper_get_type ()) +G_DECLARE_FINAL_TYPE (MetaToolActionMapper, meta_tool_action_mapper, + META, TOOL_ACTION_MAPPER, MetaTabletActionMapper) + +MetaToolActionMapper *meta_tool_action_mapper_new (MetaBackend * backend); diff --git a/src/meson.build b/src/meson.build index b74fe37fe..c5dffd587 100644 --- a/src/meson.build +++ b/src/meson.build @@ -379,6 +379,7 @@ mutter_sources = [ 'core/meta-selection-source-memory.c', 'core/meta-sound-player.c', 'core/meta-tablet-action-mapper.c', + 'core/meta-tool-action-mapper.c', 'core/meta-workspace-manager.c', 'core/meta-workspace-manager-private.h', 'core/place.c',