From 1d745a858470b29b44e5b0e308488a477c4526cb Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 22 Feb 2018 17:48:17 +0100 Subject: [PATCH 1/2] clutter/x11: Implement missing ClutterInputDevice pad vmethods Use libwacom to be able to find out modes, groups and button roles on pad devices. https://gitlab.gnome.org/GNOME/mutter/issues/48 Closes: #48 --- clutter/clutter/x11/clutter-device-manager-xi2.c | 11 +++ clutter/clutter/x11/clutter-device-manager-xi2.h | 8 ++ clutter/clutter/x11/clutter-input-device-xi2.c | 97 ++++++++++++++++++++++++ clutter/clutter/x11/clutter-input-device-xi2.h | 10 +++ clutter/configure.ac | 32 +++++++- 5 files changed, 156 insertions(+), 2 deletions(-) diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c index d2610cc..dee2604 100644 --- a/clutter/clutter/x11/clutter-device-manager-xi2.c +++ b/clutter/clutter/x11/clutter-device-manager-xi2.c @@ -495,11 +495,18 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2, "device-node", node_path, "n-rings", num_rings, "n-strips", num_strips, + "n-mode-groups", MAX (num_rings, num_strips), NULL); translate_device_classes (backend_x11->xdpy, retval, info->classes, info->num_classes); + +#ifdef HAVE_LIBWACOM + if (source == CLUTTER_PAD_DEVICE) + clutter_input_device_xi2_ensure_wacom_info (retval, manager_xi2->wacom_db); +#endif + g_free (vendor_id); g_free (product_id); @@ -2063,4 +2070,8 @@ clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self) (GDestroyNotify) g_object_unref); self->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref); + +#ifdef HAVE_LIBWACOM + self->wacom_db = libwacom_database_new (); +#endif } diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.h b/clutter/clutter/x11/clutter-device-manager-xi2.h index c8e66f9..be25759 100644 --- a/clutter/clutter/x11/clutter-device-manager-xi2.h +++ b/clutter/clutter/x11/clutter-device-manager-xi2.h @@ -26,6 +26,10 @@ #include +#ifdef HAVE_LIBWACOM +#include +#endif + G_BEGIN_DECLS #define CLUTTER_TYPE_DEVICE_MANAGER_XI2 (_clutter_device_manager_xi2_get_type ()) @@ -51,6 +55,10 @@ struct _ClutterDeviceManagerXI2 GList *slave_devices; int opcode; + +#ifdef HAVE_LIBWACOM + WacomDeviceDatabase *wacom_db; +#endif }; struct _ClutterDeviceManagerXI2Class diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c index 7fb0e05..2d9b6d2 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.c +++ b/clutter/clutter/x11/clutter-input-device-xi2.c @@ -45,6 +45,10 @@ struct _ClutterInputDeviceXI2 gint device_id; ClutterInputDeviceTool *current_tool; + +#ifdef HAVE_LIBWACOM + WacomDevice *wacom_device; +#endif }; #define N_BUTTONS 5 @@ -88,15 +92,94 @@ clutter_input_device_xi2_is_grouped (ClutterInputDevice *device, } static void +clutter_input_device_xi2_finalize (GObject *object) +{ +#ifdef HAVE_LIBWACOM + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (object); + + if (device_xi2->wacom_device) + libwacom_destroy (device_xi2->wacom_device); +#endif + + G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); +} + +static gint +clutter_input_device_xi2_get_group_n_modes (ClutterInputDevice *device, + gint group) +{ +#ifdef HAVE_LIBWACOM + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + + if (device_xi2->wacom_device) + { + if (group == 0) + { + if (libwacom_has_ring (device_xi2->wacom_device)) + return libwacom_get_ring_num_modes (device_xi2->wacom_device); + else if (libwacom_get_num_strips (device_xi2->wacom_device) >= 1) + return libwacom_get_strips_num_modes (device_xi2->wacom_device); + } + else if (group == 1) + { + if (libwacom_has_ring2 (device_xi2->wacom_device)) + return libwacom_get_ring2_num_modes (device_xi2->wacom_device); + else if (libwacom_get_num_strips (device_xi2->wacom_device) >= 2) + return libwacom_get_strips_num_modes (device_xi2->wacom_device); + } + } +#endif + + return -1; +} + +#ifdef HAVE_LIBWACOM +static int +clutter_input_device_xi2_get_button_group (ClutterInputDevice *device, + guint button) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + + if (device_xi2->wacom_device) + { + if (button >= libwacom_get_num_buttons (device_xi2->wacom_device)) + return -1; + + return libwacom_get_button_led_group (device_xi2->wacom_device, + 'A' + button); + } + else + return -1; +} +#endif + +static gboolean +clutter_input_device_xi2_is_mode_switch_button (ClutterInputDevice *device, + guint group, + guint button) +{ + int button_group = -1; + +#ifdef HAVE_LIBWACOM + button_group = clutter_input_device_xi2_get_button_group (device, button); +#endif + + return button_group == (int) group; +} + +static void clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); gobject_class->constructed = clutter_input_device_xi2_constructed; + gobject_class->finalize = clutter_input_device_xi2_finalize; device_class->keycode_to_evdev = clutter_input_device_xi2_keycode_to_evdev; device_class->is_grouped = clutter_input_device_xi2_is_grouped; + device_class->get_group_n_modes = clutter_input_device_xi2_get_group_n_modes; + device_class->is_mode_switch_button = clutter_input_device_xi2_is_mode_switch_button; } static void @@ -196,3 +279,17 @@ clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device) ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); return device_xi2->current_tool; } + +#ifdef HAVE_LIBWACOM +void +clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, + WacomDeviceDatabase *wacom_db) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + const gchar *node_path; + + node_path = clutter_input_device_get_device_node (device); + device_xi2->wacom_device = libwacom_new_from_path (wacom_db, node_path, + WFALLBACK_NONE, NULL); +} +#endif diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h index b93684f..e30fb4d 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.h +++ b/clutter/clutter/x11/clutter-input-device-xi2.h @@ -27,6 +27,10 @@ #include #include +#ifdef HAVE_LIBWACOM +#include +#endif + G_BEGIN_DECLS #define CLUTTER_TYPE_INPUT_DEVICE_XI2 (_clutter_input_device_xi2_get_type ()) @@ -45,6 +49,12 @@ void clutter_input_device_xi2_update_tool (ClutterInputDevice *device, ClutterInputDeviceTool *tool); ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device); +#ifdef HAVE_LIBWACOM +void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, + WacomDeviceDatabase *wacom_db); + +#endif + G_END_DECLS #endif /* __CLUTTER_INPUT_DEVICE_XI2_H__ */ diff --git a/clutter/configure.ac b/clutter/configure.ac index 3c3d0c5..5474fa0 100644 --- a/clutter/configure.ac +++ b/clutter/configure.ac @@ -121,6 +121,7 @@ m4_define([xcomposite_req_version], [0.4]) m4_define([gdk_req_version], [3.3.18]) m4_define([libinput_req_version], [1.4.0]) m4_define([libudev_req_version], [136]) +m4_define([libwacom_req_version], [0.13]) AC_SUBST([GLIB_REQ_VERSION], [glib_req_version]) AC_SUBST([COGL_REQ_VERSION], [cogl_req_version]) @@ -133,6 +134,7 @@ AC_SUBST([XCOMPOSITE_REQ_VERSION], [xcomposite_req_version]) AC_SUBST([GDK_REQ_VERSION], [gdk_req_version]) AC_SUBST([LIBINPUT_REQ_VERSION], [libinput_req_version]) AC_SUBST([LIBUDEV_REQ_VERSION], [libudev_req_version]) +AC_SUBST([LIBWACOM_REQ_VERSION], [libwacom_req_version]) # Checks for typedefs, structures, and compiler characteristics. AM_PATH_GLIB_2_0([glib_req_version], @@ -508,6 +510,32 @@ X11_EXTS=${X11_EXTS#* } AC_CACHE_SAVE +dnl === Libwacom support for X11 =============================================== +AC_ARG_WITH(libwacom, + AC_HELP_STRING([--without-libwacom], + [disable the use of libwacom for advanced tablet management]),, + with_libwacom=auto) + +have_libwacom=no +AC_MSG_CHECKING([libwacom]) +if test x$with_libwacom = xno ; then + AC_MSG_RESULT([disabled]) +else + if $PKG_CONFIG --exists libwacom '>=' $LIBWACOM_REQ_VERSION; then + have_libwacom=yes + AC_MSG_RESULT(yes) + PKG_CHECK_MODULES([LIBWACOM], [libwacom]) + AC_SUBST(LIBWACOM_CFLAGS) + AC_SUBST(LIBWACOM_LIBS) + AC_DEFINE([HAVE_LIBWACOM], 1, [Building with libwacom for advanced tablet management]) + else + AC_MSG_RESULT(no) + if test x$with_libwacom = xyes ; then + AC_MSG_ERROR([libwacom forced but not found]) + fi + fi +fi + dnl === Enable GDK-Pixbuf in tests ============================================ m4_define([pixbuf_default], [yes]) @@ -679,8 +707,8 @@ AS_IF([test "x$CLUTTER_BASE_PC_FILES_PRIVATE" = "x" && test "x$BACKEND_PC_FILES_ AC_SUBST(CLUTTER_REQUIRES) AC_SUBST(CLUTTER_REQUIRES_PRIVATE) -CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS" -CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS" +CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS $LIBWACOM_CFLAGS" +CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS $LIBWACOM_LIBS" AC_SUBST(CLUTTER_CFLAGS) AC_SUBST(CLUTTER_LIBS) -- 1.8.3.1 From f8fa4b8fa13fba9ed484be74fb7fc82499d46261 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Thu, 22 Feb 2018 17:50:42 +0100 Subject: [PATCH 2/2] clutter/x11: Communicate proper group/mode on pad events. So we can trigger actions for the right mode. https://gitlab.gnome.org/GNOME/mutter/issues/48 Closes: #48 --- clutter/clutter/x11/clutter-device-manager-xi2.c | 15 +++++- clutter/clutter/x11/clutter-input-device-xi2.c | 61 ++++++++++++++++++++++++ clutter/clutter/x11/clutter-input-device-xi2.h | 9 ++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c index dee2604..d269a38 100644 --- a/clutter/clutter/x11/clutter-device-manager-xi2.c +++ b/clutter/clutter/x11/clutter-device-manager-xi2.c @@ -1133,7 +1133,7 @@ translate_pad_event (ClutterEvent *event, ClutterInputDevice *device) { gdouble value; - guint number; + guint number, mode = 0; if (!translate_pad_axis (device, &xev->valuators, &event->any.type, @@ -1147,15 +1147,21 @@ translate_pad_event (ClutterEvent *event, if (xev->evtype == XI_Motion) value = -1; +#ifdef HAVE_LIBWACOM + mode = clutter_input_device_xi2_get_pad_group_mode (device, number); +#endif + if (event->any.type == CLUTTER_PAD_RING) { event->pad_ring.ring_number = number; event->pad_ring.angle = value; + event->pad_ring.mode = mode; } else { event->pad_strip.strip_number = number; event->pad_strip.value = value; + event->pad_strip.mode = mode; } event->any.time = xev->time; @@ -1382,6 +1388,13 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, /* Pad buttons are 0-indexed */ event->pad_button.button = xev->detail - 1; +#ifdef HAVE_LIBWACOM + clutter_input_device_xi2_update_pad_state (device, + event->pad_button.button, + (xi_event->evtype == XI_ButtonPress), + &event->pad_button.group, + &event->pad_button.mode); +#endif clutter_event_set_device (event, device); clutter_event_set_source_device (event, source_device); diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c index 2d9b6d2..f62ba85 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.c +++ b/clutter/clutter/x11/clutter-input-device-xi2.c @@ -48,6 +48,7 @@ struct _ClutterInputDeviceXI2 #ifdef HAVE_LIBWACOM WacomDevice *wacom_device; + GArray *group_modes; #endif }; @@ -68,6 +69,15 @@ clutter_input_device_xi2_constructed (GObject *gobject) if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed) G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject); + +#ifdef HAVE_LIBWACOM + if (clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (gobject)) == CLUTTER_PAD_DEVICE) + { + device_xi2->group_modes = g_array_new (FALSE, TRUE, sizeof (guint)); + g_array_set_size (device_xi2->group_modes, + clutter_input_device_get_n_mode_groups (CLUTTER_INPUT_DEVICE (gobject))); + } +#endif } static gboolean @@ -99,6 +109,8 @@ clutter_input_device_xi2_finalize (GObject *object) if (device_xi2->wacom_device) libwacom_destroy (device_xi2->wacom_device); + + g_array_unref (device_xi2->group_modes); #endif G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); @@ -292,4 +304,53 @@ clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, device_xi2->wacom_device = libwacom_new_from_path (wacom_db, node_path, WFALLBACK_NONE, NULL); } + +guint +clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device, + guint group) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + + if (group >= device_xi2->group_modes->len) + return 0; + + return g_array_index (device_xi2->group_modes, guint, group); +} + +void +clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, + guint button, + guint state, + guint *group, + guint *mode) +{ + ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); + guint button_group, *group_mode; + gboolean is_mode_switch = FALSE; + + button_group = clutter_input_device_xi2_get_button_group (device, button); + is_mode_switch = button_group >= 0; + + /* Assign all non-mode-switch buttons to group 0 so far */ + button_group = MAX (0, button_group); + + if (button_group >= device_xi2->group_modes->len) + return; + + group_mode = &g_array_index (device_xi2->group_modes, guint, button_group); + + if (is_mode_switch && state) + { + guint next, n_modes; + + n_modes = clutter_input_device_get_group_n_modes (device, button_group); + next = (*group_mode + 1) % n_modes; + *group_mode = next; + } + + if (group) + *group = button_group; + if (mode) + *mode = *group_mode; +} #endif diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h index e30fb4d..2194e1b 100644 --- a/clutter/clutter/x11/clutter-input-device-xi2.h +++ b/clutter/clutter/x11/clutter-input-device-xi2.h @@ -53,6 +53,15 @@ ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInput void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, WacomDeviceDatabase *wacom_db); +guint clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device, + guint group); + +void clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, + guint button, + guint state, + guint *group, + guint *mode); + #endif G_END_DECLS -- 1.8.3.1