
Only a tiny number of tablet pads that have more than one mode group, everyone else has one mode toggle button and one group. Let's not display "Group 0" for everyone if (almost) no-one has a Group 1 anyway. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4248>
637 lines
20 KiB
C
637 lines
20 KiB
C
/*
|
|
* Copyright (C) 2014-2024 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Written by:
|
|
* Carlos Garnacho <carlosg@gnome.org>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib/gi18n-lib.h>
|
|
#include <gdesktop-enums.h>
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
#include <libwacom/libwacom.h>
|
|
#endif
|
|
|
|
#include "core/meta-pad-action-mapper.h"
|
|
#include "backends/meta-input-device-private.h"
|
|
#include "backends/meta-logical-monitor.h"
|
|
#include "backends/meta-monitor.h"
|
|
#include "core/display-private.h"
|
|
|
|
typedef struct _PadMappingInfo PadMappingInfo;
|
|
|
|
struct _PadMappingInfo
|
|
{
|
|
ClutterInputDevice *device;
|
|
guint *group_modes;
|
|
};
|
|
|
|
struct _MetaPadActionMapper
|
|
{
|
|
GObject parent_class;
|
|
|
|
GHashTable *pads;
|
|
|
|
/* Pad ring/strip emission */
|
|
struct {
|
|
ClutterInputDevice *pad;
|
|
MetaPadFeatureType feature;
|
|
guint number;
|
|
double value;
|
|
} last_pad_action_info;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaPadActionMapper, meta_pad_action_mapper, META_TYPE_TABLET_ACTION_MAPPER);
|
|
|
|
static gboolean
|
|
meta_pad_action_mapper_handle_event (MetaTabletActionMapper *mapper,
|
|
const ClutterEvent *event);
|
|
static void
|
|
device_added (MetaTabletActionMapper *mapper,
|
|
ClutterInputDevice *device);
|
|
static void
|
|
device_removed (MetaTabletActionMapper *mapper,
|
|
ClutterInputDevice *device);
|
|
|
|
static void
|
|
meta_pad_action_mapper_finalize (GObject *object)
|
|
{
|
|
MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (object);
|
|
|
|
g_hash_table_unref (mapper->pads);
|
|
|
|
G_OBJECT_CLASS (meta_pad_action_mapper_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
meta_pad_action_mapper_class_init (MetaPadActionMapperClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = meta_pad_action_mapper_finalize;
|
|
}
|
|
|
|
static PadMappingInfo *
|
|
pad_mapping_info_new (ClutterInputDevice *pad)
|
|
{
|
|
PadMappingInfo *info;
|
|
|
|
info = g_new0 (PadMappingInfo, 1);
|
|
info->device = pad;
|
|
info->group_modes =
|
|
g_new0 (guint, clutter_input_device_get_n_mode_groups (pad));
|
|
|
|
return info;
|
|
}
|
|
|
|
static void
|
|
pad_mapping_info_free (PadMappingInfo *info)
|
|
{
|
|
g_free (info->group_modes);
|
|
g_free (info);
|
|
}
|
|
|
|
static void
|
|
device_added (MetaTabletActionMapper *tablet_mapper,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (tablet_mapper);
|
|
PadMappingInfo *info;
|
|
|
|
if ((clutter_input_device_get_capabilities (device) &
|
|
CLUTTER_INPUT_CAPABILITY_TABLET_PAD) != 0)
|
|
{
|
|
info = pad_mapping_info_new (device);
|
|
g_hash_table_insert (mapper->pads, device, info);
|
|
}
|
|
}
|
|
|
|
static void
|
|
device_removed (MetaTabletActionMapper *tablet_mapper,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (tablet_mapper);
|
|
|
|
g_hash_table_remove (mapper->pads, device);
|
|
}
|
|
|
|
static void
|
|
meta_pad_action_mapper_init (MetaPadActionMapper *mapper)
|
|
{
|
|
g_signal_connect (mapper, "device-added", G_CALLBACK (device_added), NULL);
|
|
g_signal_connect (mapper, "device-removed", G_CALLBACK (device_removed), NULL);
|
|
g_signal_connect (mapper, "input-event", G_CALLBACK (meta_pad_action_mapper_handle_event), NULL);
|
|
|
|
mapper->pads = g_hash_table_new_full (NULL, NULL, NULL,
|
|
(GDestroyNotify) pad_mapping_info_free);
|
|
}
|
|
|
|
MetaPadActionMapper *
|
|
meta_pad_action_mapper_new (MetaMonitorManager *monitor_manager)
|
|
{
|
|
MetaPadActionMapper *action_mapper;
|
|
|
|
action_mapper = g_object_new (META_TYPE_PAD_ACTION_MAPPER,
|
|
"monitor_manager", monitor_manager,
|
|
NULL);
|
|
|
|
return action_mapper;
|
|
}
|
|
|
|
static GSettings *
|
|
get_pad_feature_gsettings (ClutterInputDevice *device,
|
|
const char *feature,
|
|
int feature_number,
|
|
const char *suffix)
|
|
{
|
|
GSettings *settings;
|
|
g_autofree char *path = NULL;
|
|
const gchar *vendor, *product;
|
|
char tag;
|
|
|
|
tag = 'A' + feature_number;
|
|
vendor = clutter_input_device_get_vendor_id (device);
|
|
product = clutter_input_device_get_product_id (device);
|
|
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/%s%c%s/",
|
|
vendor, product, feature, tag,
|
|
suffix ? suffix : "");
|
|
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
|
|
path);
|
|
|
|
return settings;
|
|
}
|
|
|
|
static GSettings *
|
|
lookup_pad_button_settings (ClutterInputDevice *device,
|
|
int button)
|
|
{
|
|
return get_pad_feature_gsettings (device, "button", button, NULL);
|
|
}
|
|
|
|
static GSettings *
|
|
lookup_pad_feature_settings (ClutterInputDevice *device,
|
|
MetaPadFeatureType feature,
|
|
guint number,
|
|
MetaPadDirection direction,
|
|
int mode)
|
|
{
|
|
g_autofree char *suffix = NULL;
|
|
const char *feature_type, *detail_type;
|
|
|
|
switch (feature)
|
|
{
|
|
case META_PAD_FEATURE_RING:
|
|
g_assert (direction == META_PAD_DIRECTION_CW ||
|
|
direction == META_PAD_DIRECTION_CCW);
|
|
feature_type = "ring";
|
|
detail_type = (direction == META_PAD_DIRECTION_CW) ? "cw" : "ccw";
|
|
break;
|
|
case META_PAD_FEATURE_STRIP:
|
|
g_assert (direction == META_PAD_DIRECTION_UP ||
|
|
direction == META_PAD_DIRECTION_DOWN);
|
|
feature_type = "strip";
|
|
detail_type = (direction == META_PAD_DIRECTION_UP) ? "up" : "down";
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
if (mode >= 0)
|
|
suffix = g_strdup_printf ("-%s-mode-%d", detail_type, mode);
|
|
else
|
|
suffix = g_strdup_printf ("-%s", detail_type);
|
|
|
|
return get_pad_feature_gsettings (device, feature_type, number, suffix);
|
|
}
|
|
|
|
static GDesktopPadButtonAction
|
|
meta_pad_action_mapper_get_button_action (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
guint button)
|
|
{
|
|
GDesktopPadButtonAction action;
|
|
GSettings *settings;
|
|
|
|
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper),
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
|
|
settings = lookup_pad_button_settings (pad, button);
|
|
action = g_settings_get_enum (settings, "action");
|
|
g_object_unref (settings);
|
|
|
|
return action;
|
|
}
|
|
|
|
gboolean
|
|
meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
guint button)
|
|
{
|
|
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
|
|
g_return_val_if_fail ((clutter_input_device_get_capabilities (pad) &
|
|
CLUTTER_INPUT_CAPABILITY_TABLET_PAD) != 0, FALSE);
|
|
|
|
return (meta_pad_action_mapper_get_button_action (mapper, pad, button) !=
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
}
|
|
|
|
static gboolean
|
|
meta_pad_action_mapper_handle_button (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
const ClutterEvent *event)
|
|
{
|
|
MetaTabletActionMapper *tablet_mapper = META_TABLET_ACTION_MAPPER (mapper);
|
|
MetaTabletActionMapperClass *tablet_klass = META_TABLET_ACTION_MAPPER_GET_CLASS (mapper);
|
|
GDesktopPadButtonAction action;
|
|
int group, n_modes = 0;
|
|
gboolean is_press;
|
|
GSettings *settings;
|
|
char *accel;
|
|
uint32_t button, mode;
|
|
MetaDisplay *display;
|
|
|
|
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
|
|
g_return_val_if_fail (clutter_event_type (event) == CLUTTER_PAD_BUTTON_PRESS ||
|
|
clutter_event_type (event) == CLUTTER_PAD_BUTTON_RELEASE, FALSE);
|
|
|
|
clutter_event_get_pad_details (event, &button, &mode, NULL, NULL);
|
|
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
|
is_press = clutter_event_type (event) == CLUTTER_PAD_BUTTON_PRESS;
|
|
display = tablet_klass->get_display (tablet_mapper);
|
|
|
|
if (group >= 0)
|
|
n_modes = clutter_input_device_get_group_n_modes (pad, group);
|
|
|
|
if (is_press && n_modes > 0)
|
|
{
|
|
const char *pretty_name = NULL;
|
|
PadMappingInfo *info;
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDevice *wacom_device;
|
|
#endif
|
|
|
|
info = g_hash_table_lookup (mapper->pads, pad);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
|
|
|
|
if (wacom_device)
|
|
pretty_name = libwacom_get_name (wacom_device);
|
|
#endif
|
|
meta_display_notify_pad_group_switch (display, pad,
|
|
pretty_name, group, mode, n_modes);
|
|
info->group_modes[group] = mode;
|
|
}
|
|
|
|
action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
|
|
|
|
switch (action)
|
|
{
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
|
if (is_press)
|
|
tablet_klass->cycle_tablet_output (tablet_mapper, pad);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
|
if (is_press)
|
|
meta_display_request_pad_osd (display, pad, FALSE);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
|
settings = lookup_pad_button_settings (pad, button);
|
|
accel = g_settings_get_string (settings, "keybinding");
|
|
tablet_klass->emulate_keybinding (tablet_mapper, accel, is_press);
|
|
g_object_unref (settings);
|
|
g_free (accel);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
meta_pad_action_mapper_get_action_direction (MetaPadActionMapper *mapper,
|
|
const ClutterEvent *event,
|
|
MetaPadDirection *direction)
|
|
{
|
|
ClutterInputDevice *pad = clutter_event_get_device (event);
|
|
MetaPadFeatureType pad_feature;
|
|
gboolean has_direction = FALSE;
|
|
MetaPadDirection inc_dir, dec_dir;
|
|
uint32_t number;
|
|
double value;
|
|
gboolean detect_wraparound = FALSE;
|
|
|
|
switch (clutter_event_type (event))
|
|
{
|
|
case CLUTTER_PAD_RING:
|
|
pad_feature = META_PAD_FEATURE_RING;
|
|
clutter_event_get_pad_details (event, &number, NULL, NULL, &value);
|
|
inc_dir = META_PAD_DIRECTION_CW;
|
|
dec_dir = META_PAD_DIRECTION_CCW;
|
|
detect_wraparound = TRUE;
|
|
break;
|
|
case CLUTTER_PAD_STRIP:
|
|
pad_feature = META_PAD_FEATURE_STRIP;
|
|
clutter_event_get_pad_details (event, &number, NULL, NULL, &value);
|
|
inc_dir = META_PAD_DIRECTION_DOWN;
|
|
dec_dir = META_PAD_DIRECTION_UP;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
if (mapper->last_pad_action_info.pad == pad &&
|
|
mapper->last_pad_action_info.feature == pad_feature &&
|
|
mapper->last_pad_action_info.number == number &&
|
|
value >= 0 && mapper->last_pad_action_info.value >= 0)
|
|
{
|
|
double delta = value - mapper->last_pad_action_info.value;
|
|
|
|
if (detect_wraparound)
|
|
{
|
|
if (delta < -180.0)
|
|
delta += 360;
|
|
else if (delta > 180.0)
|
|
delta -= 360;
|
|
}
|
|
|
|
*direction = delta > 0 ? inc_dir : dec_dir;
|
|
has_direction = TRUE;
|
|
}
|
|
|
|
mapper->last_pad_action_info.pad = pad;
|
|
mapper->last_pad_action_info.feature = pad_feature;
|
|
mapper->last_pad_action_info.number = number;
|
|
mapper->last_pad_action_info.value = value;
|
|
return has_direction;
|
|
}
|
|
|
|
static gboolean
|
|
meta_pad_action_mapper_handle_action (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
const ClutterEvent *event,
|
|
MetaPadFeatureType feature,
|
|
guint number,
|
|
guint mode)
|
|
{
|
|
MetaPadDirection direction;
|
|
g_autoptr (GSettings) settings1 = NULL, settings2 = NULL;
|
|
g_autofree char *accel1 = NULL, *accel2 = NULL;
|
|
gboolean handled;
|
|
|
|
if (feature == META_PAD_FEATURE_RING)
|
|
{
|
|
settings1 = lookup_pad_feature_settings (pad, feature, number,
|
|
META_PAD_DIRECTION_CW, mode);
|
|
settings2 = lookup_pad_feature_settings (pad, feature, number,
|
|
META_PAD_DIRECTION_CCW, mode);
|
|
}
|
|
else if (feature == META_PAD_FEATURE_STRIP)
|
|
{
|
|
settings1 = lookup_pad_feature_settings (pad, feature, number,
|
|
META_PAD_DIRECTION_UP, mode);
|
|
settings2 = lookup_pad_feature_settings (pad, feature, number,
|
|
META_PAD_DIRECTION_DOWN, mode);
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
accel1 = g_settings_get_string (settings1, "keybinding");
|
|
accel2 = g_settings_get_string (settings2, "keybinding");
|
|
handled = ((accel1 && *accel1) || (accel2 && *accel2));
|
|
|
|
if (meta_pad_action_mapper_get_action_direction (mapper, event, &direction))
|
|
{
|
|
const gchar *accel = NULL;
|
|
|
|
if (direction == META_PAD_DIRECTION_UP ||
|
|
direction == META_PAD_DIRECTION_CW)
|
|
accel = accel1;
|
|
else if (direction == META_PAD_DIRECTION_DOWN ||
|
|
direction == META_PAD_DIRECTION_CCW)
|
|
accel = accel2;
|
|
|
|
if (accel && *accel)
|
|
{
|
|
MetaTabletActionMapper *parent = META_TABLET_ACTION_MAPPER (mapper);
|
|
MetaTabletActionMapperClass *klass = META_TABLET_ACTION_MAPPER_GET_CLASS (parent);
|
|
klass->emulate_keybinding (parent, accel, TRUE);
|
|
klass->emulate_keybinding (parent, accel, FALSE);
|
|
}
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
static gboolean
|
|
meta_pad_action_mapper_handle_event (MetaTabletActionMapper *tablet_mapper,
|
|
const ClutterEvent *event)
|
|
{
|
|
MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (tablet_mapper);
|
|
ClutterInputDevice *pad;
|
|
uint32_t number, mode;
|
|
|
|
pad = clutter_event_get_source_device ((ClutterEvent *) event);
|
|
|
|
switch (clutter_event_type (event))
|
|
{
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
return meta_pad_action_mapper_handle_button (mapper, pad, event);
|
|
case CLUTTER_PAD_RING:
|
|
clutter_event_get_pad_details (event, &number, &mode, NULL, NULL);
|
|
return meta_pad_action_mapper_handle_action (mapper, pad, event,
|
|
META_PAD_FEATURE_RING,
|
|
number, mode);
|
|
case CLUTTER_PAD_STRIP:
|
|
clutter_event_get_pad_details (event, &number, &mode, NULL, NULL);
|
|
return meta_pad_action_mapper_handle_action (mapper, pad, event,
|
|
META_PAD_FEATURE_STRIP,
|
|
number, mode);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return CLUTTER_EVENT_PROPAGATE;
|
|
}
|
|
|
|
static char *
|
|
meta_pad_action_mapper_get_ring_label (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
int number,
|
|
unsigned int mode,
|
|
MetaPadDirection direction)
|
|
{
|
|
g_autoptr (GSettings) settings = NULL;
|
|
g_autofree char *action = NULL;
|
|
|
|
if (direction != META_PAD_DIRECTION_CW &&
|
|
direction != META_PAD_DIRECTION_CCW)
|
|
return NULL;
|
|
|
|
settings = lookup_pad_feature_settings (pad, META_PAD_FEATURE_RING,
|
|
number, direction, mode);
|
|
|
|
/* We only allow keybinding actions with those */
|
|
action = g_settings_get_string (settings, "keybinding");
|
|
if (action && *action)
|
|
return g_steal_pointer (&action);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static char *
|
|
meta_pad_action_mapper_get_strip_label (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
int number,
|
|
unsigned int mode,
|
|
MetaPadDirection direction)
|
|
{
|
|
g_autoptr (GSettings) settings = NULL;
|
|
g_autofree char *action = NULL;
|
|
|
|
if (direction != META_PAD_DIRECTION_UP &&
|
|
direction != META_PAD_DIRECTION_DOWN)
|
|
return NULL;
|
|
|
|
settings = lookup_pad_feature_settings (pad, META_PAD_FEATURE_STRIP,
|
|
number, direction, mode);
|
|
|
|
/* We only allow keybinding actions with those */
|
|
action = g_settings_get_string (settings, "keybinding");
|
|
if (action && *action)
|
|
return g_steal_pointer (&action);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
char *
|
|
meta_pad_action_mapper_get_button_label (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
int button)
|
|
{
|
|
GDesktopPadButtonAction action;
|
|
int group;
|
|
|
|
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL);
|
|
g_return_val_if_fail ((clutter_input_device_get_capabilities (pad) &
|
|
CLUTTER_INPUT_CAPABILITY_TABLET_PAD) != 0, NULL);
|
|
|
|
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
|
|
|
if (group >= 0)
|
|
{
|
|
int n_groups = clutter_input_device_get_n_mode_groups (pad);
|
|
if (n_groups > 1)
|
|
{
|
|
/* TRANSLATORS: This string refers to a button that switches between
|
|
* different modes in that button group.
|
|
*/
|
|
return g_strdup_printf (_("Mode Switch (Group %d)"), group);
|
|
}
|
|
else
|
|
{
|
|
/* TRANSLATORS: This string refers to a button that switches between
|
|
* different modes.
|
|
*/
|
|
return g_strdup_printf (_("Mode Switch"));
|
|
}
|
|
}
|
|
|
|
action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
|
|
|
|
switch (action)
|
|
{
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
|
{
|
|
GSettings *settings;
|
|
char *accel;
|
|
|
|
settings = lookup_pad_button_settings (pad, button);
|
|
accel = g_settings_get_string (settings, "keybinding");
|
|
g_object_unref (settings);
|
|
|
|
return accel;
|
|
}
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
|
/* TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
|
* mapping through the available outputs.
|
|
*/
|
|
return g_strdup (_("Switch monitor"));
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
|
return g_strdup (_("Show on-screen help"));
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static guint
|
|
get_current_pad_mode (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
MetaPadFeatureType feature,
|
|
guint number)
|
|
{
|
|
PadMappingInfo *info;
|
|
guint group = 0, n_groups;
|
|
|
|
info = g_hash_table_lookup (mapper->pads, pad);
|
|
n_groups = clutter_input_device_get_n_mode_groups (pad);
|
|
|
|
if (!info->group_modes || n_groups == 0)
|
|
return 0;
|
|
|
|
if (feature == META_PAD_FEATURE_RING ||
|
|
feature == META_PAD_FEATURE_STRIP)
|
|
{
|
|
/* Assume features are evenly distributed in groups */
|
|
group = number % n_groups;
|
|
}
|
|
|
|
return info->group_modes[group];
|
|
}
|
|
|
|
char *
|
|
meta_pad_action_mapper_get_feature_label (MetaPadActionMapper *mapper,
|
|
ClutterInputDevice *pad,
|
|
MetaPadFeatureType feature,
|
|
MetaPadDirection direction,
|
|
int number)
|
|
{
|
|
unsigned int mode;
|
|
|
|
switch (feature)
|
|
{
|
|
case META_PAD_FEATURE_RING:
|
|
mode = get_current_pad_mode (mapper, pad, feature, number);
|
|
return meta_pad_action_mapper_get_ring_label (mapper, pad, number, mode, direction);
|
|
case META_PAD_FEATURE_STRIP:
|
|
mode = get_current_pad_mode (mapper, pad, feature, number);
|
|
return meta_pad_action_mapper_get_strip_label (mapper, pad, number, mode, direction);
|
|
}
|
|
|
|
return NULL;
|
|
}
|