diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index be6abc0ce..e1ebd0a01 100644
--- a/src/backends/meta-backend-private.h
+++ b/src/backends/meta-backend-private.h
@@ -209,3 +209,9 @@ void meta_backend_update_from_event (MetaBackend *backend,
char * meta_backend_get_vendor_name (MetaBackend *backend,
const char *pnp_id);
+
+META_EXPORT_TEST
+uint32_t meta_clutter_button_to_evdev (uint32_t clutter_button);
+
+META_EXPORT_TEST
+uint32_t meta_evdev_button_to_clutter (uint32_t evdev_button);
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index a77b81581..f925a2f69 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -119,6 +119,12 @@ static guint signals[N_SIGNALS];
#define HIDDEN_POINTER_TIMEOUT 300 /* ms */
+#ifndef BTN_LEFT
+#define BTN_LEFT 0x110
+#define BTN_RIGHT 0x111
+#define BTN_MIDDLE 0x112
+#endif
+
struct _MetaBackendPrivate
{
MetaContext *context;
@@ -1797,3 +1803,37 @@ meta_backend_get_vendor_name (MetaBackend *backend,
return g_strdup (pnp_id);
#endif
}
+
+uint32_t
+meta_clutter_button_to_evdev (uint32_t clutter_button)
+{
+ switch (clutter_button)
+ {
+ case CLUTTER_BUTTON_PRIMARY:
+ return BTN_LEFT;
+ case CLUTTER_BUTTON_SECONDARY:
+ return BTN_RIGHT;
+ case CLUTTER_BUTTON_MIDDLE:
+ return BTN_MIDDLE;
+ }
+
+ return (clutter_button + (BTN_LEFT - 1)) - 4;
+}
+
+uint32_t
+meta_evdev_button_to_clutter (uint32_t evdev_button)
+{
+ switch (evdev_button)
+ {
+ case BTN_LEFT:
+ return CLUTTER_BUTTON_PRIMARY;
+ case BTN_RIGHT:
+ return CLUTTER_BUTTON_SECONDARY;
+ case BTN_MIDDLE:
+ return CLUTTER_BUTTON_MIDDLE;
+ }
+
+ g_return_val_if_fail (evdev_button > BTN_LEFT, 0);
+
+ return (evdev_button - (BTN_LEFT - 1)) + 4;
+}
diff --git a/src/tests/button-transform-tests.c b/src/tests/button-transform-tests.c
new file mode 100644
index 000000000..1d6b250e7
--- /dev/null
+++ b/src/tests/button-transform-tests.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 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, see .
+ *
+ */
+
+#include "config.h"
+
+#include "button-transform-tests.h"
+
+#include
+
+#include "backends/meta-backend-private.h"
+
+static void
+meta_test_clutter_to_evdev (void)
+{
+ struct {
+ uint32_t clutter_button;
+ uint32_t evdev_button;
+ } test_cases[] = {
+ { .clutter_button = CLUTTER_BUTTON_PRIMARY, .evdev_button = BTN_LEFT },
+ { .clutter_button = CLUTTER_BUTTON_MIDDLE, .evdev_button = BTN_MIDDLE },
+ { .clutter_button = CLUTTER_BUTTON_SECONDARY, .evdev_button = BTN_RIGHT },
+ };
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
+ {
+ uint32_t clutter_button;
+ uint32_t expected_evdev_button;
+ uint32_t evdev_button;
+
+ clutter_button = test_cases[i].clutter_button;
+ expected_evdev_button = test_cases[i].evdev_button;
+
+ evdev_button = meta_clutter_button_to_evdev (clutter_button);
+ g_assert_cmpuint (evdev_button, ==, expected_evdev_button);
+ }
+}
+
+static void
+meta_test_evdev_to_clutter (void)
+{
+ struct {
+ uint32_t evdev_button;
+ uint32_t clutter_button;
+ } test_cases[] = {
+ { .evdev_button = BTN_LEFT, .clutter_button = CLUTTER_BUTTON_PRIMARY },
+ { .evdev_button = BTN_MIDDLE, .clutter_button = CLUTTER_BUTTON_MIDDLE },
+ { .evdev_button = BTN_RIGHT, .clutter_button = CLUTTER_BUTTON_SECONDARY },
+ };
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
+ {
+ uint32_t evdev_button;
+ uint32_t expected_clutter_button;
+ uint32_t clutter_button;
+
+ evdev_button = test_cases[i].evdev_button;
+ expected_clutter_button = test_cases[i].clutter_button;
+
+ clutter_button = meta_evdev_button_to_clutter (evdev_button);
+ g_assert_cmpuint (clutter_button, ==, expected_clutter_button);
+ }
+}
+
+static void
+meta_test_evdev_to_clutter_to_evdev (void)
+{
+ uint32_t test_cases[] = {
+ BTN_LEFT,
+ BTN_MIDDLE,
+ BTN_RIGHT,
+ BTN_SIDE,
+ BTN_BACK,
+ BTN_FORWARD,
+ };
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++)
+ {
+ uint32_t evdev_button;
+ uint32_t expected_evdev_button;
+ uint32_t clutter_button;
+
+ evdev_button = test_cases[i];
+ expected_evdev_button = evdev_button;
+
+ clutter_button = meta_evdev_button_to_clutter (evdev_button);
+ evdev_button = meta_clutter_button_to_evdev (clutter_button);
+ g_assert_cmpuint (evdev_button, ==, expected_evdev_button);
+ }
+}
+
+void
+init_button_transform_tests (void)
+{
+ g_test_add_func ("/backends/button-transform/clutter-to-evdev",
+ meta_test_clutter_to_evdev);
+ g_test_add_func ("/backends/button-transform/evdev-clutter",
+ meta_test_evdev_to_clutter);
+ g_test_add_func ("/backends/button-transform/evdev-clutter-evdev",
+ meta_test_evdev_to_clutter_to_evdev);
+}
diff --git a/src/tests/button-transform-tests.h b/src/tests/button-transform-tests.h
new file mode 100644
index 000000000..b44b5c7c9
--- /dev/null
+++ b/src/tests/button-transform-tests.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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, see .
+ *
+ */
+
+#pragma once
+
+void init_button_transform_tests (void);
diff --git a/src/tests/meson.build b/src/tests/meson.build
index e658c33b2..adc37333b 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -242,6 +242,7 @@ test_cases += [
'monitor-transform-tests.h',
'orientation-manager-unit-tests.c',
'hdr-metadata-unit-tests.c',
+ 'button-transform-tests.c',
],
'depends': [
test_client,
diff --git a/src/tests/unit-tests.c b/src/tests/unit-tests.c
index f565d8687..fae808114 100644
--- a/src/tests/unit-tests.c
+++ b/src/tests/unit-tests.c
@@ -39,6 +39,7 @@
#include "tests/meta-test-utils.h"
#include "tests/orientation-manager-unit-tests.h"
#include "tests/hdr-metadata-unit-tests.h"
+#include "tests/button-transform-tests.h"
MetaContext *test_context;
@@ -244,6 +245,7 @@ init_tests (void)
init_monitor_transform_tests ();
init_orientation_manager_tests ();
init_hdr_metadata_tests ();
+ init_button_transform_tests ();
}
int