diff options
Diffstat (limited to 'plugins/wacom')
-rw-r--r-- | plugins/wacom/Makefile.am | 126 | ||||
-rw-r--r-- | plugins/wacom/README.config-storage | 60 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-button-editor.c | 578 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-button-editor.h | 68 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-device.c | 2286 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-device.h | 202 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-key-shortcut-button.c | 634 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-key-shortcut-button.h | 69 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-manager.c | 1691 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-oled.c | 58 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-oled.h | 3 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-osd-window.c | 2104 | ||||
-rw-r--r-- | plugins/wacom/gsd-wacom-osd-window.h | 66 | ||||
-rw-r--r-- | plugins/wacom/list-wacom.c | 360 | ||||
-rw-r--r-- | plugins/wacom/tablet-layout.css | 39 | ||||
-rw-r--r-- | plugins/wacom/test-osd-window.c | 136 | ||||
-rw-r--r-- | plugins/wacom/wacom.gresource.xml | 7 |
17 files changed, 130 insertions, 8357 deletions
diff --git a/plugins/wacom/Makefile.am b/plugins/wacom/Makefile.am index 869ac3e7..7bf2e855 100644 --- a/plugins/wacom/Makefile.am +++ b/plugins/wacom/Makefile.am @@ -3,28 +3,17 @@ plugin_name = wacom org.gnome.settings-daemon.plugins.wacom.policy.in: org.gnome.settings-daemon.plugins.wacom.policy.in.in Makefile $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ -gsd-wacom-resources.c: wacom.gresource.xml tablet-layout.css - glib-compile-resources \ - --target=$@ \ - --sourcedir=$(srcdir) \ - --generate-source \ - --c-name gsd_wacom \ - $(srcdir)/wacom.gresource.xml - @INTLTOOL_POLICY_RULE@ polkit_policydir = $(datadir)/polkit-1/actions polkit_policy_in_files = org.gnome.settings-daemon.plugins.wacom.policy.in polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy) -# so it always gets included in the tarball -gsd_wacom_led_helper_SOURCES = gsd-wacom-led-helper.c -gsd_wacom_oled_helper_SOURCES = gsd-wacom-oled-helper.c gsd-wacom-oled-constants.h +EXTRA_DIST = wacom.gresource.xml -EXTRA_DIST = $(gsd_wacom_led_helper_SOURCES) wacom.gresource.xml tablet-layout.css \ - $(gsd_wacom_oled_helper_SOURCES) +libexec_PROGRAMS = gsd-wacom if HAVE_GUDEV -libexec_PROGRAMS = gsd-wacom-led-helper gsd-wacom-oled-helper +libexec_PROGRAMS += gsd-wacom-led-helper gsd-wacom-oled-helper gsd_wacom_led_helper_LDFLAGS = \ $(BACKLIGHT_HELPER_LIBS) \ @@ -45,98 +34,32 @@ endif EXTRA_DIST += org.gnome.settings-daemon.plugins.wacom.policy.in.in -libexec_PROGRAMS += gsd-wacom gsd-list-wacom gsd-test-wacom-osd - -gsd_wacom_SOURCES = \ - main.c \ - gsd-wacom-manager.c \ - gsd-wacom-manager.h \ - gsd-wacom-key-shortcut-button.h \ - gsd-wacom-key-shortcut-button.c \ - gsd-wacom-button-editor.h \ - gsd-wacom-button-editor.c \ - gsd-wacom-osd-window.h \ - gsd-wacom-osd-window.c \ - gsd-wacom-oled.h \ - gsd-wacom-oled.c \ - gsd-wacom-device.c \ - gsd-wacom-device.h \ - gsd-wacom-resources.c +gsd_wacom_SOURCES = \ + main.c \ + gsd-wacom-manager.c \ + gsd-wacom-manager.h \ + gsd-wacom-oled.h \ + gsd-wacom-oled.c gsd_wacom_CPPFLAGS = \ - -I$(top_srcdir)/data/ \ - -I$(top_srcdir)/gnome-settings-daemon \ - -I$(top_builddir)/gnome-settings-daemon \ - -I$(top_srcdir)/plugins/common \ - -DBINDIR=\"$(bindir)\" \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ - -DLIBEXECDIR=\""$(libexecdir)"\" - -gsd_wacom_CFLAGS = \ - $(PLUGIN_CFLAGS) \ - $(WACOM_CFLAGS) - -gsd_wacom_LDADD = \ - $(top_builddir)/gnome-settings-daemon/libgsd.la \ - $(top_builddir)/plugins/common/libcommon.la \ - $(WACOM_LIBS) \ - $(LIBM) - -gsd_list_wacom_SOURCES = \ - list-wacom.c \ - gsd-wacom-device.c \ - gsd-wacom-device.h - -gsd_list_wacom_CPPFLAGS = \ - -I$(top_srcdir)/data/ \ - -I$(top_srcdir)/gnome-settings-daemon \ - -I$(top_builddir)/gnome-settings-daemon \ - -I$(top_srcdir)/plugins/common \ - -DBINDIR=\"$(bindir)\" \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" - -gsd_list_wacom_CFLAGS = $(WACOM_CFLAGS) - -gsd_list_wacom_LDADD = \ - $(top_builddir)/gnome-settings-daemon/libgsd.la \ - $(top_builddir)/plugins/common/libcommon.la \ - $(WACOM_LIBS) \ - $(LIBM) - -gsd_test_wacom_osd_SOURCES = \ - test-osd-window.c \ - gsd-wacom-key-shortcut-button.h \ - gsd-wacom-key-shortcut-button.c \ - gsd-wacom-button-editor.h \ - gsd-wacom-button-editor.c \ - gsd-wacom-osd-window.h \ - gsd-wacom-osd-window.c \ - gsd-wacom-device.c \ - gsd-wacom-device.h \ - gsd-wacom-resources.c - -gsd_test_wacom_osd_CPPFLAGS = \ - -I$(top_srcdir)/data/ \ - -I$(top_srcdir)/gnome-settings-daemon \ - -I$(top_builddir)/gnome-settings-daemon \ - -I$(top_srcdir)/plugins/common \ - -DBINDIR=\"$(bindir)\" \ - -DPIXMAPDIR=\""$(pkgdatadir)"\" \ - -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ - -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ + -I$(top_srcdir)/data/ \ + -I$(top_srcdir)/gnome-settings-daemon \ + -I$(top_builddir)/gnome-settings-daemon \ + -I$(top_srcdir)/plugins/common \ + -DBINDIR=\"$(bindir)\" \ + -DPIXMAPDIR=\""$(pkgdatadir)"\" \ + -DGTKBUILDERDIR=\""$(pkgdatadir)"\" \ + -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \ -DLIBEXECDIR=\""$(libexecdir)"\" -gsd_test_wacom_osd_CFLAGS = \ +gsd_wacom_CFLAGS = \ + $(PLUGIN_CFLAGS) \ $(WACOM_CFLAGS) -gsd_test_wacom_osd_LDADD = \ - $(top_builddir)/gnome-settings-daemon/libgsd.la \ - $(top_builddir)/plugins/common/libcommon.la \ - $(WACOM_LIBS) \ +gsd_wacom_LDADD = \ + $(top_builddir)/gnome-settings-daemon/libgsd.la \ + $(top_builddir)/plugins/common/libcommon.la \ + $(WACOM_LIBS) \ $(LIBM) desktopdir = $(sysconfdir)/xdg/autostart @@ -146,9 +69,8 @@ desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) org.gnome.SettingsDaemon.Wacom.desktop: $(desktop_in_files) Makefile $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ -EXTRA_DIST += $(desktop_in_files) README.config-storage +EXTRA_DIST += $(desktop_in_files) CLEANFILES = \ $(desktop_DATA) \ - gsd-wacom-resources.c \ org.gnome.settings-daemon.plugins.wacom.policy \ org.gnome.settings-daemon.plugins.wacom.policy.in diff --git a/plugins/wacom/README.config-storage b/plugins/wacom/README.config-storage deleted file mode 100644 index bb99214b..00000000 --- a/plugins/wacom/README.config-storage +++ /dev/null @@ -1,60 +0,0 @@ -Configuration storage for Wacom tablets and styli - -Tablets -------- - -Configuration is stored on a per-device model basis, meaning that it's -possible to use the same device, with same configuration on 2 machines -with a shared home directory, or replace a malfunctioning device with the -same model and have the same configuration. - -It does not allow [1] having 2 separate tablets of the same model to have -different configurations, whether on a single machine, or using a shared -home directory. - -The configuration scheme is: -schema: org.gnome.settings-daemon.peripherals.wacom -path: /org/gnome/settings-daemon/peripherals/wacom/<machine ID>-<device ID>/ - -where <machine ID> is the D-Bus machine-id for the machine, and -<device ID> is a unique identifier for the tablet model. - -[1]: If you're using NFS shared home directories, you can share configurations -between different machines by creating an empty -~/.config/gnome-settings-daemon/no-per-machine-config file. -$ mkdir -p ~/.config/gnome-settings-daemon/ -$ touch ~/.config/gnome-settings-daemon/no-per-machine-config - -Note that this needs to happen without any gnome-settings-daemon -running (otherwise half of the configuration would be done in a per-machine -way and half in a generic way), and that previous machine-specific -configurations will be lost. - -Stylus ------- - -Styli use a similar configuration scheme. The identifier for each stylus -is the tool ID, for professional ranges, and a generic identifier for -the consumer ranges that do not support tool ID. - -schema: org.gnome.settings-daemon.peripherals.wacom.stylus -or: org.gnome.settings-daemon.peripherals.wacom.eraser - -path: /org/gnome/settings-daemon/peripherals/wacom/<device ID>/<tool ID>/ - -So each tool can be configured per tablet (so the compatible airbrush stylus -will have different configurations on a Cintiq and an Intuos tablet) - -Buttons -------- - -schema: org.gnome.settings-daemon.peripherals.wacom.tablet-button -path: /org/gnome/settings-daemon/peripherals/wacom/<device ID>/<button ID> - -Testing -------- - -You can see all the metadata held about tablets, styli and buttons using -list-wacom, as available in the gnome-settings-daemon sources. - -An example output is available at: https://gist.github.com/1688632 diff --git a/plugins/wacom/gsd-wacom-button-editor.c b/plugins/wacom/gsd-wacom-button-editor.c deleted file mode 100644 index 1cb690e1..00000000 --- a/plugins/wacom/gsd-wacom-button-editor.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright © 2013 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 <http://www.gnu.org/licenses/>. - * - * Author: Joaquim Rocha <jrocha@redhat.com> - */ - -#include "config.h" -#include <glib/gi18n.h> -#include <math.h> -#include "gsd-enums.h" -#include "gsd-wacom-key-shortcut-button.h" -#include "gsd-wacom-device.h" -#include "gsd-wacom-button-editor.h" - -#define BACK_OPACITY 0.8 -#define DEFAULT_ROW_SPACING 12 -#define ACTION_TYPE_KEY "action-type" -#define CUSTOM_ACTION_KEY "custom-action" -#define CUSTOM_ELEVATOR_ACTION_KEY "custom-elevator-action" -#define OLED_LABEL "oled-label" - -#define GSD_WACOM_BUTTON_EDITOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSD_WACOM_BUTTON_EDITOR_TYPE, GsdWacomButtonEditorPrivate)) - -G_DEFINE_TYPE (GsdWacomButtonEditor, gsd_wacom_button_editor, GTK_TYPE_GRID); - -enum { - BUTTON_EDITED, - DONE_EDITING, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static struct { - GsdWacomActionType action_type; - const gchar *action_name; -} action_table[] = { - { GSD_WACOM_ACTION_TYPE_NONE, NC_("Wacom action-type", "None") }, - { GSD_WACOM_ACTION_TYPE_CUSTOM, NC_("Wacom action-type", "Send Keystroke") }, - { GSD_WACOM_ACTION_TYPE_SWITCH_MONITOR, NC_("Wacom action-type", "Switch Monitor") }, - { GSD_WACOM_ACTION_TYPE_HELP, NC_("Wacom action-type", "Show On-Screen Help") } -}; - -#define WACOM_C(x) g_dpgettext2(NULL, "Wacom action-type", x) - -enum { - ACTION_NAME_COLUMN, - ACTION_TYPE_COLUMN, - ACTION_N_COLUMNS -}; - -struct _GsdWacomButtonEditorPrivate -{ - GsdWacomTabletButton *button; - GtkDirectionType direction; - GtkComboBox *action_combo; - GtkWidget *shortcut_button; -}; - -static void -assign_custom_key_to_dir_button (GsdWacomButtonEditor *self, - gchar *custom_key) -{ - GsdWacomTabletButton *button; - GtkDirectionType dir; - char *strs[3]; - char **strv; - - button = self->priv->button; - dir = self->priv->direction; - - strs[2] = NULL; - strs[0] = strs[1] = ""; - strv = g_settings_get_strv (button->settings, CUSTOM_ELEVATOR_ACTION_KEY); - - if (g_strv_length (strv) >= 1) - strs[0] = strv[0]; - if (g_strv_length (strv) >= 2) - strs[1] = strv[1]; - - if (dir == GTK_DIR_UP) - strs[0] = custom_key; - else - strs[1] = custom_key; - - g_settings_set_strv (button->settings, - CUSTOM_ELEVATOR_ACTION_KEY, - (const gchar * const*) strs); - - g_strfreev (strv); -} - -static void -change_button_action_type (GsdWacomButtonEditor *self, - GsdWacomActionType type) -{ - GsdWacomActionType current_type; - GsdWacomTabletButton *button; - - button = self->priv->button; - - if (button == NULL) - return; - - current_type = g_settings_get_enum (self->priv->button->settings, ACTION_TYPE_KEY); - - if (button->type == WACOM_TABLET_BUTTON_TYPE_STRIP || - button->type == WACOM_TABLET_BUTTON_TYPE_RING) - { - if (type == GSD_WACOM_ACTION_TYPE_NONE) - assign_custom_key_to_dir_button (self, ""); - else if (type == GSD_WACOM_ACTION_TYPE_CUSTOM) - { - guint keyval; - GdkModifierType mask; - char *custom_key; - - g_object_get (self->priv->shortcut_button, - "key-value", &keyval, - "key-mods", &mask, - NULL); - - mask &= ~GDK_LOCK_MASK; - - custom_key = gtk_accelerator_name (keyval, mask); - assign_custom_key_to_dir_button (self, custom_key); - g_settings_set_enum (button->settings, ACTION_TYPE_KEY, type); - - g_free (custom_key); - } - } - else if (current_type != type) - { - const char *oled_label; - - switch (type) { - case GSD_WACOM_ACTION_TYPE_NONE: - oled_label = ""; - break; - case GSD_WACOM_ACTION_TYPE_HELP: - oled_label = C_("Action type", "Show On-Screen Help"); - break; - case GSD_WACOM_ACTION_TYPE_SWITCH_MONITOR: - oled_label = C_("Action type", "Switch Monitor"); - break; - default: - oled_label = ""; - break; - }; - g_settings_set_string (button->settings, OLED_LABEL, oled_label); - g_settings_set_enum (button->settings, ACTION_TYPE_KEY, type); - } - - gtk_widget_set_visible (self->priv->shortcut_button, - type == GSD_WACOM_ACTION_TYPE_CUSTOM); -} - -static void -update_action_combo (GsdWacomButtonEditor *self, - GsdWacomActionType new_type) -{ - GtkTreeIter iter; - GsdWacomActionType type; - gboolean iter_valid; - GtkTreeModel *model; - - model = gtk_combo_box_get_model (self->priv->action_combo); - - for (iter_valid = gtk_tree_model_get_iter_first (model, &iter); - iter_valid; - iter_valid = gtk_tree_model_iter_next (model, &iter)) - { - gtk_tree_model_get (model, &iter, - ACTION_TYPE_COLUMN, &type, - -1); - - if (new_type == type) - { - gtk_combo_box_set_active_iter (self->priv->action_combo, &iter); - break; - } - } -} - -static void -reset_shortcut_button_label (GsdWacomButtonEditor *self) -{ - gtk_button_set_label (GTK_BUTTON (self->priv->shortcut_button), NC_("keyboard shortcut", "None")); -} - -static void -on_key_shortcut_cleared (GsdWacomKeyShortcutButton *shortcut_button, - GsdWacomButtonEditor *self) -{ - update_action_combo (self, GSD_WACOM_ACTION_TYPE_NONE); - - reset_shortcut_button_label (self); - - g_signal_emit (self, signals[BUTTON_EDITED], 0); -} - -static void -on_key_shortcut_edited (GsdWacomKeyShortcutButton *shortcut_button, - GsdWacomButtonEditor *self) -{ - GsdWacomTabletButton *button; - GtkDirectionType dir; - char *custom_key; - guint keyval; - GdkModifierType mask; - - button = self->priv->button; - - if (button == NULL) - return; - - dir = self->priv->direction; - - change_button_action_type (self, GSD_WACOM_ACTION_TYPE_CUSTOM); - - g_object_get (self->priv->shortcut_button, - "key-value", &keyval, - "key-mods", &mask, - NULL); - - if (keyval == 0 && mask == 0) - reset_shortcut_button_label (self); - - mask &= ~GDK_LOCK_MASK; - - custom_key = gtk_accelerator_name (keyval, mask); - - if (button->type == WACOM_TABLET_BUTTON_TYPE_STRIP || - button->type == WACOM_TABLET_BUTTON_TYPE_RING) - { - char *strs[3]; - char **strv; - - strs[2] = NULL; - strs[0] = strs[1] = ""; - strv = g_settings_get_strv (button->settings, CUSTOM_ELEVATOR_ACTION_KEY); - - if (g_strv_length (strv) >= 1) - strs[0] = strv[0]; - if (g_strv_length (strv) >= 2) - strs[1] = strv[1]; - - if (dir == GTK_DIR_UP) - strs[0] = custom_key; - else - strs[1] = custom_key; - - g_settings_set_strv (button->settings, - CUSTOM_ELEVATOR_ACTION_KEY, - (const gchar * const*) strs); - - g_strfreev (strv); - } - else - { - char *oled_label; - - oled_label = gtk_accelerator_get_label (keyval, mask); - g_settings_set_string (button->settings, OLED_LABEL, oled_label); - g_free (oled_label); - - g_settings_set_string (button->settings, CUSTOM_ACTION_KEY, custom_key); - } - - g_free (custom_key); - - g_signal_emit (self, signals[BUTTON_EDITED], 0); -} - -static void -on_combo_box_changed (GtkComboBox *combo, - GsdWacomButtonEditor *self) -{ - GsdWacomActionType type; - GtkTreeModel *model; - GtkTreeIter iter; - - if (!gtk_combo_box_get_active_iter (combo, &iter)) - return; - - model = gtk_combo_box_get_model (combo); - gtk_tree_model_get (model, &iter, ACTION_TYPE_COLUMN, &type, -1); - - change_button_action_type (self, type); - - g_signal_emit (self, signals[BUTTON_EDITED], 0); -} - -static void -on_finish_button_clicked (GtkWidget *button, GsdWacomButtonEditor *self) -{ - g_signal_emit (self, signals[DONE_EDITING], 0); -} - -static gboolean -action_type_is_allowed (GsdWacomTabletButton *button, GsdWacomActionType action_type) -{ - if (button->type != WACOM_TABLET_BUTTON_TYPE_STRIP && button->type != WACOM_TABLET_BUTTON_TYPE_RING) - return TRUE; - - if (action_type == GSD_WACOM_ACTION_TYPE_NONE || action_type == GSD_WACOM_ACTION_TYPE_CUSTOM) - return TRUE; - - return FALSE; -} - -static void -reset_action_combo_model (GsdWacomButtonEditor *self) -{ - GtkListStore *model; - GtkTreeIter iter; - GsdWacomTabletButton *button; - gint i; - - if (self->priv->button == NULL) - return; - - button = self->priv->button; - - model = GTK_LIST_STORE (gtk_combo_box_get_model (self->priv->action_combo)); - - gtk_list_store_clear (model); - - for (i = 0; i < G_N_ELEMENTS (action_table); i++) - { - if (!action_type_is_allowed (button, action_table[i].action_type)) - continue; - - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - ACTION_NAME_COLUMN, WACOM_C(action_table[i].action_name), - ACTION_TYPE_COLUMN, action_table[i].action_type, -1); - } -} - -static void -update_button (GsdWacomButtonEditor *self) -{ - GsdWacomTabletButton *button; - GtkDirectionType dir; - GsdWacomActionType current_type; - gchar *shortcut = NULL; - guint keyval; - GdkModifierType mask; - - button = self->priv->button; - - if (button == NULL) - return; - - dir = self->priv->direction; - - if (button->type == WACOM_TABLET_BUTTON_TYPE_STRIP || - button->type == WACOM_TABLET_BUTTON_TYPE_RING) - { - char *str; - char **strv; - - strv = g_settings_get_strv (button->settings, CUSTOM_ELEVATOR_ACTION_KEY); - if (strv != NULL) - { - if (dir == GTK_DIR_UP) - str = strv[0]; - else - str = strv[1]; - - shortcut = g_strdup (str); - if (g_strcmp0 (shortcut, "") == 0) - current_type = GSD_WACOM_ACTION_TYPE_NONE; - else - current_type = GSD_WACOM_ACTION_TYPE_CUSTOM; - - g_strfreev (strv); - } - else - { - current_type = GSD_WACOM_ACTION_TYPE_NONE; - } - } - else - { - current_type = g_settings_get_enum (button->settings, ACTION_TYPE_KEY); - if (current_type == GSD_WACOM_ACTION_TYPE_CUSTOM) - shortcut = g_settings_get_string (button->settings, CUSTOM_ACTION_KEY); - } - - if (shortcut != NULL && current_type == GSD_WACOM_ACTION_TYPE_CUSTOM) - { - gtk_accelerator_parse (shortcut, &keyval, &mask); - - g_object_set (self->priv->shortcut_button, - "key-value", keyval, - "key-mods", mask, - NULL); - - g_free (shortcut); - } - else - { - g_object_set (self->priv->shortcut_button, - "key-value", 0, - "key-mods", 0, - NULL); - - reset_shortcut_button_label (self); - } - - update_action_combo (self, current_type); -} - -static void -gsd_wacom_button_editor_init (GsdWacomButtonEditor *self) -{ - gint i; - GtkStyleContext *style_context; - GtkListStore *model; - GtkTreeIter iter; - GsdWacomButtonEditorPrivate *priv; - GtkCellRenderer *renderer; - GtkWidget *action_combo, *shortcut_button, *finish_button; - - style_context = gtk_widget_get_style_context (GTK_WIDGET (self)); - gtk_style_context_add_class (style_context, "osd"); - - priv = GSD_WACOM_BUTTON_EDITOR_GET_PRIVATE (self); - self->priv = priv; - - model = gtk_list_store_new (ACTION_N_COLUMNS, G_TYPE_STRING, G_TYPE_INT); - - for (i = 0; i < G_N_ELEMENTS (action_table); i++) { - gtk_list_store_append (model, &iter); - gtk_list_store_set (model, &iter, - ACTION_NAME_COLUMN, WACOM_C(action_table[i].action_name), - ACTION_TYPE_COLUMN, action_table[i].action_type, -1); - } - - action_combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model)); - self->priv->action_combo = GTK_COMBO_BOX (action_combo); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (action_combo), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (action_combo), renderer, - "text", ACTION_NAME_COLUMN, NULL); - - g_signal_connect (action_combo, "changed", - G_CALLBACK (on_combo_box_changed), - self); - - gtk_grid_attach (GTK_GRID (self), action_combo, 0, 0, 1, 1); - - shortcut_button = gsd_wacom_key_shortcut_button_new (); - /* Accept all shortcuts and disable the cancel key (by default: Escape) - * because we might want to assign it too */ - g_object_set (shortcut_button, - "mode", GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL, - "cancel-key", 0, - NULL); - self->priv->shortcut_button = shortcut_button; - - g_signal_connect (shortcut_button, "key-shortcut-cleared", - G_CALLBACK (on_key_shortcut_cleared), - self); - g_signal_connect (shortcut_button, "key-shortcut-edited", - G_CALLBACK (on_key_shortcut_edited), - self); - - gtk_grid_attach (GTK_GRID (self), shortcut_button, 1, 0, 1, 1); - - finish_button = gtk_button_new_with_label (_("Done")); - - g_signal_connect (finish_button, "clicked", - G_CALLBACK (on_finish_button_clicked), - self); - - gtk_grid_attach (GTK_GRID (self), finish_button, 2, 0, 1, 1); - - gtk_grid_set_row_spacing (GTK_GRID (self), DEFAULT_ROW_SPACING); - gtk_grid_set_column_spacing (GTK_GRID (self), DEFAULT_ROW_SPACING); - - g_object_set (self, - "halign", GTK_ALIGN_START, - "valign", GTK_ALIGN_START, - NULL); - - gtk_widget_show_all (GTK_WIDGET (self)); - gtk_widget_hide (GTK_WIDGET (self)); -} - -static gboolean -gsd_wacom_button_editor_key_press (GtkWidget *widget, - GdkEventKey *event) -{ - GTK_WIDGET_CLASS (gsd_wacom_button_editor_parent_class)->key_press_event (widget, event); - - return FALSE; -} - -static void -gsd_wacom_button_editor_class_init (GsdWacomButtonEditorClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - signals[BUTTON_EDITED] = g_signal_new ("button-edited", - GSD_WACOM_BUTTON_EDITOR_TYPE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsdWacomButtonEditorClass, button_edited), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[DONE_EDITING] = g_signal_new ("done-editing", - GSD_WACOM_BUTTON_EDITOR_TYPE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsdWacomButtonEditorClass, done_editing), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - widget_class->key_press_event = gsd_wacom_button_editor_key_press; - - g_type_class_add_private (klass, sizeof (GsdWacomButtonEditorPrivate)); -} - -void -gsd_wacom_button_editor_set_button (GsdWacomButtonEditor *self, - GsdWacomTabletButton *button, - GtkDirectionType direction) -{ - gboolean reset = TRUE; - - g_return_if_fail (GSD_WACOM_IS_BUTTON_EDITOR (self)); - - if (self->priv->button && button && self->priv->button->type == button->type) - reset = FALSE; - - self->priv->button = button; - self->priv->direction = direction; - - if (reset) - reset_action_combo_model (self); - - update_button (self); -} - -GsdWacomTabletButton * -gsd_wacom_button_editor_get_button (GsdWacomButtonEditor *self, - GtkDirectionType *direction) -{ - g_return_val_if_fail (GSD_WACOM_IS_BUTTON_EDITOR (self), NULL); - - *direction = self->priv->direction; - - return self->priv->button; -} - -GtkWidget * -gsd_wacom_button_editor_new (void) -{ - return g_object_new (GSD_WACOM_BUTTON_EDITOR_TYPE, NULL); -} diff --git a/plugins/wacom/gsd-wacom-button-editor.h b/plugins/wacom/gsd-wacom-button-editor.h deleted file mode 100644 index 10f8ab1e..00000000 --- a/plugins/wacom/gsd-wacom-button-editor.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright © 2013 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 <http://www.gnu.org/licenses/>. - * - * Author: Joaquim Rocha <jrocha@redhat.com> - */ - -#ifndef __GSD_WACOM_BUTTON_EDITOR_H__ -#define __GSD_WACOM_BUTTON_EDITOR_H__ - -#include <glib.h> -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define GSD_WACOM_BUTTON_EDITOR_TYPE (gsd_wacom_button_editor_get_type ()) -#define GSD_WACOM_BUTTON_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_WACOM_BUTTON_EDITOR_TYPE, GsdWacomButtonEditor)) -#define GSD_WACOM_IS_BUTTON_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_WACOM_BUTTON_EDITOR_TYPE)) -#define GSD_WACOM_BUTTON_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_WACOM_BUTTON_EDITOR_TYPE, GsdWacomButtonEditorClass)) -#define GSD_WACOM_IS_BUTTON_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_WACOM_BUTTON_EDITOR_TYPE)) -#define GSD_WACOM_BUTTON_EDITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_WACOM_BUTTON_EDITOR_TYPE, GsdWacomButtonEditorClass)) - -typedef struct _GsdWacomButtonEditor GsdWacomButtonEditor; -typedef struct _GsdWacomButtonEditorClass GsdWacomButtonEditorClass; -typedef struct _GsdWacomButtonEditorPrivate GsdWacomButtonEditorPrivate; - - -struct _GsdWacomButtonEditor -{ - GtkGrid parent_instance; - - /*< private >*/ - GsdWacomButtonEditorPrivate *priv; -}; - -struct _GsdWacomButtonEditorClass -{ - GtkGridClass parent_class; - - void (* button_edited) (void); - void (* done_editing) (void); -}; - -GtkWidget * gsd_wacom_button_editor_new (void); - -void gsd_wacom_button_editor_set_button (GsdWacomButtonEditor *self, - GsdWacomTabletButton *button, - GtkDirectionType direction); - -GsdWacomTabletButton * gsd_wacom_button_editor_get_button (GsdWacomButtonEditor *self, - GtkDirectionType *direction); - - -GType gsd_wacom_button_editor_get_type (void); - -#endif /* __GSD_WACOM_BUTTON_EDITOR_H__ */ diff --git a/plugins/wacom/gsd-wacom-device.c b/plugins/wacom/gsd-wacom-device.c deleted file mode 100644 index 33d9cc58..00000000 --- a/plugins/wacom/gsd-wacom-device.c +++ /dev/null @@ -1,2286 +0,0 @@ -/* - * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. - * - * Author: Bastien Nocera <hadess@hadess.net> - * - */ - -#include "config.h" - -#include <glib.h> -#include <glib/gi18n-lib.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#include <gdk/gdkx.h> -#include <X11/Xatom.h> -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include <libgnome-desktop/gnome-rr.h> - -#include <libwacom/libwacom.h> -#include <X11/extensions/XInput.h> -#include <X11/extensions/XInput2.h> - -#include "gsd-input-helper.h" - -#include "gsd-enums.h" -#include "gsd-wacom-device.h" -#include "gsd-device-manager.h" -#include "gsd-device-manager-x11.h" - -#define GSD_WACOM_STYLUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_STYLUS, GsdWacomStylusPrivate)) - -#define WACOM_TABLET_SCHEMA "org.gnome.settings-daemon.peripherals.wacom" -#define WACOM_DEVICE_CONFIG_BASE "/org/gnome/settings-daemon/peripherals/wacom/%s-%s/" -#define WACOM_STYLUS_SCHEMA "org.gnome.settings-daemon.peripherals.wacom.stylus" -#define WACOM_ERASER_SCHEMA "org.gnome.settings-daemon.peripherals.wacom.eraser" -#define WACOM_BUTTON_SCHEMA "org.gnome.settings-daemon.peripherals.wacom.tablet-button" - -static struct { - GnomeRRRotation rotation; - GsdWacomRotation rotation_wacom; - const gchar *rotation_string; -} rotation_table[] = { - { GNOME_RR_ROTATION_0, GSD_WACOM_ROTATION_NONE, "none" }, - { GNOME_RR_ROTATION_90, GSD_WACOM_ROTATION_CCW, "ccw" }, - { GNOME_RR_ROTATION_180, GSD_WACOM_ROTATION_HALF, "half" }, - { GNOME_RR_ROTATION_270, GSD_WACOM_ROTATION_CW, "cw" } -}; - -static WacomDeviceDatabase *db = NULL; - -struct GsdWacomStylusPrivate -{ - GsdWacomDevice *device; - int id; - WacomStylusType type; - char *name; - const char *icon_name; - GSettings *settings; - gboolean has_eraser; - int num_buttons; -}; - -static void gsd_wacom_stylus_class_init (GsdWacomStylusClass *klass); -static void gsd_wacom_stylus_init (GsdWacomStylus *wacom_stylus); -static void gsd_wacom_stylus_finalize (GObject *object); - -G_DEFINE_TYPE (GsdWacomStylus, gsd_wacom_stylus, G_TYPE_OBJECT) - -static void -gsd_wacom_stylus_class_init (GsdWacomStylusClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = gsd_wacom_stylus_finalize; - - g_type_class_add_private (klass, sizeof (GsdWacomStylusPrivate)); -} - -static void -gsd_wacom_stylus_init (GsdWacomStylus *stylus) -{ - stylus->priv = GSD_WACOM_STYLUS_GET_PRIVATE (stylus); -} - -static void -gsd_wacom_stylus_finalize (GObject *object) -{ - GsdWacomStylus *stylus; - GsdWacomStylusPrivate *p; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSD_IS_WACOM_STYLUS (object)); - - stylus = GSD_WACOM_STYLUS (object); - - g_return_if_fail (stylus->priv != NULL); - - p = stylus->priv; - - if (p->settings != NULL) { - g_object_unref (p->settings); - p->settings = NULL; - } - - g_free (p->name); - p->name = NULL; - - G_OBJECT_CLASS (gsd_wacom_stylus_parent_class)->finalize (object); -} - -static const char * -get_icon_name_from_type (const WacomStylus *wstylus) -{ - WacomStylusType type = libwacom_stylus_get_type (wstylus); - - switch (type) { - case WSTYLUS_INKING: - case WSTYLUS_STROKE: - /* The stroke pen is the same as the inking pen with - * a different nib */ - return "wacom-stylus-inking"; - case WSTYLUS_AIRBRUSH: - return "wacom-stylus-airbrush"; - case WSTYLUS_MARKER: - return "wacom-stylus-art-pen"; - case WSTYLUS_CLASSIC: - return "wacom-stylus-classic"; - default: - if (!libwacom_stylus_has_eraser (wstylus)) - return "wacom-stylus-no-eraser"; - return "wacom-stylus"; - } -} - -static GsdWacomStylus * -gsd_wacom_stylus_new (GsdWacomDevice *device, - const WacomStylus *wstylus, - GSettings *settings) -{ - GsdWacomStylus *stylus; - - g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); - g_return_val_if_fail (wstylus != NULL, NULL); - - stylus = GSD_WACOM_STYLUS (g_object_new (GSD_TYPE_WACOM_STYLUS, - NULL)); - stylus->priv->device = device; - stylus->priv->id = libwacom_stylus_get_id (wstylus); - stylus->priv->name = g_strdup (libwacom_stylus_get_name (wstylus)); - stylus->priv->settings = settings; - stylus->priv->type = libwacom_stylus_get_type (wstylus); - stylus->priv->icon_name = get_icon_name_from_type (wstylus); - stylus->priv->has_eraser = libwacom_stylus_has_eraser (wstylus); - stylus->priv->num_buttons = libwacom_stylus_get_num_buttons (wstylus); - - return stylus; -} - -GSettings * -gsd_wacom_stylus_get_settings (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL); - - return stylus->priv->settings; -} - -const char * -gsd_wacom_stylus_get_name (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL); - - return stylus->priv->name; -} - -const char * -gsd_wacom_stylus_get_icon_name (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL); - - return stylus->priv->icon_name; -} - -GsdWacomDevice * -gsd_wacom_stylus_get_device (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL); - - return stylus->priv->device; -} - -gboolean -gsd_wacom_stylus_get_has_eraser (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), FALSE); - - return stylus->priv->has_eraser; -} - -guint -gsd_wacom_stylus_get_num_buttons (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), -1); - - return stylus->priv->num_buttons; -} - -GsdWacomStylusType -gsd_wacom_stylus_get_stylus_type (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), WACOM_STYLUS_TYPE_UNKNOWN); - - switch (stylus->priv->type) { - case WSTYLUS_UNKNOWN: - return WACOM_STYLUS_TYPE_UNKNOWN; - case WSTYLUS_GENERAL: - return WACOM_STYLUS_TYPE_GENERAL; - case WSTYLUS_INKING: - return WACOM_STYLUS_TYPE_INKING; - case WSTYLUS_AIRBRUSH: - return WACOM_STYLUS_TYPE_AIRBRUSH; - case WSTYLUS_CLASSIC: - return WACOM_STYLUS_TYPE_CLASSIC; - case WSTYLUS_MARKER: - return WACOM_STYLUS_TYPE_MARKER; - case WSTYLUS_STROKE: - return WACOM_STYLUS_TYPE_STROKE; - case WSTYLUS_PUCK: - return WACOM_STYLUS_TYPE_PUCK; - default: - g_assert_not_reached (); - } - - return WACOM_STYLUS_TYPE_UNKNOWN; -} - -int -gsd_wacom_stylus_get_id (GsdWacomStylus *stylus) -{ - g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), -1); - - return stylus->priv->id; -} - -/* Tablet buttons */ -static GsdWacomTabletButton * -gsd_wacom_tablet_button_new (const char *name, - const char *id, - const char *settings_path, - GsdWacomTabletButtonType type, - GsdWacomTabletButtonPos pos, - int group_id, - int idx, - int status_led, - int has_oled) -{ - GsdWacomTabletButton *ret; - - ret = g_new0 (GsdWacomTabletButton, 1); - ret->name = g_strdup (name); - ret->id = g_strdup (id); - if (type != WACOM_TABLET_BUTTON_TYPE_HARDCODED) { - char *button_settings_path; - - button_settings_path = g_strdup_printf ("%s%s/", settings_path, id); - ret->settings = g_settings_new_with_path (WACOM_BUTTON_SCHEMA, button_settings_path); - g_free (button_settings_path); - } - ret->group_id = group_id; - ret->idx = idx; - ret->type = type; - ret->pos = pos; - ret->status_led = status_led; - ret->has_oled = has_oled; - - return ret; -} - -void -gsd_wacom_tablet_button_free (GsdWacomTabletButton *button) -{ - g_return_if_fail (button != NULL); - - if (button->settings != NULL) - g_object_unref (button->settings); - g_free (button->name); - g_free (button->id); - g_free (button); -} - -GsdWacomTabletButton * -gsd_wacom_tablet_button_copy (GsdWacomTabletButton *button) -{ - GsdWacomTabletButton *ret; - - g_return_val_if_fail (button != NULL, NULL); - - ret = g_new0 (GsdWacomTabletButton, 1); - ret->name = g_strdup (button->name); - if (button->settings != NULL) - ret->settings = g_object_ref (button->settings); - ret->id = button->id; - ret->type = button->type; - ret->group_id = button->group_id; - - return ret; -} - -#define GSD_WACOM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_DEVICE, GsdWacomDevicePrivate)) - -/* we support two types of settings: - * Tablet-wide settings: applied to each tool on the tablet. e.g. rotation - * Tool-specific settings: applied to one tool only. - */ -#define SETTINGS_WACOM_DIR "org.gnome.settings-daemon.peripherals.wacom" -#define SETTINGS_STYLUS_DIR "stylus" -#define SETTINGS_ERASER_DIR "eraser" - -struct GsdWacomDevicePrivate -{ - GdkDevice *gdk_device; - int device_id; - int opcode; - - GsdWacomDeviceType type; - char *name; - char *path; - char *machine_id; - const char *icon_name; - char *layout_path; - char *tool_name; - gboolean reversible; - gboolean is_screen_tablet; - gboolean is_isd; /* integrated system device */ - gboolean is_fallback; - GList *styli; - GsdWacomStylus *last_stylus; - GList *buttons; - gint num_rings; - gint num_strips; - GHashTable *modes; /* key = int (group), value = int (index) */ - GHashTable *num_modes; /* key = int (group), value = int (index) */ - GSettings *wacom_settings; -}; - -enum { - PROP_0, - PROP_GDK_DEVICE, - PROP_LAST_STYLUS -}; - -static void gsd_wacom_device_class_init (GsdWacomDeviceClass *klass); -static void gsd_wacom_device_init (GsdWacomDevice *wacom_device); -static void gsd_wacom_device_finalize (GObject *object); - -G_DEFINE_TYPE (GsdWacomDevice, gsd_wacom_device, G_TYPE_OBJECT) - -static GdkFilterReturn -filter_events (XEvent *xevent, - GdkEvent *event, - GsdWacomDevice *device) -{ - XIEvent *xiev; - XIPropertyEvent *pev; - XGenericEventCookie *cookie; - char *name; - int tool_id; - - /* verify we have a property event */ - if (xevent->type != GenericEvent) - return GDK_FILTER_CONTINUE; - - cookie = &xevent->xcookie; - if (cookie->extension != device->priv->opcode) - return GDK_FILTER_CONTINUE; - - xiev = (XIEvent *) xevent->xcookie.data; - - if (xiev->evtype != XI_PropertyEvent) - return GDK_FILTER_CONTINUE; - - pev = (XIPropertyEvent *) xiev; - - /* Is the event for us? */ - if (pev->deviceid != device->priv->device_id) - return GDK_FILTER_CONTINUE; - - name = XGetAtomName (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), pev->property); - if (name == NULL || - g_strcmp0 (name, WACOM_SERIAL_IDS_PROP) != 0) { - if (name) - XFree (name); - return GDK_FILTER_CONTINUE; - } - XFree (name); - - tool_id = xdevice_get_last_tool_id (device->priv->device_id); - if (tool_id == -1) { - g_warning ("Failed to get value for changed stylus ID on device '%d'", device->priv->device_id); - return GDK_FILTER_CONTINUE; - } - gsd_wacom_device_set_current_stylus (device, tool_id); - - return GDK_FILTER_CONTINUE; -} - -static gboolean -setup_property_notify (GsdWacomDevice *device) -{ - Display *dpy; - XIEventMask evmask; - int tool_id; - - evmask.deviceid = device->priv->device_id; - evmask.mask_len = XIMaskLen (XI_PropertyEvent); - evmask.mask = g_new0 (guchar, evmask.mask_len); - XISetMask (evmask.mask, XI_PropertyEvent); - - dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - - gdk_error_trap_push (); - XISelectEvents (dpy, DefaultRootWindow (dpy), &evmask, 1); - g_free (evmask.mask); - if (gdk_error_trap_pop ()) - return TRUE; - - gdk_window_add_filter (NULL, - (GdkFilterFunc) filter_events, - device); - - tool_id = xdevice_get_last_tool_id (device->priv->device_id); - if (tool_id == -1) { - g_warning ("Failed to get value for changed stylus ID on device '%d", device->priv->device_id); - return TRUE; - } - gsd_wacom_device_set_current_stylus (device, tool_id); - - return TRUE; -} - -static GsdWacomDeviceType -get_device_type (XDeviceInfo *dev) -{ - GsdWacomDeviceType ret; - static Atom stylus, cursor, eraser, pad, touch, prop; - XDevice *device; - Atom realtype; - int realformat; - unsigned long nitems, bytes_after; - unsigned char *data = NULL; - int rc; - - ret = WACOM_TYPE_INVALID; - - if ((dev->use == IsXPointer) || (dev->use == IsXKeyboard)) - return ret; - - if (!stylus) - stylus = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "STYLUS", False); - if (!eraser) - eraser = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "ERASER", False); - if (!cursor) - cursor = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "CURSOR", False); - if (!pad) - pad = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "PAD", False); - if (!touch) - touch = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "TOUCH", False); - if (!prop) - prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Wacom Tool Type", False); - - if (dev->type == stylus) - ret = WACOM_TYPE_STYLUS; - else if (dev->type == eraser) - ret = WACOM_TYPE_ERASER; - else if (dev->type == cursor) - ret = WACOM_TYPE_CURSOR; - else if (dev->type == pad) - ret = WACOM_TYPE_PAD; - else if (dev->type == touch) - ret = WACOM_TYPE_TOUCH; - - if (ret == WACOM_TYPE_INVALID) - return ret; - - /* There is currently no good way of detecting the driver for a device - * other than checking for a driver-specific property. - * Wacom Tool Type exists on all tools - */ - gdk_error_trap_push (); - device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), dev->id); - if (gdk_error_trap_pop () || (device == NULL)) - return ret; - - gdk_error_trap_push (); - - rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), - device, prop, 0, 1, False, - XA_ATOM, &realtype, &realformat, &nitems, - &bytes_after, &data); - - if (gdk_error_trap_pop () || rc != Success || realtype == None) - ret = WACOM_TYPE_INVALID; - - xdevice_close (device); - - XFree (data); - - return ret; -} - -/* Finds an output which matches the given EDID information. Any NULL - * parameter will be interpreted to match any value. */ -static GnomeRROutput * -find_output_by_edid (GnomeRRScreen *rr_screen, const gchar *vendor, const gchar *product, const gchar *serial) -{ - GnomeRROutput **rr_outputs; - GnomeRROutput *retval = NULL; - guint i; - - rr_outputs = gnome_rr_screen_list_outputs (rr_screen); - - for (i = 0; rr_outputs[i] != NULL; i++) { - gchar *o_vendor; - gchar *o_product; - gchar *o_serial; - gboolean match; - - gnome_rr_output_get_ids_from_edid (rr_outputs[i], - &o_vendor, - &o_product, - &o_serial); - - g_debug ("Checking for match between '%s','%s','%s' and '%s','%s','%s'", \ - vendor, product, serial, o_vendor, o_product, o_serial); - - match = (vendor == NULL || g_strcmp0 (vendor, o_vendor) == 0) && \ - (product == NULL || g_strcmp0 (product, o_product) == 0) && \ - (serial == NULL || g_strcmp0 (serial, o_serial) == 0); - - g_free (o_vendor); - g_free (o_product); - g_free (o_serial); - - if (match) { - retval = rr_outputs[i]; - break; - } - } - - if (retval == NULL) - g_debug ("Did not find a matching output for EDID '%s,%s,%s'", - vendor, product, serial); - - return retval; -} - -static GnomeRROutput* -find_builtin_output (GnomeRRScreen *rr_screen) -{ - GnomeRROutput **rr_outputs; - GnomeRROutput *retval = NULL; - guint i; - - rr_outputs = gnome_rr_screen_list_outputs (rr_screen); - for (i = 0; rr_outputs[i] != NULL; i++) { - if (gnome_rr_output_is_builtin_display(rr_outputs[i])) { - retval = rr_outputs[i]; - break; - } - } - - if (retval == NULL) - g_debug ("Did not find a built-in monitor"); - - return retval; -} - -static GnomeRROutput * -find_output_by_heuristic (GnomeRRScreen *rr_screen, GsdWacomDevice *device) -{ - GnomeRROutput *rr_output; - - /* TODO: This heuristic will fail for non-Wacom display - * tablets and may give the wrong result if multiple Wacom - * display tablets are connected. - */ - rr_output = find_output_by_edid (rr_screen, "WAC", NULL, NULL); - - if (!rr_output) - rr_output = find_builtin_output (rr_screen); - - return rr_output; -} - -static GnomeRROutput * -find_output_by_display (GnomeRRScreen *rr_screen, GsdWacomDevice *device) -{ - gsize n; - GSettings *tablet; - GVariant *display; - const gchar **edid; - GnomeRROutput *ret; - GsdDevice *gsd_device; - - if (device == NULL) - return NULL; - - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get ()), - device->priv->gdk_device); - - if (gsd_device == NULL) - return NULL; - - ret = NULL; - tablet = gsd_device_get_settings (gsd_device); - display = g_settings_get_value (tablet, "display"); - edid = g_variant_get_strv (display, &n); - - if (n != 3) { - g_critical ("Expected 'display' key to store %d values; got %"G_GSIZE_FORMAT".", 3, n); - goto out; - } - - if (strlen (edid[0]) == 0 || strlen (edid[1]) == 0 || strlen (edid[2]) == 0) - goto out; - - ret = find_output_by_edid (rr_screen, edid[0], edid[1], edid[2]); - -out: - g_free (edid); - g_variant_unref (display); - g_object_unref (tablet); - - return ret; -} - -static gboolean -is_on (GnomeRROutput *output) -{ - GnomeRRCrtc *crtc; - - crtc = gnome_rr_output_get_crtc (output); - if (!crtc) - return FALSE; - return gnome_rr_crtc_get_current_mode (crtc) != NULL; -} - -static GnomeRROutput * -find_output_by_monitor (GnomeRRScreen *rr_screen, - GdkScreen *screen, - int monitor) -{ - GnomeRROutput **rr_outputs; - GnomeRROutput *ret; - guint i; - - ret = NULL; - - rr_outputs = gnome_rr_screen_list_outputs (rr_screen); - - for (i = 0; rr_outputs[i] != NULL; i++) { - GnomeRROutput *rr_output; - GnomeRRCrtc *crtc; - int x, y; - - rr_output = rr_outputs[i]; - - if (!is_on (rr_output)) - continue; - - crtc = gnome_rr_output_get_crtc (rr_output); - if (!crtc) - continue; - - gnome_rr_crtc_get_position (crtc, &x, &y); - - if (monitor == gdk_screen_get_monitor_at_point (screen, x, y)) { - ret = rr_output; - break; - } - } - - if (ret == NULL) - g_warning ("No output found for monitor %d.", monitor); - - return ret; -} - -static void -set_display_by_output (GsdWacomDevice *device, - GnomeRROutput *rr_output) -{ - GSettings *tablet; - GVariant *c_array; - GVariant *n_array; - gsize nvalues; - gchar *o_vendor, *o_product, *o_serial; - const gchar *values[3]; - GsdDevice *gsd_device; - - if (device == NULL) - return; - - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get ()), - device->priv->gdk_device); - - if (gsd_device == NULL) - return; - - tablet = gsd_device_get_settings (gsd_device); - c_array = g_settings_get_value (tablet, "display"); - g_variant_get_strv (c_array, &nvalues); - if (nvalues != 3) { - g_warning ("Unable set set display property. Got %"G_GSIZE_FORMAT" items; expected %d items.\n", nvalues, 4); - g_object_unref (tablet); - return; - } - - if (rr_output == NULL) { - o_vendor = g_strdup (""); - o_product = g_strdup (""); - o_serial = g_strdup (""); - } else { - gnome_rr_output_get_ids_from_edid (rr_output, - &o_vendor, - &o_product, - &o_serial); - } - - values[0] = o_vendor; - values[1] = o_product; - values[2] = o_serial; - n_array = g_variant_new_strv ((const gchar * const *) &values, 3); - g_settings_set_value (tablet, "display", n_array); - - g_free (o_vendor); - g_free (o_product); - g_free (o_serial); - g_object_unref (tablet); -} - -static GsdWacomRotation -get_rotation_wacom (GnomeRRRotation rotation) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (rotation_table); i++) { - if (rotation_table[i].rotation & rotation) - return (rotation_table[i].rotation_wacom); - } - g_assert_not_reached (); -} - -void -gsd_wacom_device_set_display (GsdWacomDevice *device, - int monitor) -{ - GError *error = NULL; - GnomeRRScreen *rr_screen; - GnomeRROutput *output = NULL; - - g_return_if_fail (GSD_IS_WACOM_DEVICE (device)); - - rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error); - if (rr_screen == NULL) { - g_warning ("Failed to create GnomeRRScreen: %s", error->message); - g_error_free (error); - return; - } - - if (monitor > GSD_WACOM_SET_ALL_MONITORS) - output = find_output_by_monitor (rr_screen, gdk_screen_get_default (), monitor); - set_display_by_output (device, output); - - g_object_unref (rr_screen); -} - -static GnomeRROutput * -find_output (GnomeRRScreen *rr_screen, - GsdWacomDevice *device) -{ - GnomeRROutput *rr_output; - rr_output = find_output_by_display (rr_screen, device); - - if (rr_output == NULL) { - if (gsd_wacom_device_is_screen_tablet (device)) { - rr_output = find_output_by_heuristic (rr_screen, device); - if (rr_output == NULL) - g_warning ("No fuzzy match based on heuristics was found."); - else - g_warning ("Automatically mapping tablet to heuristically-found display."); - } - } - - return rr_output; -} - -int -gsd_wacom_device_get_display_monitor (GsdWacomDevice *device) -{ - GError *error = NULL; - GnomeRRScreen *rr_screen; - GnomeRROutput *rr_output; - GnomeRRMode *mode; - GnomeRRCrtc *crtc; - gint area[4]; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), GSD_WACOM_SET_ALL_MONITORS); - - rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error); - if (rr_screen == NULL) { - g_warning ("Failed to create GnomeRRScreen: %s", error->message); - g_error_free (error); - return GSD_WACOM_SET_ALL_MONITORS; - } - - rr_output = find_output (rr_screen, device); - if (rr_output == NULL) { - g_object_unref (rr_screen); - return GSD_WACOM_SET_ALL_MONITORS; - } - - if (!is_on (rr_output)) { - g_warning ("Output is not active."); - g_object_unref (rr_screen); - return GSD_WACOM_SET_ALL_MONITORS; - } - - crtc = gnome_rr_output_get_crtc (rr_output); - gnome_rr_crtc_get_position (crtc, &area[0], &area[1]); - - mode = gnome_rr_crtc_get_current_mode (crtc); - area[2] = gnome_rr_mode_get_width (mode); - area[3] = gnome_rr_mode_get_height (mode); - - g_object_unref (rr_screen); - - if (area[2] <= 0 || area[3] <= 0) { - g_warning ("Output has non-positive area."); - return GSD_WACOM_SET_ALL_MONITORS; - } - - g_debug ("Area: %d,%d %dx%d", area[0], area[1], area[2], area[3]); - return gdk_screen_get_monitor_at_point (gdk_screen_get_default (), area[0], area[1]); -} - -GsdWacomRotation -gsd_wacom_device_get_display_rotation (GsdWacomDevice *device) -{ - GnomeRRScreen *rr_screen; - GnomeRROutput *rr_output; - GnomeRRRotation rotation = GNOME_RR_ROTATION_0; - - rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), NULL); - - if (rr_screen == NULL) - return GSD_WACOM_ROTATION_NONE; - - rr_output = find_output_by_display (rr_screen, device); - - if (rr_output) { - GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (rr_output); - if (crtc) - rotation = gnome_rr_crtc_get_current_rotation (crtc); - } - - g_object_unref (rr_screen); - - return get_rotation_wacom (rotation); -} - -static void -add_stylus_to_device (GsdWacomDevice *device, - const char *settings_path, - int id) -{ - const WacomStylus *wstylus; - - wstylus = libwacom_stylus_get_for_id (db, id); - if (wstylus) { - GsdWacomStylus *stylus; - char *stylus_settings_path; - GSettings *settings; - - if (device->priv->type == WACOM_TYPE_STYLUS && - libwacom_stylus_is_eraser (wstylus)) - return; - if (device->priv->type == WACOM_TYPE_ERASER && - libwacom_stylus_is_eraser (wstylus) == FALSE) - return; - - stylus_settings_path = g_strdup_printf ("%s0x%x/", settings_path, id); - if (device->priv->type == WACOM_TYPE_STYLUS) { - settings = g_settings_new_with_path (WACOM_STYLUS_SCHEMA, stylus_settings_path); - stylus = gsd_wacom_stylus_new (device, wstylus, settings); - } else { - settings = g_settings_new_with_path (WACOM_ERASER_SCHEMA, stylus_settings_path); - stylus = gsd_wacom_stylus_new (device, wstylus, settings); - } - g_free (stylus_settings_path); - device->priv->styli = g_list_prepend (device->priv->styli, stylus); - } -} - -int -gsd_wacom_device_get_num_modes (GsdWacomDevice *device, - int group_id) -{ - int num_modes; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), -1); - num_modes = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->num_modes, GINT_TO_POINTER(group_id))); - - return num_modes; -} - -int -gsd_wacom_device_get_current_mode (GsdWacomDevice *device, - int group_id) -{ - int current_idx; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), -1); - current_idx = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->modes, GINT_TO_POINTER(group_id))); - /* That means that the mode doesn't exist, see gsd_wacom_device_add_modes() */ - g_return_val_if_fail (current_idx != 0, -1); - - return current_idx; -} - -int -gsd_wacom_device_set_next_mode (GsdWacomDevice *device, - GsdWacomTabletButton *button) -{ - GList *l; - int current_idx; - int num_modes; - int num_switches; - int group_id; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), -1); - - group_id = button->group_id; - current_idx = 0; - num_switches = 0; - num_modes = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->num_modes, GINT_TO_POINTER(group_id))); - - /* - * Check if we have multiple mode-switch buttons for that - * group, and if so, compute the current index based on - * the position in the list... - */ - for (l = device->priv->buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *b = l->data; - if (b->type != WACOM_TABLET_BUTTON_TYPE_HARDCODED) - continue; - if (button->group_id == b->group_id) - num_switches++; - if (g_strcmp0 (button->id, b->id) == 0) - current_idx = num_switches; - } - - /* We should at least have found the current mode-switch button... - * If not, then it means that the given button is not a valid - * mode-switch. - */ - g_return_val_if_fail (num_switches != 0, -1); - - /* Only one mode-switch? cycle through the modes */ - if (num_switches == 1) { - current_idx = gsd_wacom_device_get_current_mode (device, group_id); - /* gsd_wacom_device_get_current_mode() returns -1 when the mode doesn't exist */ - g_return_val_if_fail (current_idx > 0, -1); - - current_idx++; - } - - if (current_idx > num_modes) - current_idx = 1; - - g_hash_table_insert (device->priv->modes, GINT_TO_POINTER (group_id), GINT_TO_POINTER (current_idx)); - - return current_idx; -} - -static int -flags_to_group (WacomButtonFlags flags) -{ - if (flags & WACOM_BUTTON_RING_MODESWITCH) - return 1; - if (flags & WACOM_BUTTON_RING2_MODESWITCH) - return 2; - if (flags & WACOM_BUTTON_TOUCHSTRIP_MODESWITCH) - return 3; - if (flags & WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH) - return 4; - - return 0; -} - -static GList * -gsd_wacom_device_add_ring_modes (WacomDevice *wacom_device, - const char *settings_path, - WacomButtonFlags direction) -{ - GList *l; - guint num_modes; - guint group; - guint i; - char *name, *id; - - l = NULL; - - if ((direction & WACOM_BUTTON_POSITION_LEFT) && libwacom_has_ring (wacom_device)) { - num_modes = libwacom_get_ring_num_modes (wacom_device); - group = flags_to_group (WACOM_BUTTON_RING_MODESWITCH); - if (num_modes == 0) { - /* If no mode is available, we use "left-ring-mode-1" for backward compat */ - l = g_list_append (l, gsd_wacom_tablet_button_new (_("Left Ring"), - "left-ring-mode-1", - settings_path, - WACOM_TABLET_BUTTON_TYPE_RING, - WACOM_TABLET_BUTTON_POS_LEFT, - group, - 0, - GSD_WACOM_NO_LED, - 0)); - } else { - for (i = 1; i <= num_modes; i++) { - name = g_strdup_printf (_("Left Ring Mode #%d"), i); - id = g_strdup_printf ("left-ring-mode-%d", i); - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_RING, - WACOM_TABLET_BUTTON_POS_LEFT, - group, - i - 1, - GSD_WACOM_NO_LED, - 0)); - g_free (name); - g_free (id); - } - } - } else if ((direction & WACOM_BUTTON_POSITION_RIGHT) && libwacom_has_ring2 (wacom_device)) { - num_modes = libwacom_get_ring2_num_modes (wacom_device); - group = flags_to_group (WACOM_BUTTON_RING2_MODESWITCH); - if (num_modes == 0) { - /* If no mode is available, we use "right-ring-mode-1" for backward compat */ - l = g_list_append (l, gsd_wacom_tablet_button_new (_("Right Ring"), - "right-ring-mode-1", - settings_path, - WACOM_TABLET_BUTTON_TYPE_RING, - WACOM_TABLET_BUTTON_POS_RIGHT, - group, - 0, - GSD_WACOM_NO_LED, - 0)); - } else { - for (i = 1; i <= num_modes; i++) { - name = g_strdup_printf (_("Right Ring Mode #%d"), i); - id = g_strdup_printf ("right-ring-mode-%d", i); - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_RING, - WACOM_TABLET_BUTTON_POS_RIGHT, - group, - i - 1, - GSD_WACOM_NO_LED, - 0)); - g_free (name); - g_free (id); - } - } - } - - return l; -} - -static GList * -gsd_wacom_device_add_strip_modes (WacomDevice *wacom_device, - const char *settings_path, - WacomButtonFlags direction) -{ - GList *l; - guint num_modes; - guint num_strips; - guint group; - guint i; - char *name, *id; - - l = NULL; - num_strips = libwacom_get_num_strips (wacom_device); - if (num_strips > 2) - g_warning ("Unhandled number of touchstrips: %d", num_strips); - - if ((direction & WACOM_BUTTON_POSITION_LEFT) && num_strips >= 1) { - num_modes = libwacom_get_strips_num_modes (wacom_device); - group = flags_to_group (WACOM_BUTTON_TOUCHSTRIP_MODESWITCH); - if (num_modes == 0) { - /* If no mode is available, we use "left-strip-mode-1" for backward compat */ - l = g_list_append (l, gsd_wacom_tablet_button_new (_("Left Touchstrip"), - "left-strip-mode-1", - settings_path, - WACOM_TABLET_BUTTON_TYPE_STRIP, - WACOM_TABLET_BUTTON_POS_LEFT, - group, - 0, - GSD_WACOM_NO_LED, - 0)); - } else { - for (i = 1; i <= num_modes; i++) { - name = g_strdup_printf (_("Left Touchstrip Mode #%d"), i); - id = g_strdup_printf ("left-strip-mode-%d", i); - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_STRIP, - WACOM_TABLET_BUTTON_POS_LEFT, - group, - i - 1, - GSD_WACOM_NO_LED, - 0)); - g_free (name); - g_free (id); - } - } - } else if ((direction & WACOM_BUTTON_POSITION_RIGHT) && num_strips >= 2) { - num_modes = libwacom_get_strips_num_modes (wacom_device); - group = flags_to_group (WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH); - if (num_modes == 0) { - /* If no mode is available, we use "right-strip-mode-1" for backward compat */ - l = g_list_append (l, gsd_wacom_tablet_button_new (_("Right Touchstrip"), - "right-strip-mode-1", - settings_path, - WACOM_TABLET_BUTTON_TYPE_STRIP, - WACOM_TABLET_BUTTON_POS_RIGHT, - group, - 0, - GSD_WACOM_NO_LED, - 0)); - } else { - for (i = 1; i <= num_modes; i++) { - name = g_strdup_printf (_("Right Touchstrip Mode #%d"), i); - id = g_strdup_printf ("right-strip-mode-%d", i); - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_STRIP, - WACOM_TABLET_BUTTON_POS_RIGHT, - group, - i - 1, - GSD_WACOM_NO_LED, - 0)); - g_free (name); - g_free (id); - } - } - } - - return l; -} - -static char * -gsd_wacom_device_modeswitch_name (WacomButtonFlags flags, - guint button_num) -{ - if (flags & WACOM_BUTTON_RINGS_MODESWITCH) { - if (flags & WACOM_BUTTON_POSITION_LEFT) - return g_strdup_printf (_("Left Touchring Mode Switch")); - else - return g_strdup_printf (_("Right Touchring Mode Switch")); - } else if (flags & WACOM_BUTTON_TOUCHSTRIPS_MODESWITCH) { - if (flags & WACOM_BUTTON_POSITION_LEFT) - return g_strdup_printf (_("Left Touchstrip Mode Switch")); - else - return g_strdup_printf (_("Right Touchstrip Mode Switch")); - } - - g_warning ("Unhandled modeswitch and direction combination"); - - return g_strdup_printf (_("Mode Switch #%d"), button_num); -} - -static GsdWacomTabletButtonType -gsd_wacom_device_button_pos (WacomButtonFlags flags) -{ - if (flags & WACOM_BUTTON_POSITION_LEFT) - return WACOM_TABLET_BUTTON_POS_LEFT; - else if (flags & WACOM_BUTTON_POSITION_RIGHT) - return WACOM_TABLET_BUTTON_POS_RIGHT; - else if (flags & WACOM_BUTTON_POSITION_TOP) - return WACOM_TABLET_BUTTON_POS_TOP; - else if (flags & WACOM_BUTTON_POSITION_BOTTOM) - return WACOM_TABLET_BUTTON_POS_BOTTOM; - - g_warning ("Unhandled button position"); - - return WACOM_TABLET_BUTTON_POS_UNDEF; -} - -static GList * -gsd_wacom_device_add_buttons_dir (WacomDevice *wacom_device, - const char *settings_path, - WacomButtonFlags direction, - const char *button_str_id) -{ - GList *l; - guint num_buttons, i, button_num; - char *name, *id; - gboolean has_oled; - - l = NULL; - button_num = 1; - num_buttons = libwacom_get_num_buttons (wacom_device); - for (i = 'A'; i < 'A' + num_buttons; i++) { - WacomButtonFlags flags; - - flags = libwacom_get_button_flag (wacom_device, i); - if (!(flags & direction)) - continue; - /* Ignore mode switches */ - if (flags & WACOM_BUTTON_MODESWITCH) - continue; - - switch (direction) { - case WACOM_BUTTON_POSITION_LEFT: - name = g_strdup_printf (_("Left Button #%d"), button_num++); - break; - case WACOM_BUTTON_POSITION_RIGHT: - name = g_strdup_printf (_("Right Button #%d"), button_num++); - break; - case WACOM_BUTTON_POSITION_TOP: - name = g_strdup_printf (_("Top Button #%d"), button_num++); - break; - case WACOM_BUTTON_POSITION_BOTTOM: - name = g_strdup_printf (_("Bottom Button #%d"), button_num++); - break; - default: - g_assert_not_reached (); - } - - id = g_strdup_printf ("%s%c", button_str_id, i); - has_oled = (libwacom_get_button_flag (wacom_device, i) & WACOM_BUTTON_OLED) != 0; - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_NORMAL, - gsd_wacom_device_button_pos (flags), - flags_to_group (flags), - -1, - GSD_WACOM_NO_LED, - has_oled)); - g_free (name); - g_free (id); - } - - /* Handle modeswitches */ - for (i = 'A'; i < 'A' + num_buttons; i++) { - WacomButtonFlags flags; - char *name, *id; - int status_led; - - flags = libwacom_get_button_flag (wacom_device, i); - if (!(flags & direction)) - continue; - /* Ignore non-mode switches */ - if (!(flags & WACOM_BUTTON_MODESWITCH)) - continue; - - name = gsd_wacom_device_modeswitch_name (flags, button_num++); - id = g_strdup_printf ("%s%c", button_str_id, i); - status_led = libwacom_get_button_led_group (wacom_device, i); - l = g_list_append (l, gsd_wacom_tablet_button_new (name, - id, - settings_path, - WACOM_TABLET_BUTTON_TYPE_HARDCODED, - gsd_wacom_device_button_pos (flags), - flags_to_group (flags), - -1, - status_led, - FALSE)); - g_free (name); - g_free (id); - } - - /* Handle touch{strips,rings} */ - if (libwacom_has_ring2 (wacom_device) || libwacom_has_ring (wacom_device)) - l = g_list_concat (l, gsd_wacom_device_add_ring_modes (wacom_device, settings_path, direction)); - if (libwacom_get_num_strips (wacom_device) > 0) - l = g_list_concat (l, gsd_wacom_device_add_strip_modes (wacom_device, settings_path, direction)); - - return l; -} - -static void -gsd_wacom_device_add_buttons (GsdWacomDevice *device, - WacomDevice *wacom_device, - const char *settings_path) -{ - GList *l, *ret; - - ret = NULL; - - l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_LEFT, "button"); - if (l) - ret = l; - l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_RIGHT, "button"); - if (l) - ret = g_list_concat (ret, l); - l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_TOP, "button"); - if (l) - ret = g_list_concat (ret, l); - l = gsd_wacom_device_add_buttons_dir (wacom_device, settings_path, WACOM_BUTTON_POSITION_BOTTOM, "button"); - if (l) - ret = g_list_concat (ret, l); - - device->priv->buttons = ret; -} - -static void -gsd_wacom_device_get_modeswitches (WacomDevice *wacom_device, - gint *num_rings, - gint *num_strips) -{ - *num_strips = libwacom_get_num_strips (wacom_device); - - if (libwacom_has_ring2 (wacom_device)) - *num_rings = 2; - else if (libwacom_has_ring (wacom_device)) - *num_rings = 1; - else - *num_rings = 0; -} - -static void -gsd_wacom_device_add_modes (GsdWacomDevice *device, - WacomDevice *wacom_device) -{ - GList *l; - - device->priv->modes = g_hash_table_new (g_direct_hash, g_direct_equal); - device->priv->num_modes = g_hash_table_new (g_direct_hash, g_direct_equal); - - for (l = device->priv->buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *button = l->data; - - if (button->group_id > 0) - g_hash_table_insert (device->priv->modes, GINT_TO_POINTER (button->group_id), GINT_TO_POINTER (1)); - - /* See flags_to_group() for group ID/button type matches */ - if (button->group_id == 1) { - g_hash_table_insert (device->priv->num_modes, - GINT_TO_POINTER (button->group_id), - GINT_TO_POINTER (libwacom_get_ring_num_modes (wacom_device))); - } else if (button->group_id == 2) { - g_hash_table_insert (device->priv->num_modes, - GINT_TO_POINTER (button->group_id), - GINT_TO_POINTER (libwacom_get_ring2_num_modes (wacom_device))); - } else if (button->group_id == 3 || button->group_id == 4) { - g_hash_table_insert (device->priv->num_modes, - GINT_TO_POINTER (button->group_id), - GINT_TO_POINTER (libwacom_get_strips_num_modes (wacom_device))); - } - } -} - -static void -gsd_wacom_device_update_from_db (GsdWacomDevice *device, - WacomDevice *wacom_device, - const char *identifier) -{ - char *settings_path; - WacomIntegrationFlags integration_flags; - - settings_path = g_strdup_printf (WACOM_DEVICE_CONFIG_BASE, - device->priv->machine_id, - libwacom_get_match (wacom_device)); - device->priv->wacom_settings = g_settings_new_with_path (WACOM_TABLET_SCHEMA, - settings_path); - - device->priv->name = g_strdup (libwacom_get_name (wacom_device)); - device->priv->layout_path = g_strdup (libwacom_get_layout_filename (wacom_device)); - device->priv->reversible = libwacom_is_reversible (wacom_device); - integration_flags = libwacom_get_integration_flags (wacom_device); - device->priv->is_screen_tablet = (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY); - device->priv->is_isd = (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM); - if (device->priv->is_screen_tablet) { - if (!device->priv->is_isd) - device->priv->icon_name = "wacom-tablet-cintiq"; - else - device->priv->icon_name = "wacom-tablet-pc"; - } else { - device->priv->icon_name = "wacom-tablet"; - } - - if (device->priv->type == WACOM_TYPE_PAD) { - gsd_wacom_device_get_modeswitches (wacom_device, - &device->priv->num_rings, - &device->priv->num_strips); - gsd_wacom_device_add_buttons (device, wacom_device, settings_path); - gsd_wacom_device_add_modes (device, wacom_device); - } - - if (device->priv->type == WACOM_TYPE_STYLUS || - device->priv->type == WACOM_TYPE_ERASER) { - const int *ids; - int num_styli; - guint i; - - ids = libwacom_get_supported_styli (wacom_device, &num_styli); - g_assert (num_styli >= 1); - for (i = 0; i < num_styli; i++) - add_stylus_to_device (device, settings_path, ids[i]); - device->priv->styli = g_list_reverse (device->priv->styli); - } - g_free (settings_path); -} - -static GObject * -gsd_wacom_device_constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - GsdWacomDevice *device; - GdkDeviceManager *device_manager; - XDeviceInfo *device_info; - WacomDevice *wacom_device; - int n_devices; - guint i; - - device = GSD_WACOM_DEVICE (G_OBJECT_CLASS (gsd_wacom_device_parent_class)->constructor (type, - n_construct_properties, - construct_properties)); - - if (device->priv->gdk_device == NULL || - !GDK_IS_X11_DISPLAY (gdk_display_get_default ())) - return G_OBJECT (device); - - device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); - g_object_get (device_manager, "opcode", &device->priv->opcode, NULL); - - g_object_get (device->priv->gdk_device, "device-id", &device->priv->device_id, NULL); - - device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); - if (device_info == NULL) { - g_warning ("Could not list any input devices through XListInputDevices()"); - goto end; - } - - for (i = 0; i < n_devices; i++) { - if (device_info[i].id == device->priv->device_id) { - device->priv->type = get_device_type (&device_info[i]); - device->priv->tool_name = g_strdup (device_info[i].name); - break; - } - } - - XFreeDeviceList (device_info); - - if (device->priv->type == WACOM_TYPE_INVALID) - goto end; - - device->priv->path = xdevice_get_device_node (device->priv->device_id); - if (device->priv->path == NULL) { - g_warning ("Could not get the device node path for ID '%d'", device->priv->device_id); - device->priv->type = WACOM_TYPE_INVALID; - goto end; - } - - if (db == NULL) - db = libwacom_database_new (); - - wacom_device = libwacom_new_from_path (db, device->priv->path, FALSE, NULL); - if (!wacom_device) { - WacomError *wacom_error; - - g_debug ("Creating fallback driver for wacom tablet '%s' ('%s')", - gdk_device_get_name (device->priv->gdk_device), - device->priv->path); - - device->priv->is_fallback = TRUE; - wacom_error = libwacom_error_new (); - wacom_device = libwacom_new_from_path (db, device->priv->path, TRUE, wacom_error); - if (wacom_device == NULL) { - g_warning ("Failed to create fallback wacom device for '%s': %s (%d)", - device->priv->path, - libwacom_error_get_message (wacom_error), - libwacom_error_get_code (wacom_error)); - libwacom_error_free (&wacom_error); - device->priv->type = WACOM_TYPE_INVALID; - goto end; - } - libwacom_error_free (&wacom_error); - } - - gsd_wacom_device_update_from_db (device, wacom_device, device->priv->path); - libwacom_destroy (wacom_device); - - if (device->priv->type == WACOM_TYPE_STYLUS || - device->priv->type == WACOM_TYPE_ERASER) { - setup_property_notify (device); - } - -end: - return G_OBJECT (device); -} - -static void -gsd_wacom_device_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GsdWacomDevice *device; - - device = GSD_WACOM_DEVICE (object); - - switch (prop_id) { - case PROP_GDK_DEVICE: - device->priv->gdk_device = g_value_get_pointer (value); - break; - case PROP_LAST_STYLUS: - device->priv->last_stylus = g_value_get_pointer (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gsd_wacom_device_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GsdWacomDevice *device; - - device = GSD_WACOM_DEVICE (object); - - switch (prop_id) { - case PROP_GDK_DEVICE: - g_value_set_pointer (value, device->priv->gdk_device); - break; - case PROP_LAST_STYLUS: - g_value_set_pointer (value, device->priv->last_stylus); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gsd_wacom_device_class_init (GsdWacomDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructor = gsd_wacom_device_constructor; - object_class->finalize = gsd_wacom_device_finalize; - object_class->set_property = gsd_wacom_device_set_property; - object_class->get_property = gsd_wacom_device_get_property; - - g_type_class_add_private (klass, sizeof (GsdWacomDevicePrivate)); - - g_object_class_install_property (object_class, PROP_GDK_DEVICE, - g_param_spec_pointer ("gdk-device", "gdk-device", "gdk-device", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (object_class, PROP_LAST_STYLUS, - g_param_spec_pointer ("last-stylus", "last-stylus", "last-stylus", - G_PARAM_READWRITE)); -} - -static void -gsd_wacom_device_init (GsdWacomDevice *device) -{ - char *per_user_config; - - device->priv = GSD_WACOM_DEVICE_GET_PRIVATE (device); - device->priv->type = WACOM_TYPE_INVALID; - - per_user_config = g_build_filename (g_get_user_config_dir (), "gnome-settings-daemon", "no-per-machine-config", NULL); - if (g_file_test (per_user_config, G_FILE_TEST_EXISTS)) { - g_free (per_user_config); - goto fallback; - } - g_free (per_user_config); - - if (g_file_get_contents ("/etc/machine-id", &device->priv->machine_id, NULL, NULL) == FALSE) - if (g_file_get_contents ("/var/lib/dbus/machine-id", &device->priv->machine_id, NULL, NULL) == FALSE) - goto fallback; - - device->priv->machine_id = g_strstrip (device->priv->machine_id); - return; - -fallback: - device->priv->machine_id = g_strdup ("00000000000000000000000000000000"); -} - -static void -gsd_wacom_device_finalize (GObject *object) -{ - GsdWacomDevice *device; - GsdWacomDevicePrivate *p; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSD_IS_WACOM_DEVICE (object)); - - device = GSD_WACOM_DEVICE (object); - - g_return_if_fail (device->priv != NULL); - - p = device->priv; - - if (p->wacom_settings != NULL) { - g_object_unref (p->wacom_settings); - p->wacom_settings = NULL; - } - - g_list_foreach (p->styli, (GFunc) g_object_unref, NULL); - g_list_free (p->styli); - - g_list_foreach (p->buttons, (GFunc) gsd_wacom_tablet_button_free, NULL); - g_list_free (p->buttons); - - g_free (p->name); - p->name = NULL; - - g_free (p->tool_name); - p->tool_name = NULL; - - g_free (p->path); - p->path = NULL; - - g_free (p->machine_id); - p->machine_id = NULL; - - if (p->modes) { - g_hash_table_destroy (p->modes); - p->modes = NULL; - } - if (p->num_modes) { - g_hash_table_destroy (p->num_modes); - p->num_modes = NULL; - } - - g_clear_pointer (&p->layout_path, g_free); - - gdk_window_remove_filter (NULL, - (GdkFilterFunc) filter_events, - device); - - G_OBJECT_CLASS (gsd_wacom_device_parent_class)->finalize (object); -} - -GsdWacomDevice * -gsd_wacom_device_new (GdkDevice *device) -{ - return GSD_WACOM_DEVICE (g_object_new (GSD_TYPE_WACOM_DEVICE, - "gdk-device", device, - NULL)); -} - -GList * -gsd_wacom_device_list_styli (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return g_list_copy (device->priv->styli); -} - -GsdWacomStylus * -gsd_wacom_device_get_stylus_for_type (GsdWacomDevice *device, - GsdWacomStylusType type) -{ - GList *l; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - for (l = device->priv->styli; l != NULL; l = l->next) { - GsdWacomStylus *stylus = l->data; - - if (gsd_wacom_stylus_get_stylus_type (stylus) == type) - return stylus; - } - return NULL; -} - -const char * -gsd_wacom_device_get_name (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->name; -} - -const char * -gsd_wacom_device_get_layout_path (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->layout_path; -} - -const char * -gsd_wacom_device_get_path (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->path; -} - -const char * -gsd_wacom_device_get_icon_name (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->icon_name; -} - -const char * -gsd_wacom_device_get_tool_name (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->tool_name; -} - -gboolean -gsd_wacom_device_reversible (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE); - - return device->priv->reversible; -} - -gboolean -gsd_wacom_device_is_screen_tablet (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE); - - return device->priv->is_screen_tablet; -} - -gboolean -gsd_wacom_device_is_isd (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE); - - return device->priv->is_isd; -} - -gboolean -gsd_wacom_device_is_fallback (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE); - - return device->priv->is_fallback; -} - -gint -gsd_wacom_device_get_num_strips (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), 0); - - return device->priv->num_strips; -} - -gint -gsd_wacom_device_get_num_rings (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), 0); - - return device->priv->num_rings; -} - -GSettings * -gsd_wacom_device_get_settings (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return device->priv->wacom_settings; -} - -void -gsd_wacom_device_set_current_stylus (GsdWacomDevice *device, - int stylus_id) -{ - GList *l; - GsdWacomStylus *stylus; - - g_return_if_fail (GSD_IS_WACOM_DEVICE (device)); - - /* Don't change anything if the stylus is already set */ - if (device->priv->last_stylus != NULL) { - GsdWacomStylus *stylus = device->priv->last_stylus; - if (stylus->priv->id == stylus_id) - return; - } - - for (l = device->priv->styli; l; l = l->next) { - stylus = l->data; - - /* Set a nice default if 0x0 */ - if (stylus_id == 0x0 && - stylus->priv->type == WSTYLUS_GENERAL) { - g_object_set (device, "last-stylus", stylus, NULL); - return; - } - - if (stylus->priv->id == stylus_id) { - g_object_set (device, "last-stylus", stylus, NULL); - return; - } - } - - /* Setting the default stylus to be the generic one */ - for (l = device->priv->styli; l; l = l->next) { - stylus = l->data; - - /* Set a nice default if 0x0 */ - if (stylus->priv->type == WSTYLUS_GENERAL) { - g_debug ("Could not find stylus ID 0x%x for tablet '%s', setting general pen ID 0x%x instead", - stylus_id, device->priv->name, stylus->priv->id); - g_object_set (device, "last-stylus", stylus, NULL); - return; - } - } - - g_warning ("Could not set the current stylus ID 0x%x for tablet '%s', no general pen found", - stylus_id, device->priv->name); - - /* Setting the default stylus to be the first one */ - g_assert (device->priv->styli); - - stylus = device->priv->styli->data; - g_object_set (device, "last-stylus", stylus, NULL); -} - -GsdWacomDeviceType -gsd_wacom_device_get_device_type (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), WACOM_TYPE_INVALID); - - return device->priv->type; -} - -gint * -gsd_wacom_device_get_area (GsdWacomDevice *device) -{ - int i, id; - XDevice *xdevice; - Atom area, realtype; - int rc, realformat; - unsigned long nitems, bytes_after; - unsigned char *data = NULL; - gint *device_area; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - g_object_get (device->priv->gdk_device, "device-id", &id, NULL); - - area = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Wacom Tablet Area", False); - - gdk_error_trap_push (); - xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); - if (gdk_error_trap_pop () || (device == NULL)) - return NULL; - - gdk_error_trap_push (); - rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), - xdevice, area, 0, 4, False, - XA_INTEGER, &realtype, &realformat, &nitems, - &bytes_after, &data); - if (gdk_error_trap_pop () || rc != Success || realtype == None || bytes_after != 0 || nitems != 4) { - xdevice_close (xdevice); - return NULL; - } - - device_area = g_new0 (int, nitems); - for (i = 0; i < nitems; i++) - device_area[i] = ((long *)data)[i]; - - XFree (data); - xdevice_close (xdevice); - - return device_area; -} - -static gboolean -fill_old_axis (int device_id, - gint *items) -{ - int ndevices, i; - XDeviceInfoPtr list, slist; - gboolean retval = FALSE; - - slist = list = (XDeviceInfoPtr) XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &ndevices); - - for (i = 0; i < ndevices; i++, list++) { - XAnyClassPtr any = (XAnyClassPtr) (list->inputclassinfo); - int j; - - /* Core pointer and keyboard */ - if (list->use == IsXKeyboard || list->use == IsXPointer) - continue; - - if (list->id != device_id) - continue; - - for (j = 0; j < list->num_classes; j++) { - if (any->class == ValuatorClass) { - XValuatorInfoPtr V = (XValuatorInfoPtr) any; - XAxisInfoPtr ax = (XAxisInfoPtr) V->axes; - - if (V->num_axes >= 2) { - items[0] = ax[0].min_value; - items[2] = ax[0].max_value; - items[1] = ax[1].min_value; - items[3] = ax[1].max_value; - g_debug ("Found factory values for device calibration"); - retval = TRUE; - break; - } - } - - /* - * Increment 'any' to point to the next item in the linked - * list. The length is in bytes, so 'any' must be cast to - * a character pointer before being incremented. - */ - any = (XAnyClassPtr) ((char *) any + any->length); - } - } - XFreeDeviceList(slist); - - return retval; -} - -gint * -gsd_wacom_device_get_default_area (GsdWacomDevice *device) -{ - int id; - gint *device_area; - gboolean ret; - - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - if (!device->priv->gdk_device) - return NULL; - - g_object_get (device->priv->gdk_device, "device-id", &id, NULL); - - device_area = g_new0 (int, 4); - ret = fill_old_axis (id, device_area); - if (!ret) { - g_free (device_area); - return NULL; - } - - return device_area; -} - -const char * -gsd_wacom_device_type_to_string (GsdWacomDeviceType type) -{ - switch (type) { - case WACOM_TYPE_INVALID: - return "Invalid"; - case WACOM_TYPE_STYLUS: - return "Stylus"; - case WACOM_TYPE_ERASER: - return "Eraser"; - case WACOM_TYPE_CURSOR: - return "Cursor"; - case WACOM_TYPE_PAD: - return "Pad"; - case WACOM_TYPE_TOUCH: - return "Touch"; - default: - return "Unknown type"; - } -} - -GList * -gsd_wacom_device_get_buttons (GsdWacomDevice *device) -{ - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL); - - return g_list_copy (device->priv->buttons); -} - -static GsdWacomTabletButton * -find_button_with_id (GsdWacomDevice *device, - const char *id) -{ - GList *l; - - for (l = device->priv->buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *button = l->data; - - if (g_strcmp0 (button->id, id) == 0) - return button; - } - return NULL; -} - -static GsdWacomTabletButton * -find_button_with_index (GsdWacomDevice *device, - const char *id, - int index) -{ - GsdWacomTabletButton *button; - char *str; - - str = g_strdup_printf ("%s-mode-%d", id, index); - button = find_button_with_id (device, str); - g_free (str); - - return button; -} - -GsdWacomTabletButton * -gsd_wacom_device_get_button (GsdWacomDevice *device, - int button, - GtkDirectionType *dir) -{ - int index; - - if (button <= 26) { - char *id; - GsdWacomTabletButton *ret; - int physical_button; - - /* mouse_button = physical_button < 4 ? physical_button : physical_button + 4 */ - if (button > 4) - physical_button = button - 4; - else - physical_button = button; - - id = g_strdup_printf ("button%c", 'A' + physical_button - 1); - ret = find_button_with_id (device, id); - g_free (id); - - return ret; - } - - switch (button) { - case 90: - case 92: - case 94: - case 96: - *dir = GTK_DIR_UP; - break; - case 91: - case 93: - case 95: - case 97: - *dir = GTK_DIR_DOWN; - break; - default: - ;; - } - - /* The group ID is implied by the button number */ - switch (button) { - case 90: - case 91: - index = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->modes, GINT_TO_POINTER (1))); - return find_button_with_index (device, "left-ring", index); - case 92: - case 93: - index = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->modes, GINT_TO_POINTER (2))); - return find_button_with_index (device, "right-ring", index); - case 94: - case 95: - index = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->modes, GINT_TO_POINTER (3))); - return find_button_with_index (device, "left-strip", index); - case 96: - case 97: - index = GPOINTER_TO_INT (g_hash_table_lookup (device->priv->modes, GINT_TO_POINTER (4))); - return find_button_with_index (device, "right-strip", index); - default: - return NULL; - } -} - -GsdWacomRotation -gsd_wacom_device_rotation_name_to_type (const char *rotation) -{ - guint i; - - g_return_val_if_fail (rotation != NULL, GSD_WACOM_ROTATION_NONE); - - for (i = 0; i < G_N_ELEMENTS (rotation_table); i++) { - if (strcmp (rotation_table[i].rotation_string, rotation) == 0) - return (rotation_table[i].rotation_wacom); - } - - return GSD_WACOM_ROTATION_NONE; -} - -const char * -gsd_wacom_device_rotation_type_to_name (GsdWacomRotation type) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (rotation_table); i++) { - if (rotation_table[i].rotation_wacom == type) - return (rotation_table[i].rotation_string); - } - - return "none"; -} - -GdkDevice * -gsd_wacom_device_get_gdk_device (GsdWacomDevice *device) -{ - return device->priv->gdk_device; -} - -GsdWacomDevice * -gsd_wacom_device_create_fake (GsdWacomDeviceType type, - const char *name, - const char *tool_name) -{ - GsdWacomDevice *device; - GsdWacomDevicePrivate *priv; - WacomDevice *wacom_device; - - device = GSD_WACOM_DEVICE (g_object_new (GSD_TYPE_WACOM_DEVICE, NULL)); - - if (db == NULL) - db = libwacom_database_new (); - - wacom_device = libwacom_new_from_name (db, name, NULL); - if (wacom_device == NULL) - return NULL; - - priv = device->priv; - priv->type = type; - priv->tool_name = g_strdup (tool_name); - gsd_wacom_device_update_from_db (device, wacom_device, name); - libwacom_destroy (wacom_device); - - return device; -} - -GList * -gsd_wacom_device_create_fake_cintiq (void) -{ - GsdWacomDevice *device; - GList *devices; - - device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS, - "Wacom Cintiq 21UX2", - "Wacom Cintiq 21UX2 stylus"); - devices = g_list_prepend (NULL, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER, - "Wacom Cintiq 21UX2", - "Wacom Cintiq 21UX2 eraser"); - devices = g_list_prepend (devices, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD, - "Wacom Cintiq 21UX2", - "Wacom Cintiq 21UX2 pad"); - devices = g_list_prepend (devices, device); - - return devices; -} - -GList * -gsd_wacom_device_create_fake_bt (void) -{ - GsdWacomDevice *device; - GList *devices; - - device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS, - "Wacom Graphire Wireless", - "Graphire Wireless stylus"); - devices = g_list_prepend (NULL, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER, - "Wacom Graphire Wireless", - "Graphire Wireless eraser"); - devices = g_list_prepend (devices, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD, - "Wacom Graphire Wireless", - "Graphire Wireless pad"); - devices = g_list_prepend (devices, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_CURSOR, - "Wacom Graphire Wireless", - "Graphire Wireless cursor"); - devices = g_list_prepend (devices, device); - - return devices; -} - -GList * -gsd_wacom_device_create_fake_x201 (void) -{ - GsdWacomDevice *device; - GList *devices; - - device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS, - "Wacom Serial Tablet WACf004", - "Wacom Serial Tablet WACf004 stylus"); - devices = g_list_prepend (NULL, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER, - "Wacom Serial Tablet WACf004", - "Wacom Serial Tablet WACf004 eraser"); - devices = g_list_prepend (devices, device); - - return devices; -} - -GList * -gsd_wacom_device_create_fake_intuos4 (void) -{ - GsdWacomDevice *device; - GList *devices; - - device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS, - "Wacom Intuos4 6x9", - "Wacom Intuos4 6x9 stylus"); - devices = g_list_prepend (NULL, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER, - "Wacom Intuos4 6x9", - "Wacom Intuos4 6x9 eraser"); - devices = g_list_prepend (devices, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD, - "Wacom Intuos4 6x9", - "Wacom Intuos4 6x9 pad"); - devices = g_list_prepend (devices, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_CURSOR, - "Wacom Intuos4 6x9", - "Wacom Intuos4 6x9 cursor"); - devices = g_list_prepend (devices, device); - - return devices; -} - -GList * -gsd_wacom_device_create_fake_h610pro (void) -{ - GsdWacomDevice *device; - GList *devices; - - device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS, - "Huion H610 Pro", - "Huion H610 Pro stylus"); - if (!device) { - g_warning ("Not appending Huion H610 Pro, libwacom is not new enough"); - return NULL; - } - - devices = g_list_prepend (NULL, device); - - device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD, - "Huion H610 Pro", - "Huion H610 Pro pad"); - devices = g_list_prepend (devices, device); - - return devices; -} diff --git a/plugins/wacom/gsd-wacom-device.h b/plugins/wacom/gsd-wacom-device.h deleted file mode 100644 index 374eca91..00000000 --- a/plugins/wacom/gsd-wacom-device.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. - * - * Author: Bastien Nocera <hadess@hadess.net> - * - */ - -#ifndef __GSD_WACOM_DEVICE_MANAGER_H -#define __GSD_WACOM_DEVICE_MANAGER_H - -#include <glib-object.h> -#include "gsd-enums.h" - -G_BEGIN_DECLS - -#define GSD_TYPE_WACOM_DEVICE (gsd_wacom_device_get_type ()) -#define GSD_WACOM_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_WACOM_DEVICE, GsdWacomDevice)) -#define GSD_WACOM_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_WACOM_DEVICE, GsdWacomDeviceClass)) -#define GSD_IS_WACOM_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_WACOM_DEVICE)) -#define GSD_IS_WACOM_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_WACOM_DEVICE)) -#define GSD_WACOM_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_WACOM_DEVICE, GsdWacomDeviceClass)) - -typedef struct GsdWacomDevicePrivate GsdWacomDevicePrivate; - -typedef struct -{ - GObject parent; - GsdWacomDevicePrivate *priv; -} GsdWacomDevice; - -typedef struct -{ - GObjectClass parent_class; -} GsdWacomDeviceClass; - -#define GSD_TYPE_WACOM_STYLUS (gsd_wacom_stylus_get_type ()) -#define GSD_WACOM_STYLUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_WACOM_STYLUS, GsdWacomStylus)) -#define GSD_WACOM_STYLUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_WACOM_STYLUS, GsdWacomStylusClass)) -#define GSD_IS_WACOM_STYLUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_WACOM_STYLUS)) -#define GSD_IS_WACOM_STYLUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_WACOM_STYLUS)) -#define GSD_WACOM_STYLUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_WACOM_STYLUS, GsdWacomStylusClass)) - -typedef struct GsdWacomStylusPrivate GsdWacomStylusPrivate; - -typedef struct -{ - GObject parent; - GsdWacomStylusPrivate *priv; -} GsdWacomStylus; - -typedef struct -{ - GObjectClass parent_class; -} GsdWacomStylusClass; - -typedef enum { - WACOM_STYLUS_TYPE_UNKNOWN, - WACOM_STYLUS_TYPE_GENERAL, - WACOM_STYLUS_TYPE_INKING, - WACOM_STYLUS_TYPE_AIRBRUSH, - WACOM_STYLUS_TYPE_CLASSIC, - WACOM_STYLUS_TYPE_MARKER, - WACOM_STYLUS_TYPE_STROKE, - WACOM_STYLUS_TYPE_PUCK -} GsdWacomStylusType; - -GType gsd_wacom_stylus_get_type (void); -GSettings * gsd_wacom_stylus_get_settings (GsdWacomStylus *stylus); -const char * gsd_wacom_stylus_get_name (GsdWacomStylus *stylus); -const char * gsd_wacom_stylus_get_icon_name (GsdWacomStylus *stylus); -GsdWacomDevice * gsd_wacom_stylus_get_device (GsdWacomStylus *stylus); -gboolean gsd_wacom_stylus_get_has_eraser (GsdWacomStylus *stylus); -guint gsd_wacom_stylus_get_num_buttons(GsdWacomStylus *stylus); -int gsd_wacom_stylus_get_id (GsdWacomStylus *stylus); -GsdWacomStylusType gsd_wacom_stylus_get_stylus_type (GsdWacomStylus *stylus); - -/* Tablet Buttons */ -typedef enum { - WACOM_TABLET_BUTTON_TYPE_NORMAL, - WACOM_TABLET_BUTTON_TYPE_STRIP, - WACOM_TABLET_BUTTON_TYPE_RING, - WACOM_TABLET_BUTTON_TYPE_HARDCODED -} GsdWacomTabletButtonType; - -/* - * Positions of the buttons on the tablet in default right-handed mode - * (ie with no rotation applied). - */ -typedef enum { - WACOM_TABLET_BUTTON_POS_UNDEF = 0, - WACOM_TABLET_BUTTON_POS_LEFT, - WACOM_TABLET_BUTTON_POS_RIGHT, - WACOM_TABLET_BUTTON_POS_TOP, - WACOM_TABLET_BUTTON_POS_BOTTOM -} GsdWacomTabletButtonPos; - -#define MAX_GROUP_ID 4 - -#define GSD_WACOM_NO_LED -1 - -typedef struct -{ - char *name; - char *id; - GSettings *settings; - GsdWacomTabletButtonType type; - GsdWacomTabletButtonPos pos; - int group_id, idx; - int status_led; - int has_oled; -} GsdWacomTabletButton; - -void gsd_wacom_tablet_button_free (GsdWacomTabletButton *button); -GsdWacomTabletButton *gsd_wacom_tablet_button_copy (GsdWacomTabletButton *button); - -/* Device types to apply a setting to */ -typedef enum { - WACOM_TYPE_INVALID = 0, - WACOM_TYPE_STYLUS = (1 << 1), - WACOM_TYPE_ERASER = (1 << 2), - WACOM_TYPE_CURSOR = (1 << 3), - WACOM_TYPE_PAD = (1 << 4), - WACOM_TYPE_TOUCH = (1 << 5), - WACOM_TYPE_ALL = WACOM_TYPE_STYLUS | WACOM_TYPE_ERASER | WACOM_TYPE_CURSOR | WACOM_TYPE_PAD | WACOM_TYPE_TOUCH -} GsdWacomDeviceType; - -/* We use -1 for entire screen when setting/getting monitor value */ -#define GSD_WACOM_SET_ALL_MONITORS -1 - -GType gsd_wacom_device_get_type (void); - -void gsd_wacom_device_set_display (GsdWacomDevice *device, - int monitor); -gint gsd_wacom_device_get_display_monitor (GsdWacomDevice *device); -GsdWacomRotation gsd_wacom_device_get_display_rotation (GsdWacomDevice *device); - -GsdWacomDevice * gsd_wacom_device_new (GdkDevice *device); -GList * gsd_wacom_device_list_styli (GsdWacomDevice *device); -const char * gsd_wacom_device_get_name (GsdWacomDevice *device); -const char * gsd_wacom_device_get_layout_path (GsdWacomDevice *device); -const char * gsd_wacom_device_get_path (GsdWacomDevice *device); -const char * gsd_wacom_device_get_icon_name (GsdWacomDevice *device); -const char * gsd_wacom_device_get_tool_name (GsdWacomDevice *device); -gboolean gsd_wacom_device_reversible (GsdWacomDevice *device); -gboolean gsd_wacom_device_is_screen_tablet (GsdWacomDevice *device); -gboolean gsd_wacom_device_is_isd (GsdWacomDevice *device); -gboolean gsd_wacom_device_is_fallback (GsdWacomDevice *device); -gint gsd_wacom_device_get_num_strips (GsdWacomDevice *device); -gint gsd_wacom_device_get_num_rings (GsdWacomDevice *device); -GSettings * gsd_wacom_device_get_settings (GsdWacomDevice *device); -void gsd_wacom_device_set_current_stylus (GsdWacomDevice *device, - int stylus_id); -GsdWacomStylus * gsd_wacom_device_get_stylus_for_type (GsdWacomDevice *device, - GsdWacomStylusType type); - -GsdWacomDeviceType gsd_wacom_device_get_device_type (GsdWacomDevice *device); -gint * gsd_wacom_device_get_area (GsdWacomDevice *device); -gint * gsd_wacom_device_get_default_area (GsdWacomDevice *device); -const char * gsd_wacom_device_type_to_string (GsdWacomDeviceType type); -GList * gsd_wacom_device_get_buttons (GsdWacomDevice *device); -GsdWacomTabletButton *gsd_wacom_device_get_button (GsdWacomDevice *device, - int button, - GtkDirectionType *dir); -int gsd_wacom_device_get_num_modes (GsdWacomDevice *device, - int group_id); -int gsd_wacom_device_get_current_mode (GsdWacomDevice *device, - int group_id); -int gsd_wacom_device_set_next_mode (GsdWacomDevice *device, - GsdWacomTabletButton *button); -GdkDevice * gsd_wacom_device_get_gdk_device (GsdWacomDevice *device); - -GsdWacomRotation gsd_wacom_device_rotation_name_to_type (const char *rotation); -const char * gsd_wacom_device_rotation_type_to_name (GsdWacomRotation type); - - -/* Helper and debug functions */ -GsdWacomDevice * gsd_wacom_device_create_fake (GsdWacomDeviceType type, - const char *name, - const char *tool_name); - -GList * gsd_wacom_device_create_fake_cintiq (void); -GList * gsd_wacom_device_create_fake_bt (void); -GList * gsd_wacom_device_create_fake_x201 (void); -GList * gsd_wacom_device_create_fake_intuos4 (void); -GList * gsd_wacom_device_create_fake_h610pro (void); - -G_END_DECLS - -#endif /* __GSD_WACOM_DEVICE_MANAGER_H */ diff --git a/plugins/wacom/gsd-wacom-key-shortcut-button.c b/plugins/wacom/gsd-wacom-key-shortcut-button.c deleted file mode 100644 index 925c8c18..00000000 --- a/plugins/wacom/gsd-wacom-key-shortcut-button.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * gsd-wacom-key-shortcut-button.c - * - * Copyright © 2013 Red Hat, Inc. - * - * Author: Joaquim Rocha <jrocha@redhat.com> - * - * 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/>. - */ - -#include "config.h" -#include <glib/gi18n-lib.h> - -#include "gsd-wacom-key-shortcut-button.h" - -/** - * SECTION:gsd-wacom-key-shortcut-button - * @short_description: A button which captures and displays a keyboard shortcut - * @title: GsdWacomKeyShortcutButton - * - * GsdWacomKeyShortcutButton is a button which, when clicked, captures a keyboard - * shortcut and displays it. - * It works in a similar way to #GtkCellRendererAccel but, being a #GtkWidget, - * can be added to e.g. containers. - */ - -#define DEFAULT_CANCEL_KEY GDK_KEY_Escape -#define DEFAULT_CLEAR_KEY GDK_KEY_BackSpace - -#define GSD_WACOM_KEY_SHORTCUT_BUTTON_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, GsdWacomKeyShortcutButtonPrivate)) - -G_DEFINE_TYPE (GsdWacomKeyShortcutButton, gsd_wacom_key_shortcut_button, GTK_TYPE_BUTTON); - -enum { - KEY_SHORTCUT_EDITED, - KEY_SHORTCUT_CLEARED, - LAST_SIGNAL -}; - -enum { - PROP_0, - PROP_SHORTCUT_KEY_VAL, - PROP_SHORTCUT_KEY_MODS, - PROP_SHORTCUT_MODE, - PROP_SHORTCUT_CANCEL_KEY, - PROP_SHORTCUT_CLEAR_KEY, - N_PROPERTIES -}; - -struct _GsdWacomKeyShortcutButtonPrivate -{ - gboolean editing_mode; - - GdkDevice *grab_keyboard; - GdkDevice *grab_pointer; - - guint keyval; - guint keycode; - GdkModifierType mods; - - /* Temporary shortcut info used for allowing - * modifier-only shortcuts */ - guint tmp_shortcut_keyval; - GdkModifierType tmp_shortcut_mods; - guint32 tmp_shortcut_time; - - GsdWacomKeyShortcutButtonMode mode; - - guint cancel_keyval; - guint clear_keyval; -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, }; - -static void gsd_wacom_key_shortcut_button_changed (GsdWacomKeyShortcutButton *self); - -static void -gsd_wacom_key_shortcut_button_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GsdWacomKeyShortcutButton *self = GSD_WACOM_KEY_SHORTCUT_BUTTON (object); - gboolean changed = FALSE; - - switch (property_id) - { - case PROP_SHORTCUT_KEY_VAL: - self->priv->keyval = g_value_get_uint (value); - changed = TRUE; - break; - - case PROP_SHORTCUT_KEY_MODS: - self->priv->mods = g_value_get_uint (value); - changed = TRUE; - break; - - case PROP_SHORTCUT_MODE: - self->priv->mode = g_value_get_enum (value); - break; - - case PROP_SHORTCUT_CANCEL_KEY: - self->priv->cancel_keyval = g_value_get_uint (value); - break; - - case PROP_SHORTCUT_CLEAR_KEY: - self->priv->clear_keyval = g_value_get_uint (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } - - if (changed) - gsd_wacom_key_shortcut_button_changed (self); -} - -static void -gsd_wacom_key_shortcut_button_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GsdWacomKeyShortcutButton *self = GSD_WACOM_KEY_SHORTCUT_BUTTON (object); - - switch (property_id) - { - case PROP_SHORTCUT_KEY_VAL: - g_value_set_uint (value, self->priv->keyval); - break; - - case PROP_SHORTCUT_KEY_MODS: - g_value_set_uint (value, self->priv->mods); - break; - - case PROP_SHORTCUT_MODE: - g_value_set_enum (value, self->priv->mode); - break; - - case PROP_SHORTCUT_CANCEL_KEY: - g_value_set_uint (value, self->priv->cancel_keyval); - break; - - case PROP_SHORTCUT_CLEAR_KEY: - g_value_set_uint (value, self->priv->clear_keyval); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gsd_wacom_key_shortcut_set_editing_mode (GsdWacomKeyShortcutButton *self, - GdkEvent *event) -{ - GsdWacomKeyShortcutButtonPrivate *priv; - GdkDevice *kbd = NULL, *pointer = NULL; - GdkDeviceManager *device_manager; - GdkDisplay *display; - GList *devices, *l; - GdkWindow *window; - guint32 time; - - priv = GSD_WACOM_KEY_SHORTCUT_BUTTON (self)->priv; - - priv->editing_mode = TRUE; - gsd_wacom_key_shortcut_button_changed (self); - - window = gtk_widget_get_window (GTK_WIDGET (self)); - - g_return_if_fail (window != NULL); - - display = gtk_widget_get_display (GTK_WIDGET (self)); - device_manager = gdk_display_get_device_manager (display); - devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER); - - for (l = devices; l != NULL; l = l->next) - { - GdkDevice *current_device; - - current_device = l->data; - if (!kbd && gdk_device_get_source (current_device) == GDK_SOURCE_KEYBOARD) - kbd = current_device; - else if (!pointer && gdk_device_get_source (current_device) == GDK_SOURCE_MOUSE) - pointer = current_device; - - if (kbd && pointer) - break; - } - g_list_free (devices); - - time = gdk_event_get_time (event); - - if (gdk_device_grab (kbd, window, - GDK_OWNERSHIP_WINDOW, FALSE, - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, - NULL, time) != GDK_GRAB_SUCCESS) - return; - - if (gdk_device_grab (pointer, window, - GDK_OWNERSHIP_WINDOW, FALSE, - GDK_BUTTON_PRESS_MASK, - NULL, time) != GDK_GRAB_SUCCESS) - { - gdk_device_ungrab (kbd, time); - return; - } - - gtk_widget_grab_focus (GTK_WIDGET (self)); - - priv->grab_keyboard = kbd; - priv->grab_pointer = pointer; -} - -static void -gsd_wacom_key_shortcut_remove_editing_mode (GsdWacomKeyShortcutButton *self) -{ - GsdWacomKeyShortcutButtonPrivate *priv; - - priv = GSD_WACOM_KEY_SHORTCUT_BUTTON (self)->priv; - - priv->editing_mode = FALSE; - - if (priv->grab_keyboard != NULL) - { - gdk_device_ungrab (priv->grab_keyboard, GDK_CURRENT_TIME); - priv->grab_keyboard = NULL; - } - if (priv->grab_pointer != NULL) - { - gdk_device_ungrab (priv->grab_pointer, GDK_CURRENT_TIME); - priv->grab_pointer = NULL; - } - - priv->tmp_shortcut_keyval = 0; - priv->tmp_shortcut_mods = 0; - priv->tmp_shortcut_time = 0; -} - -static void -gsd_wacom_key_shortcut_button_changed (GsdWacomKeyShortcutButton *self) -{ - gchar *text; - - if (self->priv->editing_mode) - { - gtk_button_set_label (GTK_BUTTON (self), _("New shortcut…")); - - gtk_widget_set_state_flags (GTK_WIDGET (self), - GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT, - FALSE); - - return; - } - - if (self->priv->keyval == 0 && self->priv->mods == 0) - { - gtk_button_set_label (GTK_BUTTON (self), ""); - return; - } - - text = gtk_accelerator_get_label (self->priv->keyval, self->priv->mods); - gtk_button_set_label (GTK_BUTTON (self), text); - g_free (text); -} - -static void -gsd_wacom_key_shortcut_button_activate (GtkButton *self) -{ - gsd_wacom_key_shortcut_set_editing_mode (GSD_WACOM_KEY_SHORTCUT_BUTTON (self), NULL); - - GTK_BUTTON_CLASS (gsd_wacom_key_shortcut_button_parent_class)->activate (self); -} - -static void -gsd_wacom_key_shortcut_button_init (GsdWacomKeyShortcutButton *self) -{ - self->priv = GSD_WACOM_KEY_SHORTCUT_BUTTON_GET_PRIVATE (self); - - gtk_button_set_relief (GTK_BUTTON (self), GTK_RELIEF_NONE); - - self->priv->cancel_keyval = DEFAULT_CANCEL_KEY; - self->priv->clear_keyval = DEFAULT_CLEAR_KEY; -} - -static void -key_shortcut_finished_editing (GsdWacomKeyShortcutButton *self, - guint32 time) -{ - GsdWacomKeyShortcutButtonPrivate *priv = self->priv; - - gdk_device_ungrab (priv->grab_keyboard, time); - gdk_device_ungrab (priv->grab_pointer, time); - - priv->grab_keyboard = NULL; - priv->grab_pointer = NULL; - - priv->editing_mode = FALSE; - - gsd_wacom_key_shortcut_remove_editing_mode (self); - - gsd_wacom_key_shortcut_button_changed (self); -} - -static gboolean -gsd_wacom_key_shortcut_button_key_release (GtkWidget *widget, - GdkEventKey *event) -{ - GsdWacomKeyShortcutButton *self = GSD_WACOM_KEY_SHORTCUT_BUTTON (widget); - GsdWacomKeyShortcutButtonPrivate *priv = self->priv; - - if (priv->tmp_shortcut_keyval == 0) - { - GTK_WIDGET_CLASS (gsd_wacom_key_shortcut_button_parent_class)->key_release_event (widget, event); - - return FALSE; - } - - priv->keyval = priv->tmp_shortcut_keyval; - priv->mods = priv->tmp_shortcut_mods; - - key_shortcut_finished_editing (self, priv->tmp_shortcut_time); - - g_signal_emit (self, signals[KEY_SHORTCUT_EDITED], 0); - - return TRUE; -} - -static gboolean -gsd_wacom_key_shortcut_button_key_press (GtkWidget *widget, - GdkEventKey *event) -{ - /* This code is based on the gtk_cell_renderer_accel_start_editing */ - GsdWacomKeyShortcutButton *self; - GsdWacomKeyShortcutButtonPrivate *priv; - GdkModifierType mods = 0; - guint shortcut_keyval; - guint keyval; - gboolean edited; - gboolean cleared; - - self = GSD_WACOM_KEY_SHORTCUT_BUTTON (widget); - priv = self->priv; - - /* GTK and OTHER modes don't allow modifier keyvals */ - if (event->is_modifier && priv->mode != GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL) - return TRUE; - - if (!priv->editing_mode) - { - GTK_WIDGET_CLASS (gsd_wacom_key_shortcut_button_parent_class)->key_press_event (widget, event); - - return FALSE; - } - - edited = FALSE; - cleared = FALSE; - - mods = event->state; - - keyval = event->keyval; - if (keyval == GDK_KEY_Sys_Req && - (mods & GDK_MOD1_MASK) != 0) - { - /* HACK: we don't want to use SysRq as a keybinding (but we do - * want Alt+Print), so we avoid translation from Alt+Print to SysRq - */ - keyval = GDK_KEY_Print; - } - - shortcut_keyval = gdk_keyval_to_lower (keyval); - - if (shortcut_keyval == GDK_KEY_ISO_Left_Tab) - shortcut_keyval = GDK_KEY_Tab; - - mods &= gtk_accelerator_get_default_mod_mask (); - - /* Put shift back if it changed the case of the key, not otherwise. - */ - if (shortcut_keyval != keyval) - mods |= GDK_SHIFT_MASK; - - if (mods == 0) - { - if (keyval == priv->cancel_keyval) - { - /* cancel the edition */ - goto out; - } - else if (keyval == priv->clear_keyval) - { - /* clear the current shortcut */ - cleared = TRUE; - goto out; - } - } - - priv->tmp_shortcut_keyval = 0; - priv->tmp_shortcut_mods = 0; - priv->tmp_shortcut_time = 0; - - if (event->is_modifier) - { - /* when the user presses a non-modifier key, it readily assigns the - * shortcut but since we also support modifiers-only shortcuts, we - * cannot assign the shortcut right when the user presses a modifier - * key because the user might assign e.g. Alt, Alt+Ctrl, Alt+Ctrl+Shift, etc. - * So, we keep track of the pressed shortcut's (keyval, mods and time) if - * it is a modifier shortcut and assign them when a key-release happens */ - priv->tmp_shortcut_keyval = shortcut_keyval; - priv->tmp_shortcut_mods = mods; - priv->tmp_shortcut_time = event->time; - - return TRUE; - } - - edited = TRUE; - - out: - - if (edited) - { - priv->keyval = shortcut_keyval; - priv->mods = mods; - } - - if (cleared) - { - priv->keyval = 0; - priv->mods = 0; - } - - key_shortcut_finished_editing (GSD_WACOM_KEY_SHORTCUT_BUTTON (widget), event->time); - - if (edited) - g_signal_emit (self, signals[KEY_SHORTCUT_EDITED], 0); - else if (cleared) - g_signal_emit (self, signals[KEY_SHORTCUT_CLEARED], 0); - - return TRUE; -} - -static gboolean -gsd_wacom_key_shortcut_button_button_press (GtkWidget *widget, - GdkEventButton *event) -{ - GsdWacomKeyShortcutButton *self; - - self = GSD_WACOM_KEY_SHORTCUT_BUTTON (widget); - - if (self->priv->editing_mode) - return TRUE; - - gsd_wacom_key_shortcut_set_editing_mode (self, NULL); - - GTK_WIDGET_CLASS (gsd_wacom_key_shortcut_button_parent_class)->button_press_event (widget, - event); - - return TRUE; -} - -static void -gsd_wacom_key_shortcut_button_unrealize (GtkWidget *widget) -{ - GsdWacomKeyShortcutButton *self; - - self = GSD_WACOM_KEY_SHORTCUT_BUTTON (widget); - - gsd_wacom_key_shortcut_remove_editing_mode (self); - - GTK_WIDGET_CLASS (gsd_wacom_key_shortcut_button_parent_class)->unrealize (widget); -} - -static void -gsd_wacom_key_shortcut_button_class_init (GsdWacomKeyShortcutButtonClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass); - - gobject_class->set_property = gsd_wacom_key_shortcut_button_set_property; - gobject_class->get_property = gsd_wacom_key_shortcut_button_get_property; - - obj_properties[PROP_SHORTCUT_KEY_VAL] = - g_param_spec_uint ("key-value", - "The key value", - "The key value of the shortcut currently set", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_SHORTCUT_KEY_MODS] = - g_param_spec_uint ("key-mods", - "The key modifiers", - "The key modifiers of the shortcut currently set", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_SHORTCUT_CANCEL_KEY] = - g_param_spec_uint ("cancel-key", - "The cancel key", - "The key which cancels the edition of the shortcut", - 0, - G_MAXUINT, - DEFAULT_CANCEL_KEY, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - obj_properties[PROP_SHORTCUT_CLEAR_KEY] = - g_param_spec_uint ("clear-key", - "The clear key", - "The key which clears the currently set shortcut", - 0, - G_MAXUINT, - DEFAULT_CLEAR_KEY, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - /** - * GsdWacomKeyShortcutButton:mode: - * - * Determines which type of keys are allowed in the captured shortcuts. - * %GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL is the same as - * %GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER but allows shortcuts composed of - * only modifier keys. - */ - obj_properties[PROP_SHORTCUT_MODE] = - g_param_spec_enum ("mode", - "The shortcut mode", - "The mode with which the shortcuts are captured", - GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON_MODE, - GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (gobject_class, - N_PROPERTIES, - obj_properties); - - widget_class->key_press_event = gsd_wacom_key_shortcut_button_key_press; - widget_class->button_press_event = gsd_wacom_key_shortcut_button_button_press; - widget_class->key_release_event = gsd_wacom_key_shortcut_button_key_release; - widget_class->unrealize = gsd_wacom_key_shortcut_button_unrealize; - - button_class->activate = gsd_wacom_key_shortcut_button_activate; - - /** - * GsdWacomKeyShortcutButton::key-shortcut-edited: - * @keyshortcutbutton: the #GsdWacomKeyShortcutButton - * - * Emitted when the key shortcut of the @keyshortcutbutton is edited. - * - * The new shortcut can be retrieved by using the #GsdWacomKeyShortcutButton:key-value - * and #GsdWacomKeyShortcutButton:key-mods properties. - */ - signals[KEY_SHORTCUT_EDITED] = g_signal_new ("key-shortcut-edited", - GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsdWacomKeyShortcutButtonClass, - key_shortcut_edited), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * GsdWacomKeyShortcutButton::key-shortcut-cleared: - * @keyshortcutbutton: the #GsdWacomKeyShortcutButton - * - * Emitted when the key shortcut of the @keyshortcutbutton is cleared. - */ - signals[KEY_SHORTCUT_CLEARED] = g_signal_new ("key-shortcut-cleared", - GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsdWacomKeyShortcutButtonClass, - key_shortcut_cleared), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_type_class_add_private (klass, sizeof (GsdWacomKeyShortcutButtonPrivate)); -} - -/** - * gsd_wacom_key_shortcut_button_new: - * - * Creates a new #GsdWacomKeyShortcutButton. - * - * Returns: a new #GsdWacomKeyShortcutButton object. - * - * Since: 3.10 - */ -GtkWidget * -gsd_wacom_key_shortcut_button_new (void) -{ - return g_object_new (GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, NULL); -} - -GType -gsd_wacom_key_shortcut_button_mode_type (void) -{ - static GType enum_type_id = 0; - if (G_UNLIKELY (!enum_type_id)) - { - static const GEnumValue values[] = - { - { GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER, "OTHER", "other" }, - { GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL, "ALL", "all" }, - { 0, NULL, NULL } - }; - enum_type_id = g_enum_register_static ("GsdWacomKeyShortcutButtonMode", values); - } - return enum_type_id; -} diff --git a/plugins/wacom/gsd-wacom-key-shortcut-button.h b/plugins/wacom/gsd-wacom-key-shortcut-button.h deleted file mode 100644 index eebae0f9..00000000 --- a/plugins/wacom/gsd-wacom-key-shortcut-button.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * gsd-wacom-key-shortcut-button.h - * - * Copyright © 2013 Red Hat, Inc. - * - * Author: Joaquim Rocha <jrocha@redhat.com> - * - * 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/>. - */ - -#ifndef __GSD_WACOM_KEY_SHORTCUT_BUTTON_H__ -#define __GSD_WACOM_KEY_SHORTCUT_BUTTON_H__ - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON (gsd_wacom_key_shortcut_button_get_type ()) -#define GSD_WACOM_KEY_SHORTCUT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, GsdWacomKeyShortcutButton)) -#define GSD_WACOM_IS_KEY_SHORTCUT_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON)) -#define GSD_WACOM_KEY_SHORTCUT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, GsdWacomKeyShortcutButtonClass)) -#define GSD_WACOM_IS_KEY_SHORTCUT_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON)) -#define GSD_WACOM_KEY_SHORTCUT_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON, GsdWacomKeyShortcutButtonClass)) - -typedef struct _GsdWacomKeyShortcutButton GsdWacomKeyShortcutButton; -typedef struct _GsdWacomKeyShortcutButtonClass GsdWacomKeyShortcutButtonClass; -typedef struct _GsdWacomKeyShortcutButtonPrivate GsdWacomKeyShortcutButtonPrivate; - -GType gsd_wacom_key_shortcut_button_mode_type (void) G_GNUC_CONST; -#define GSD_WACOM_TYPE_KEY_SHORTCUT_BUTTON_MODE (gsd_wacom_key_shortcut_button_mode_type()) - -typedef enum -{ - GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_OTHER, - GSD_WACOM_KEY_SHORTCUT_BUTTON_MODE_ALL -} GsdWacomKeyShortcutButtonMode; - -struct _GsdWacomKeyShortcutButton -{ - GtkButton parent_instance; - - /*< private >*/ - GsdWacomKeyShortcutButtonPrivate *priv; -}; - -struct _GsdWacomKeyShortcutButtonClass -{ - GtkButtonClass parent_class; - - void (* key_shortcut_edited) (GsdWacomKeyShortcutButton *key_shortcut_button); - - void (* key_shortcut_cleared) (GsdWacomKeyShortcutButton *key_shortcut_button); -}; - -GType gsd_wacom_key_shortcut_button_get_type (void) G_GNUC_CONST; -GtkWidget * gsd_wacom_key_shortcut_button_new (void); - -#endif /* __GSD_WACOM_KEY_SHORTCUT_BUTTON_H__ */ diff --git a/plugins/wacom/gsd-wacom-manager.c b/plugins/wacom/gsd-wacom-manager.c index 0fb08784..34880bcb 100644 --- a/plugins/wacom/gsd-wacom-manager.c +++ b/plugins/wacom/gsd-wacom-manager.c @@ -33,51 +33,19 @@ #include <glib.h> #include <glib/gi18n-lib.h> #include <gtk/gtk.h> -#include <gdk/gdkx.h> #include <libnotify/notify.h> -#include <X11/Xatom.h> -#include <X11/extensions/XTest.h> -#include <X11/keysym.h> -#include <Xwacom.h> -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include <libgnome-desktop/gnome-rr.h> #include "gsd-enums.h" -#include "gsd-input-helper.h" -#include "gsd-keygrab.h" #include "gnome-settings-profile.h" #include "gnome-settings-bus.h" #include "gsd-wacom-manager.h" -#include "gsd-wacom-device.h" #include "gsd-wacom-oled.h" -#include "gsd-wacom-osd-window.h" #include "gsd-shell-helper.h" #include "gsd-device-mapper.h" #include "gsd-device-manager.h" -#include "gsd-device-manager-x11.h" #define GSD_WACOM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_MANAGER, GsdWacomManagerPrivate)) -#define KEY_ROTATION "rotation" -#define KEY_TOUCH "touch" -#define KEY_IS_ABSOLUTE "is-absolute" -#define KEY_AREA "area" -#define KEY_KEEP_ASPECT "keep-aspect" - -/* Stylus and Eraser settings */ -#define KEY_BUTTON_MAPPING "buttonmapping" -#define KEY_PRESSURETHRESHOLD "pressurethreshold" -#define KEY_PRESSURECURVE "pressurecurve" - -/* Button settings */ -#define KEY_ACTION_TYPE "action-type" -#define KEY_CUSTOM_ACTION "custom-action" -#define KEY_CUSTOM_ELEVATOR_ACTION "custom-elevator-action" -#define OLED_LABEL "oled-label" - -/* See "Wacom Pressure Threshold" */ -#define DEFAULT_PRESSURE_THRESHOLD 27 - #define UNKNOWN_DEVICE_NOTIFICATION_TIMEOUT 15000 #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" @@ -90,10 +58,14 @@ static const gchar introspection_xml[] = "<node name='/org/gnome/SettingsDaemon/Wacom'>" " <interface name='org.gnome.SettingsDaemon.Wacom'>" -" <method name='SetOSDVisibility'>" -" <arg name='device_id' direction='in' type='u'/>" -" <arg name='visible' direction='in' type='b'/>" -" <arg name='edition_mode' direction='in' type='b'/>" +" <method name='SetGroupModeLED'>" +" <arg name='device_path' direction='in' type='s'/>" +" <arg name='group' direction='in' type='u'/>" +" <arg name='mode' direction='in' type='u'/>" +" </method>" +" <method name='SetOLEDLabels'>" +" <arg name='device_path' direction='in' type='s'/>" +" <arg name='labels' direction='in' type='as'/>" " </method>" " </interface>" "</node>"; @@ -103,23 +75,11 @@ struct GsdWacomManagerPrivate guint start_idle_id; GsdDeviceManager *device_manager; guint device_added_id; - guint device_changed_id; guint device_removed_id; - GHashTable *devices; /* key = GdkDevice, value = GsdWacomDevice */ - GnomeRRScreen *rr_screen; - GHashTable *warned_devices; GsdShell *shell_proxy; GsdDeviceMapper *device_mapper; - guint mapping_changed_id; - - /* button capture */ - GdkScreen *screen; - int opcode; - - /* Help OSD window */ - GtkWidget *osd_window; /* DBus */ GDBusNodeInfo *introspection_data; @@ -133,13 +93,10 @@ static void gsd_wacom_manager_class_init (GsdWacomManagerClass *klass); static void gsd_wacom_manager_init (GsdWacomManager *wacom_manager); static void gsd_wacom_manager_finalize (GObject *object); -static gboolean osd_window_toggle_visibility (GsdWacomManager *manager, - GsdWacomDevice *device); - -static GsdWacomDevice * device_id_to_device (GsdWacomManager *manager, - int deviceid); - -static void osd_window_destroy (GsdWacomManager *manager); +static gboolean set_led (GsdDevice *device, + guint group, + guint index, + GError **error); G_DEFINE_TYPE (GsdWacomManager, gsd_wacom_manager, G_TYPE_OBJECT) @@ -157,69 +114,22 @@ gsd_wacom_manager_class_init (GsdWacomManagerClass *klass) g_type_class_add_private (klass, sizeof (GsdWacomManagerPrivate)); } -static int -get_device_id (GsdWacomDevice *device) -{ - GdkDevice *gdk_device; - int id; - - gdk_device = gsd_wacom_device_get_gdk_device (device); - - if (gdk_device == NULL) - return -1; - g_object_get (gdk_device, "device-id", &id, NULL); - return id; -} - -static XDevice * -open_device (GsdWacomDevice *device) -{ - XDevice *xdev; - int id; - - id = get_device_id (device); - if (id < 0) - return NULL; - - gdk_error_trap_push (); - xdev = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); - if (gdk_error_trap_pop () || (xdev == NULL)) - return NULL; - - return xdev; -} - -static gboolean -set_osd_visibility (GsdWacomManager *manager, - guint device_id, - gboolean visible, - gboolean edition_mode) +static GsdDevice * +lookup_device_by_path (GsdWacomManager *manager, + const gchar *path) { - GsdWacomDevice *device; - gboolean ret = TRUE; - - if (!visible) { - osd_window_destroy (manager); - return TRUE; - } + GList *devices, *l; - device = device_id_to_device (manager, device_id); - if (!device) - return FALSE; - - /* Check whether we need to destroy the old OSD window */ - if (manager->priv->osd_window && - device != gsd_wacom_osd_window_get_device (GSD_WACOM_OSD_WINDOW (manager->priv->osd_window))) - osd_window_destroy (manager); - - /* Do we need to create a new OSD or are we reusing one? */ - if (manager->priv->osd_window == NULL) - ret = osd_window_toggle_visibility (manager, device); + devices = gsd_device_manager_list_devices (manager->priv->device_manager, + GSD_DEVICE_TYPE_TABLET); - gsd_wacom_osd_window_set_edition_mode (GSD_WACOM_OSD_WINDOW (manager->priv->osd_window), - edition_mode); + for (l = devices; l; l = l->next) { + if (g_strcmp0 (gsd_device_get_device_file (l->data), + path) == 0) + return l->data; + } - return ret; + return NULL; } static void @@ -233,889 +143,88 @@ handle_method_call (GDBusConnection *connection, gpointer data) { GsdWacomManager *self = GSD_WACOM_MANAGER (data); + GError *error = NULL; + GsdDevice *device; - if (g_strcmp0 (method_name, "SetOSDVisibility") == 0) { - guint32 device_id; - gboolean visible, edition_mode; - - g_variant_get (parameters, "(ubb)", &device_id, &visible, &edition_mode); - if (!set_osd_visibility (self, device_id, visible, edition_mode)) { - g_dbus_method_invocation_return_error_literal (invocation, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to show the OSD for this device"); - } else { - g_dbus_method_invocation_return_value (invocation, NULL); - } - } -} - -static const GDBusInterfaceVTable interface_vtable = -{ - handle_method_call, - NULL, /* Get Property */ - NULL, /* Set Property */ -}; - -static void -wacom_set_property (GsdWacomDevice *device, - PropertyHelper *property) -{ - XDevice *xdev; - - xdev = open_device (device); - if (xdev == NULL) - return; - device_set_property (xdev, gsd_wacom_device_get_tool_name (device), property); - xdevice_close (xdev); -} - -static void -set_rotation (GsdWacomDevice *device, - GsdWacomRotation rotation) -{ - gchar rot = rotation; - PropertyHelper property = { - .name = "Wacom Rotation", - .nitems = 1, - .format = 8, - .type = XA_INTEGER, - .data.c = &rot - }; - - wacom_set_property (device, &property); -} - -static void -set_pressurecurve (GsdWacomDevice *device, - GVariant *value) -{ - PropertyHelper property = { - .name = "Wacom Pressurecurve", - .nitems = 4, - .type = XA_INTEGER, - .format = 32, - }; - gsize nvalues; - - property.data.i = g_variant_get_fixed_array (value, &nvalues, sizeof (gint32)); - - if (nvalues != 4) { - g_error ("Pressurecurve requires 4 values."); - return; - } - - wacom_set_property (device, &property); - g_variant_unref (value); -} - -/* Area handling. Each area is defined as top x/y, bottom x/y and limits the - * usable area of the physical device to the given area (in device coords) - */ -static void -set_area (GsdWacomDevice *device, - GVariant *value) -{ - PropertyHelper property = { - .name = "Wacom Tablet Area", - .nitems = 4, - .type = XA_INTEGER, - .format = 32, - }; - gsize nvalues; - - property.data.i = g_variant_get_fixed_array (value, &nvalues, sizeof (gint32)); - - if (nvalues != 4) { - g_error ("Area configuration requires 4 values."); - g_variant_unref (value); - return; - } - - if (property.data.i[0] == -1 && - property.data.i[1] == -1 && - property.data.i[2] == -1 && - property.data.i[3] == -1) { - gint *area; - area = gsd_wacom_device_get_default_area (device); + if (g_strcmp0 (method_name, "SetGroupModeLED") == 0) { + gchar *device_path; + guint group, mode; - if (!area) { - g_warning ("No default area could be obtained from the device"); - g_variant_unref (value); + g_variant_get (parameters, "(suu)", &device_path, &group, &mode); + device = lookup_device_by_path (self, device_path); + if (!device) { + g_dbus_method_invocation_return_value (invocation, NULL); return; } - property.data.i = area; - g_debug ("Resetting area to: %d, %d, %d, %d", - property.data.i[0], - property.data.i[1], - property.data.i[2], - property.data.i[3]); - wacom_set_property (device, &property); - g_free (area); - } else { - g_debug ("Setting area to: %d, %d, %d, %d", - property.data.i[0], - property.data.i[1], - property.data.i[2], - property.data.i[3]); - wacom_set_property (device, &property); - } - g_variant_unref (value); -} - -static void -reset_area (GsdWacomDevice *device) -{ - GVariant *values[4], *variant; - guint i; - - /* Set area to default values for the device */ - for (i = 0; i < G_N_ELEMENTS (values); i++) - values[i] = g_variant_new_int32 (-1); - variant = g_variant_new_array (G_VARIANT_TYPE_INT32, values, G_N_ELEMENTS (values)); - - set_area (device, variant); -} - -static void -set_absolute (GsdWacomDevice *device, - gint is_absolute) -{ - XDevice *xdev; - - xdev = open_device (device); - if (xdev == NULL) - return; - gdk_error_trap_push (); - XSetDeviceMode (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev, is_absolute ? Absolute : Relative); - if (gdk_error_trap_pop ()) - g_warning ("Failed to set mode \"%s\" for \"%s\".", - is_absolute ? "Absolute" : "Relative", gsd_wacom_device_get_tool_name (device)); - xdevice_close (xdev); -} + if (set_led (device, group, mode, &error)) + g_dbus_method_invocation_return_value (invocation, NULL); + else + g_dbus_method_invocation_return_gerror (invocation, error); + } else if (g_strcmp0 (method_name, "SetOLEDLabels") == 0) { + gchar *device_path, *label; + GVariantIter *iter; + gint i = 0; + + g_variant_get (parameters, "(sas)", &device_path, &iter); + device = lookup_device_by_path (self, device_path); + if (!device) { + g_dbus_method_invocation_return_value (invocation, NULL); + return; + } -static void -compute_aspect_area (gint monitor, - gint *area, - GsdWacomRotation rotation) -{ - gint width = area[2] - area[0]; - gint height = area[3] - area[1]; - GdkScreen *screen; - GdkRectangle monitor_geometry; - float aspect; - - screen = gdk_screen_get_default (); - if (monitor < 0) { - monitor_geometry.width = gdk_screen_get_width (screen); - monitor_geometry.height = gdk_screen_get_height (screen); - } else { - gdk_screen_get_monitor_geometry (screen, monitor, &monitor_geometry); - } + while (g_variant_iter_loop (iter, "s", &label)) { + if (!set_oled (device, i, label, &error)) { + g_free (label); + break; + } + i++; + } - if (rotation == GSD_WACOM_ROTATION_CW || rotation == GSD_WACOM_ROTATION_CCW) - aspect = (float) monitor_geometry.height / (float) monitor_geometry.width; - else - aspect = (float) monitor_geometry.width / (float) monitor_geometry.height; - - if ((float) width / (float) height > aspect) - width = height * aspect; - else - height = width / aspect; - - switch (rotation) - { - case GSD_WACOM_ROTATION_NONE: - area[2] = area[0] + width; - area[3] = area[1] + height; - break; - case GSD_WACOM_ROTATION_CW: - area[0] = area[2] - width; - area[3] = area[1] + height; - break; - case GSD_WACOM_ROTATION_HALF: - area[0] = area[2] - width; - area[1] = area[3] - height; - break; - case GSD_WACOM_ROTATION_CCW: - area[2] = area[0] + width; - area[1] = area[3] - height; - break; - default: - break; - } -} + g_variant_iter_free (iter); -static void -set_keep_aspect (GsdWacomDevice *device, - gboolean keep_aspect) -{ - GVariant *values[4], *variant; - guint i; - GdkDevice *gdk_device; - GsdDeviceMapper *mapper; - GsdDeviceManager *device_manager; - GsdDevice *gsd_device; - gint *area; - gint monitor = GSD_WACOM_SET_ALL_MONITORS; - GsdWacomRotation rotation; - GSettings *settings; - - settings = gsd_wacom_device_get_settings (device); - - /* Set area to default values for the device */ - for (i = 0; i < G_N_ELEMENTS (values); i++) - values[i] = g_variant_new_int32 (-1); - variant = g_variant_new_array (G_VARIANT_TYPE_INT32, values, G_N_ELEMENTS (values)); - - /* If keep_aspect is not set, just reset the area to default and let - * gsettings notification call reset_area() for us... - */ - if (!keep_aspect) { - g_settings_set_value (settings, KEY_AREA, variant); - return; + if (error) + g_dbus_method_invocation_return_gerror (invocation, error); + else + g_dbus_method_invocation_return_value (invocation, NULL); } - g_variant_unref (variant); - - /* Reset the device area to get the default area */ - reset_area (device); - - /* Get current rotation */ - rotation = g_settings_get_enum (settings, KEY_ROTATION); - - /* Get current area */ - area = gsd_wacom_device_get_area (device); - if (!area) { - g_warning("Device area not available.\n"); - return; - } - - /* Get corresponding monitor size */ - mapper = gsd_device_mapper_get (); - device_manager = gsd_device_manager_get (); - - gdk_device = gsd_wacom_device_get_gdk_device (device); - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (device_manager), - gdk_device); - monitor = gsd_device_mapper_get_device_monitor (mapper, gsd_device); - - /* Adjust area to match the monitor aspect ratio */ - g_debug ("Initial device area: (%d,%d) (%d,%d)", area[0], area[1], area[2], area[3]); - compute_aspect_area (monitor, area, rotation); - g_debug ("Adjusted device area: (%d,%d) (%d,%d)", area[0], area[1], area[2], area[3]); - - for (i = 0; i < G_N_ELEMENTS (values); i++) - values[i] = g_variant_new_int32 (area[i]); - variant = g_variant_new_array (G_VARIANT_TYPE_INT32, values, G_N_ELEMENTS (values)); - g_settings_set_value (settings, KEY_AREA, variant); - - g_free (area); -} - - -static void -set_device_buttonmap (GsdWacomDevice *device, - GVariant *value) -{ - XDevice *xdev; - gsize nmap; - const gint *intmap; - unsigned char *map; - int i, j, rc; - - xdev = open_device (device); - if (xdev == NULL) { - g_variant_unref (value); - return; - } - - intmap = g_variant_get_fixed_array (value, &nmap, sizeof (gint32)); - map = g_new0 (unsigned char, nmap); - for (i = 0; i < nmap; i++) - map[i] = intmap[i]; - g_variant_unref (value); - - gdk_error_trap_push (); - - /* X refuses to change the mapping while buttons are engaged, - * so if this is the case we'll retry a few times - */ - for (j = 0; - j < 20 && (rc = XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev, map, nmap)) == MappingBusy; - ++j) { - g_usleep (300); - } - - if ((gdk_error_trap_pop () && rc != MappingSuccess) || - rc != MappingSuccess) - g_warning ("Error in setting button mapping for \"%s\"", gsd_wacom_device_get_tool_name (device)); - - g_free (map); - - xdevice_close (xdev); -} - -static void -set_touch (GsdWacomDevice *device, - gboolean touch) -{ - gchar data = touch; - PropertyHelper property = { - .name = "Wacom Enable Touch", - .nitems = 1, - .format = 8, - .type = XA_INTEGER, - .data.c = &data, - }; - - wacom_set_property (device, &property); -} - -static void -set_pressurethreshold (GsdWacomDevice *device, - gint threshold) -{ - PropertyHelper property = { - .name = "Wacom Pressure Threshold", - .nitems = 1, - .format = 32, - .type = XA_INTEGER, - .data.i = &threshold, - }; - - wacom_set_property (device, &property); } -static void -apply_stylus_settings (GsdWacomDevice *device) +static const GDBusInterfaceVTable interface_vtable = { - GSettings *stylus_settings; - GsdWacomStylus *stylus; - int threshold; - - g_object_get (device, "last-stylus", &stylus, NULL); - if (stylus == NULL) { - g_warning ("Last stylus is not set"); - return; - } - - g_debug ("Applying setting for stylus '%s' on device '%s'", - gsd_wacom_stylus_get_name (stylus), - gsd_wacom_device_get_name (device)); - - stylus_settings = gsd_wacom_stylus_get_settings (stylus); - set_pressurecurve (device, g_settings_get_value (stylus_settings, KEY_PRESSURECURVE)); - set_device_buttonmap (device, g_settings_get_value (stylus_settings, KEY_BUTTON_MAPPING)); - - threshold = g_settings_get_int (stylus_settings, KEY_PRESSURETHRESHOLD); - if (threshold == -1) - threshold = DEFAULT_PRESSURE_THRESHOLD; - set_pressurethreshold (device, threshold); -} + handle_method_call, + NULL, /* Get Property */ + NULL, /* Set Property */ +}; -static void -set_led (GsdWacomDevice *device, - GsdWacomTabletButton *button, - int index) +static gboolean +set_led (GsdDevice *device, + guint group, + guint index, + GError **error) { - GError *error = NULL; const char *path; char *command; - gint status_led; gboolean ret; #ifndef HAVE_GUDEV /* Not implemented on non-Linux systems */ - return; + return TRUE; #endif - g_return_if_fail (index >= 1); - - path = gsd_wacom_device_get_path (device); - status_led = button->status_led; + path = gsd_device_get_device_file (device); - if (status_led == GSD_WACOM_NO_LED) { - g_debug ("Ignoring unhandled group ID %d for device %s", - button->group_id, gsd_wacom_device_get_name (device)); - return; - } - g_debug ("Switching group ID %d to index %d for device %s", button->group_id, index, path); + g_debug ("Switching group ID %d to index %d for device %s", group, index, path); command = g_strdup_printf ("pkexec " LIBEXECDIR "/gsd-wacom-led-helper --path %s --group %d --led %d", - path, status_led, index - 1); + path, group, index); ret = g_spawn_command_line_sync (command, NULL, NULL, NULL, - &error); - - if (ret == FALSE) { - g_debug ("Failed to launch '%s': %s", command, error->message); - g_error_free (error); - } - + error); g_free (command); -} - -struct DefaultButtons { - const char *button; - int num; -}; - -struct DefaultButtons def_touchrings_buttons[] = { - /* Touchrings */ - { "AbsWheelUp", 90 }, - { "AbsWheelDown", 91 }, - { "RelWheelUp", 90 }, - { "RelWheelDown", 91 }, - { "AbsWheel2Up", 92 }, - { "AbsWheel2Down", 93 }, - { NULL, 0 } -}; - -struct DefaultButtons def_touchstrip_buttons[] = { - /* Touchstrips */ - { "StripLeftUp", 94 }, - { "StripLeftDown", 95 }, - { "StripRightUp", 96 }, - { "StripRightDown", 97 }, - { NULL, 0 } -}; - -static void -reset_touch_buttons (XDevice *xdev, - struct DefaultButtons *buttons, - const char *device_property) -{ - Atom actions[6]; - Atom action_prop; - guint i; - - /* Create a device property with the action for button i */ - for (i = 0; buttons[i].button != NULL; i++) - { - char *propname; - glong action[2]; /* press + release */ - Atom prop; - int mapped_button = buttons[i].num; - - action[0] = AC_BUTTON | AC_KEYBTNPRESS | mapped_button; - action[1] = AC_BUTTON | mapped_button; - - propname = g_strdup_printf ("Button %s action", buttons[i].button); - prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), propname, False); - g_free (propname); - XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev, - prop, XA_INTEGER, 32, PropModeReplace, - (const guchar *) &action, 2); - - /* prop now contains press + release for the mapped button */ - actions[i] = prop; - } - - /* Now set the actual action property to contain references to the various - * actions */ - action_prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device_property, True); - XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev, - action_prop, XA_ATOM, 32, PropModeReplace, - (const guchar *) actions, i); -} - -/* This function does LED and OLED */ -static void -update_pad_leds (GsdWacomDevice *device) -{ - GList *buttons, *l; - - /* Reset all the LEDs and OLEDs*/ - buttons = gsd_wacom_device_get_buttons (device); - for (l = buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *button = l->data; - if (button->type == WACOM_TABLET_BUTTON_TYPE_HARDCODED && - button->status_led != GSD_WACOM_NO_LED) { - set_led (device, button, 1); - } - if (button->has_oled) { - char *label; - label = g_settings_get_string (button->settings, OLED_LABEL); - set_oled (device, button->id, label); - g_free (label); - } - } - g_list_free (buttons); -} - -static void -reset_pad_buttons (GsdWacomDevice *device) -{ - XDevice *xdev; - int nmap; - unsigned char *map; - int i, j, rc; - - /* Normal buttons */ - xdev = open_device (device); - if (xdev == NULL) - return; - - gdk_error_trap_push (); - - nmap = 256; - map = g_new0 (unsigned char, nmap); - for (i = 0; i < nmap && i < sizeof (map); i++) - map[i] = i + 1; - - /* X refuses to change the mapping while buttons are engaged, - * so if this is the case we'll retry a few times */ - for (j = 0; - j < 20 && (rc = XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev, map, nmap)) == MappingBusy; - ++j) { - g_usleep (300); - } - - if ((gdk_error_trap_pop () && rc != MappingSuccess) || - rc != MappingSuccess) - g_warning ("Error in resetting button mapping for \"%s\" (rc=%d)", gsd_wacom_device_get_tool_name (device), rc); - - g_free (map); - - gdk_error_trap_push (); - reset_touch_buttons (xdev, def_touchrings_buttons, "Wacom Wheel Buttons"); - reset_touch_buttons (xdev, def_touchstrip_buttons, "Wacom Strip Buttons"); - gdk_error_trap_pop_ignored (); - - xdevice_close (xdev); - - update_pad_leds (device); -} - -static void -gsettings_oled_changed (GSettings *settings, - gchar *key, - GsdWacomTabletButton *button) -{ - GsdWacomDevice *device; - char *label; - - label = g_settings_get_string (settings, OLED_LABEL); - device = g_object_get_data (G_OBJECT (button->settings), "parent-device"); - set_oled (device, button->id, label); - g_free (label); -} - -static void -set_wacom_settings (GsdWacomManager *manager, - GsdWacomDevice *device) -{ - GsdWacomDeviceType type; - GSettings *settings; - GList *buttons, *l; - - g_debug ("Applying settings for device '%s' (type: %s)", - gsd_wacom_device_get_tool_name (device), - gsd_wacom_device_type_to_string (gsd_wacom_device_get_device_type (device))); - - settings = gsd_wacom_device_get_settings (device); - set_touch (device, g_settings_get_boolean (settings, KEY_TOUCH)); - - type = gsd_wacom_device_get_device_type (device); - - if (type == WACOM_TYPE_TOUCH && - gsd_wacom_device_is_screen_tablet (device) == FALSE) { - set_absolute (device, FALSE); - return; - } - - if (type == WACOM_TYPE_CURSOR) { - set_absolute (device, FALSE); - reset_area (device); - return; - } - - if (type == WACOM_TYPE_PAD) { - int id; - - buttons = gsd_wacom_device_get_buttons (device); - for (l = buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *button = l->data; - if (button->has_oled) { - g_signal_connect (G_OBJECT (button->settings), "changed::" OLED_LABEL, - G_CALLBACK (gsettings_oled_changed), button); - g_object_set_data (G_OBJECT (button->settings), "parent-device", device); - } - } - g_list_free (buttons); - - id = get_device_id (device); - reset_pad_buttons (device); - grab_button (id, TRUE, manager->priv->screen); - - return; - } else { - set_rotation (device, g_settings_get_enum (settings, KEY_ROTATION)); - } - - set_absolute (device, g_settings_get_boolean (settings, KEY_IS_ABSOLUTE)); - - /* Ignore touch devices as they do not share the same range of values for area */ - if (type != WACOM_TYPE_TOUCH) { - if (gsd_wacom_device_is_screen_tablet (device) == FALSE) - set_keep_aspect (device, g_settings_get_boolean (settings, KEY_KEEP_ASPECT)); - set_area (device, g_settings_get_value (settings, KEY_AREA)); - } - - /* only pen and eraser have pressure threshold and curve settings */ - if (type == WACOM_TYPE_STYLUS || - type == WACOM_TYPE_ERASER) { - apply_stylus_settings (device); - } -} - -static void -wacom_settings_changed (GSettings *settings, - gchar *key, - GsdWacomDevice *device) -{ - GsdWacomDeviceType type; - - type = gsd_wacom_device_get_device_type (device); - - if (g_str_equal (key, KEY_ROTATION)) { - if (type == WACOM_TYPE_PAD) - update_pad_leds (device); - else - set_rotation (device, g_settings_get_enum (settings, key)); - } else if (g_str_equal (key, KEY_TOUCH)) { - if (type == WACOM_TYPE_TOUCH) - set_touch (device, g_settings_get_boolean (settings, key)); - } else if (g_str_equal (key, KEY_IS_ABSOLUTE)) { - if (type != WACOM_TYPE_CURSOR && - type != WACOM_TYPE_PAD && - type != WACOM_TYPE_TOUCH) - set_absolute (device, g_settings_get_boolean (settings, key)); - } else if (g_str_equal (key, KEY_AREA)) { - if (type != WACOM_TYPE_CURSOR && - type != WACOM_TYPE_PAD && - type != WACOM_TYPE_TOUCH) - set_area (device, g_settings_get_value (settings, key)); - } else if (g_str_equal (key, KEY_KEEP_ASPECT)) { - if (type != WACOM_TYPE_CURSOR && - type != WACOM_TYPE_PAD && - type != WACOM_TYPE_TOUCH && - !gsd_wacom_device_is_screen_tablet (device)) - set_keep_aspect (device, g_settings_get_boolean (settings, key)); - } else { - g_warning ("Unhandled tablet-wide setting '%s' changed", key); - } -} - -static void -stylus_settings_changed (GSettings *settings, - gchar *key, - GsdWacomStylus *stylus) -{ - GsdWacomDevice *device; - GsdWacomStylus *last_stylus; - - device = gsd_wacom_stylus_get_device (stylus); - - g_object_get (device, "last-stylus", &last_stylus, NULL); - if (last_stylus != stylus) { - g_debug ("Not applying changed settings because '%s' is the current stylus, not '%s'", - last_stylus ? gsd_wacom_stylus_get_name (last_stylus) : "NONE", - gsd_wacom_stylus_get_name (stylus)); - return; - } - - if (g_str_equal (key, KEY_PRESSURECURVE)) { - set_pressurecurve (device, g_settings_get_value (settings, key)); - } else if (g_str_equal (key, KEY_PRESSURETHRESHOLD)) { - int threshold; - - threshold = g_settings_get_int (settings, KEY_PRESSURETHRESHOLD); - if (threshold == -1) - threshold = DEFAULT_PRESSURE_THRESHOLD; - set_pressurethreshold (device, threshold); - } else if (g_str_equal (key, KEY_BUTTON_MAPPING)) { - set_device_buttonmap (device, g_settings_get_value (settings, key)); - } else { - g_warning ("Unhandled stylus setting '%s' changed", key); - } -} - -static void -last_stylus_changed (GsdWacomDevice *device, - GParamSpec *pspec, - GsdWacomManager *manager) -{ - g_debug ("Stylus for device '%s' changed, applying settings", - gsd_wacom_device_get_name (device)); - apply_stylus_settings (device); -} - -static void -osd_window_destroy (GsdWacomManager *manager) -{ - g_return_if_fail (manager != NULL); - - g_clear_pointer (&manager->priv->osd_window, gtk_widget_destroy); -} - -static gboolean -osd_window_on_focus_out_event (GtkWidget *widget, - GdkEvent *event, - GsdWacomManager *manager) -{ - GsdWacomOSDWindow *osd_window; - - osd_window = GSD_WACOM_OSD_WINDOW (widget); - - /* If the OSD window loses focus, hide it unless it is in edition mode */ - if (gsd_wacom_osd_window_get_edition_mode (osd_window)) - return FALSE; - - osd_window_destroy (manager); - - return FALSE; -} -static gboolean -osd_window_toggle_visibility (GsdWacomManager *manager, - GsdWacomDevice *device) -{ - GtkWidget *widget; - const gchar *layout_path; - - if (manager->priv->osd_window) { - osd_window_destroy (manager); - return FALSE; - } - - layout_path = gsd_wacom_device_get_layout_path (device); - if (layout_path == NULL) { - g_warning ("Cannot display the on-screen help window as the tablet " - "definition for %s is missing the layout\n" - "Please consider contributing the layout for your " - "tablet to libwacom at linuxwacom-devel@lists.sourceforge.net\n", - gsd_wacom_device_get_name (device)); - return FALSE; - } - - if (g_file_test (layout_path, G_FILE_TEST_EXISTS) == FALSE) { - g_warning ("Cannot display the on-screen help window as the " - "layout file %s cannot be found on disk\n" - "Please check your libwacom installation\n", - layout_path); - return FALSE; - } - - widget = gsd_wacom_osd_window_new (device, NULL); - - g_signal_connect (widget, "focus-out-event", - G_CALLBACK(osd_window_on_focus_out_event), manager); - g_object_add_weak_pointer (G_OBJECT (widget), (gpointer *) &manager->priv->osd_window); - - gtk_window_present (GTK_WINDOW(widget)); - manager->priv->osd_window = widget; - - return TRUE; -} - -static gboolean -osd_window_update_viewable (GsdWacomManager *manager, - GsdWacomTabletButton *button, - GtkDirectionType dir, - XIEvent *xiev) -{ - if (manager->priv->osd_window == NULL) - return FALSE; - - gsd_wacom_osd_window_set_active (GSD_WACOM_OSD_WINDOW (manager->priv->osd_window), - button, - dir, - xiev->evtype == XI_ButtonPress); - - return TRUE; -} - -static void -notify_unknown_device (GsdWacomManager *manager, const gchar *device_name) -{ - gchar *msg_body; - NotifyNotification *notification; - - msg_body = g_strdup_printf (_("The \"%s\" tablet may not work as expected."), device_name); - notification = notify_notification_new (_("Unknown Tablet Connected"), msg_body, - "input-tablet"); - notify_notification_set_timeout (notification, UNKNOWN_DEVICE_NOTIFICATION_TIMEOUT); - notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL); - notify_notification_set_app_name (notification, _("Wacom Settings")); - notify_notification_show (notification, NULL); - - g_signal_connect (notification, "closed", - G_CALLBACK (g_object_unref), NULL); - - g_free (msg_body); -} - -static void -gsd_wacom_manager_add_gdk_device (GsdWacomManager *manager, - GdkDevice *gdk_device) -{ - GsdWacomDevice *device; - GSettings *settings; - const gchar *device_name; - GsdWacomDeviceType type; - - device = gsd_wacom_device_new (gdk_device); - device_name = gsd_wacom_device_get_name (device); - type = gsd_wacom_device_get_device_type (device); - - if (gsd_wacom_device_is_fallback (device) && - type != WACOM_TYPE_TOUCH && device_name != NULL) { - GHashTable *warned_devices; - - warned_devices = manager->priv->warned_devices; - - if (!g_hash_table_contains (warned_devices, device_name)) { - g_warning ("No definition for '%s' found in the tablet database. Using a fallback one.", - device_name); - g_hash_table_insert (warned_devices, g_strdup (device_name), NULL); - notify_unknown_device (manager, device_name); - } - } - - if (type == WACOM_TYPE_INVALID) { - g_object_unref (device); - return; - } - g_debug ("Adding device '%s' (type: '%s') to known devices list", - gsd_wacom_device_get_tool_name (device), - gsd_wacom_device_type_to_string (type)); - g_hash_table_insert (manager->priv->devices, (gpointer) gdk_device, device); - - settings = gsd_wacom_device_get_settings (device); - g_signal_connect (G_OBJECT (settings), "changed", - G_CALLBACK (wacom_settings_changed), device); - - if (type == WACOM_TYPE_STYLUS || type == WACOM_TYPE_ERASER) { - GList *styli, *l; - - styli = gsd_wacom_device_list_styli (device); - - for (l = styli ; l ; l = l->next) { - settings = gsd_wacom_stylus_get_settings (l->data); - g_signal_connect (G_OBJECT (settings), "changed", - G_CALLBACK (stylus_settings_changed), l->data); - } - - g_list_free (styli); - - g_signal_connect (G_OBJECT (device), "notify::last-stylus", - G_CALLBACK (last_stylus_changed), manager); - } - - set_wacom_settings (manager, device); + return ret; } static void @@ -1123,92 +232,15 @@ device_added_cb (GsdDeviceManager *device_manager, GsdDevice *gsd_device, GsdWacomManager *manager) { - GdkDevice **devices; GsdDeviceType device_type; - guint i, n_gdk_devices; device_type = gsd_device_get_device_type (gsd_device); - if (device_type & GSD_DEVICE_TYPE_TABLET) { + if ((device_type & GSD_DEVICE_TYPE_TABLET) != 0 && + (device_type & GSD_DEVICE_TYPE_TOUCHPAD) == 0) { gsd_device_mapper_add_input (manager->priv->device_mapper, gsd_device); } - - if (gnome_settings_is_wayland ()) - return; - - devices = gsd_x11_device_manager_get_gdk_devices (GSD_X11_DEVICE_MANAGER (device_manager), - gsd_device, &n_gdk_devices); - - for (i = 0; i < n_gdk_devices; i++) - gsd_wacom_manager_add_gdk_device (manager, devices[i]); - - g_free (devices); -} - -static void -device_changed_cb (GsdDeviceManager *device_manager, - GsdDevice *gsd_device, - GsdWacomManager *manager) -{ - GdkDevice **devices; - guint i, n_gdk_devices; - - if (gnome_settings_is_wayland ()) - return; - - devices = gsd_x11_device_manager_get_gdk_devices (GSD_X11_DEVICE_MANAGER (device_manager), - gsd_device, &n_gdk_devices); - - for (i = 0; i < n_gdk_devices; i++) { - if (!g_hash_table_lookup (manager->priv->devices, devices[i])) - gsd_wacom_manager_add_gdk_device (manager, devices[i]); - } - - g_free (devices); -} - -static void -gsd_wacom_manager_remove_gdk_device (GsdWacomManager *manager, - GdkDevice *gdk_device) -{ - GsdWacomDevice *device; - GSettings *settings; - GsdWacomDeviceType type; - - g_debug ("Removing device '%s' from known devices list", - gdk_device_get_name (gdk_device)); - - device = g_hash_table_lookup (manager->priv->devices, gdk_device); - if (!device) - return; - - type = gsd_wacom_device_get_device_type (device); - settings = gsd_wacom_device_get_settings (device); - - g_signal_handlers_disconnect_by_data (G_OBJECT (settings), device); - - if (type == WACOM_TYPE_STYLUS || type == WACOM_TYPE_ERASER) { - GList *styli, *l; - - styli = gsd_wacom_device_list_styli (device); - - for (l = styli ; l ; l = l->next) { - settings = gsd_wacom_stylus_get_settings (l->data); - g_signal_handlers_disconnect_by_data (G_OBJECT (settings), l->data); - } - - g_list_free (styli); - } - - g_hash_table_remove (manager->priv->devices, gdk_device); - - /* Enable this chunk of code if you want to valgrind - * test-wacom. It will exit when there are no Wacom devices left */ -#if 0 - if (g_hash_table_size (manager->priv->devices) == 0) - gtk_main_quit (); -#endif } static void @@ -1216,385 +248,8 @@ device_removed_cb (GsdDeviceManager *device_manager, GsdDevice *gsd_device, GsdWacomManager *manager) { - GdkDevice **devices; - guint i, n_gdk_devices; - gsd_device_mapper_remove_input (manager->priv->device_mapper, gsd_device); - - if (gnome_settings_is_wayland ()) - return; - - devices = gsd_x11_device_manager_get_gdk_devices (GSD_X11_DEVICE_MANAGER (device_manager), - gsd_device, &n_gdk_devices); - - for (i = 0; i < n_gdk_devices; i++) - gsd_wacom_manager_remove_gdk_device (manager, devices[i]); - - g_free (devices); -} - -static GsdWacomDevice * -device_id_to_device (GsdWacomManager *manager, - int deviceid) -{ - GList *devices, *l; - GsdWacomDevice *ret; - - ret = NULL; - devices = g_hash_table_get_keys (manager->priv->devices); - - for (l = devices; l != NULL; l = l->next) { - GdkDevice *device = l->data; - int id; - - g_object_get (device, "device-id", &id, NULL); - if (id == deviceid) { - ret = g_hash_table_lookup (manager->priv->devices, device); - break; - } - } - - g_list_free (devices); - return ret; -} - -struct { - guint mask; - KeySym keysym; -} mods_keysyms[] = { - { GDK_MOD1_MASK, XK_Alt_L }, - { GDK_SHIFT_MASK, XK_Shift_L }, - { GDK_CONTROL_MASK, XK_Control_L }, -}; - -static void -send_modifiers (Display *display, - guint mask, - gboolean is_press) -{ - guint i; - - if (mask == 0) - return; - - for (i = 0; i < G_N_ELEMENTS(mods_keysyms); i++) { - if (mask & mods_keysyms[i].mask) { - guint keycode; - - keycode = XKeysymToKeycode (display, mods_keysyms[i].keysym); - XTestFakeKeyEvent (display, keycode, - is_press ? True : False, 0); - } - } -} - -static char * -get_elevator_shortcut_string (GSettings *settings, - GtkDirectionType dir) -{ - char **strv, *str; - - strv = g_settings_get_strv (settings, KEY_CUSTOM_ELEVATOR_ACTION); - if (strv == NULL) - return NULL; - - if (g_strv_length (strv) >= 1 && dir == GTK_DIR_UP) - str = g_strdup (strv[0]); - else if (g_strv_length (strv) >= 2 && dir == GTK_DIR_DOWN) - str = g_strdup (strv[1]); - else - str = NULL; - - g_strfreev (strv); - - return str; -} - -static void -generate_key (GsdWacomTabletButton *wbutton, - int group, - Display *display, - GtkDirectionType dir, - gboolean is_press) -{ - char *str; - guint keyval; - guint *keycodes; - guint keycode; - guint mods; - GdkKeymapKey *keys; - int n_keys; - guint i; - - if (wbutton->type == WACOM_TABLET_BUTTON_TYPE_STRIP || - wbutton->type == WACOM_TABLET_BUTTON_TYPE_RING) - str = get_elevator_shortcut_string (wbutton->settings, dir); - else - str = g_settings_get_string (wbutton->settings, KEY_CUSTOM_ACTION); - - if (str == NULL) - return; - - gtk_accelerator_parse_with_keycode (str, &keyval, &keycodes, &mods); - if (keycodes == NULL) { - g_warning ("Failed to find a keycode for shortcut '%s'", str); - g_free (str); - return; - } - g_free (keycodes); - - /* Now look for our own keycode, in the group as us */ - if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (), keyval, &keys, &n_keys)) { - g_warning ("Failed to find a keycode for keyval '%s' (0x%x)", gdk_keyval_name (keyval), keyval); - g_free (str); - return; - } - - keycode = 0; - for (i = 0; i < n_keys; i++) { - if (keys[i].group != group) - continue; - if (keys[i].level > 0) - continue; - keycode = keys[i].keycode; - } - /* Couldn't find it in the current group? Look in group 0 */ - if (keycode == 0) { - for (i = 0; i < n_keys; i++) { - if (keys[i].group > 0) - continue; - keycode = keys[i].keycode; - } - } - g_free (keys); - - if (keycode == 0) { - g_warning ("Not emitting '%s' (keyval: %d, keycode: %d mods: 0x%x), invalid keycode", - str, keyval, keycode, mods); - g_free (str); - return; - } else { - g_debug ("Emitting '%s' (keyval: %d, keycode: %d mods: 0x%x)", - str, keyval, keycode, mods); - } - - /* And send out the keys! */ - gdk_error_trap_push (); - if (is_press) - send_modifiers (display, mods, TRUE); - XTestFakeKeyEvent (display, keycode, - is_press ? True : False, 0); - if (is_press == FALSE) - send_modifiers (display, mods, FALSE); - if (gdk_error_trap_pop ()) - g_warning ("Failed to generate fake key event '%s'", str); - - g_free (str); -} - -static void -switch_monitor (GsdWacomManager *manager, - GsdWacomDevice *device) -{ - gint current_monitor, n_monitors; - GdkDevice *gdk_device; - GsdDevice *gsd_device; - - /* We dont; do that for screen tablets, sorry... */ - if (gsd_wacom_device_is_screen_tablet (device)) - return; - - n_monitors = gdk_screen_get_n_monitors (gdk_screen_get_default ()); - - /* There's no point in switching if there just one monitor */ - if (n_monitors < 2) - return; - - gdk_device = gsd_wacom_device_get_gdk_device (device); - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get ()), - gdk_device); - current_monitor = - gsd_device_mapper_get_device_monitor (manager->priv->device_mapper, - gsd_device); - - /* Select next monitor */ - current_monitor++; - - if (current_monitor >= n_monitors) - current_monitor = 0; - - gsd_device_mapper_set_device_monitor (manager->priv->device_mapper, - gsd_device, current_monitor); -} - -static void -notify_osd_for_device (GsdWacomManager *manager, - GsdWacomDevice *device) -{ - GdkDevice *gdk_device; - GsdDevice *gsd_device; - GdkScreen *screen; - gint monitor_num; - - gdk_device = gsd_wacom_device_get_gdk_device (device); - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get ()), - gdk_device); - monitor_num = gsd_device_mapper_get_device_monitor (manager->priv->device_mapper, - gsd_device); - - if (monitor_num == GSD_WACOM_SET_ALL_MONITORS) - return; - - screen = gdk_screen_get_default (); - - if (gdk_screen_get_n_monitors (screen) == 1) - return; - - if (manager->priv->shell_proxy == NULL) - manager->priv->shell_proxy = gnome_settings_bus_get_shell_proxy (); - - shell_show_osd (manager->priv->shell_proxy, - "input-tablet-symbolic", - gsd_wacom_device_get_name (device), -1, - monitor_num); -} - -static const char* -get_direction_name (GsdWacomTabletButtonType type, - GtkDirectionType dir) -{ - if (type == WACOM_TABLET_BUTTON_TYPE_RING) - return (dir == GTK_DIR_UP ? " 'CCW'" : " 'CW'"); - - if (type == WACOM_TABLET_BUTTON_TYPE_STRIP) - return (dir == GTK_DIR_UP ? " 'up'" : " 'down'"); - - return ""; -} - -static GdkFilterReturn -filter_button_events (XEvent *xevent, - GdkEvent *event, - GsdWacomManager *manager) -{ - XIEvent *xiev; - XIDeviceEvent *xev; - XGenericEventCookie *cookie; - guint deviceid; - GsdWacomDevice *device; - int button; - GsdWacomTabletButton *wbutton; - GtkDirectionType dir; - gboolean emulate; - - /* verify we have a key event */ - if (xevent->type != GenericEvent) - return GDK_FILTER_CONTINUE; - cookie = &xevent->xcookie; - if (cookie->extension != manager->priv->opcode) - return GDK_FILTER_CONTINUE; - - xiev = (XIEvent *) xevent->xcookie.data; - - if (xiev->evtype != XI_ButtonRelease && - xiev->evtype != XI_ButtonPress) - return GDK_FILTER_CONTINUE; - - xev = (XIDeviceEvent *) xiev; - - deviceid = xev->sourceid; - device = device_id_to_device (manager, deviceid); - if (gsd_wacom_device_get_device_type (device) != WACOM_TYPE_PAD) - return GDK_FILTER_CONTINUE; - - if ((manager->priv->osd_window != NULL) && - (device != gsd_wacom_osd_window_get_device (GSD_WACOM_OSD_WINDOW(manager->priv->osd_window)))) - /* This is a button event from another device while showing OSD window */ - osd_window_destroy (manager); - - button = xev->detail; - - wbutton = gsd_wacom_device_get_button (device, button, &dir); - if (wbutton == NULL) { - g_warning ("Could not find matching button for '%d' on '%s'", - button, gsd_wacom_device_get_name (device)); - return GDK_FILTER_CONTINUE; - } - - g_debug ("Received event button %s '%s'%s ('%d') on device '%s' ('%d')", - xiev->evtype == XI_ButtonPress ? "press" : "release", - wbutton->id, - get_direction_name (wbutton->type, dir), - button, - gsd_wacom_device_get_name (device), - deviceid); - - if (wbutton->type == WACOM_TABLET_BUTTON_TYPE_HARDCODED) { - int new_mode; - - /* We switch modes on key press */ - if (xiev->evtype == XI_ButtonRelease) { - osd_window_update_viewable (manager, wbutton, dir, xiev); - return GDK_FILTER_REMOVE; - } - new_mode = gsd_wacom_device_set_next_mode (device, wbutton); - if (manager->priv->osd_window != NULL) { - gsd_wacom_osd_window_set_mode (GSD_WACOM_OSD_WINDOW(manager->priv->osd_window), wbutton->group_id, new_mode); - osd_window_update_viewable (manager, wbutton, dir, xiev); - } - set_led (device, wbutton, new_mode); - return GDK_FILTER_REMOVE; - } - - if (manager->priv->osd_window != NULL) { - GsdWacomDevice *osd_window_device; - gboolean edition_mode; - - g_object_get (manager->priv->osd_window, - "wacom-device", &osd_window_device, - "edition-mode", &edition_mode, NULL); - - if (osd_window_device && device == osd_window_device && edition_mode) { - osd_window_update_viewable (manager, wbutton, dir, xiev); - g_object_unref (osd_window_device); - - return GDK_FILTER_REMOVE; - } - - g_object_unref (osd_window_device); - } - - /* Update OSD window if shown */ - emulate = osd_window_update_viewable (manager, wbutton, dir, xiev); - - /* Nothing to do */ - if (g_settings_get_enum (wbutton->settings, KEY_ACTION_TYPE) == GSD_WACOM_ACTION_TYPE_NONE) - return GDK_FILTER_REMOVE; - - /* Show OSD window when requested */ - if (g_settings_get_enum (wbutton->settings, KEY_ACTION_TYPE) == GSD_WACOM_ACTION_TYPE_HELP) { - if (xiev->evtype == XI_ButtonRelease) - osd_window_toggle_visibility (manager, device); - return GDK_FILTER_REMOVE; - } - - if (emulate) - return GDK_FILTER_REMOVE; - - /* Switch monitor */ - if (g_settings_get_enum (wbutton->settings, KEY_ACTION_TYPE) == GSD_WACOM_ACTION_TYPE_SWITCH_MONITOR) { - if (xiev->evtype == XI_ButtonRelease) { - switch_monitor (manager, device); - notify_osd_for_device (manager, device); - } - return GDK_FILTER_REMOVE; - } - - /* Send a key combination out */ - generate_key (wbutton, xev->group.effective, xev->display, dir, xiev->evtype == XI_ButtonPress ? True : False); - - return GDK_FILTER_REMOVE; } static void @@ -1605,8 +260,6 @@ set_devicepresence_handler (GsdWacomManager *manager) device_manager = gsd_device_manager_get (); manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", G_CALLBACK (device_added_cb), manager); - manager->priv->device_changed_id = g_signal_connect (G_OBJECT (device_manager), "device-changed", - G_CALLBACK (device_changed_cb), manager); manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", G_CALLBACK (device_removed_cb), manager); manager->priv->device_manager = device_manager; @@ -1618,40 +271,6 @@ gsd_wacom_manager_init (GsdWacomManager *manager) manager->priv = GSD_WACOM_MANAGER_GET_PRIVATE (manager); } -static void -device_mapping_changed (GsdDeviceMapper *mapper, - GsdDevice *gsd_device, - GsdWacomManager *manager) -{ - guint i, n_gdk_devices; - GdkDevice **devices; - - if (gnome_settings_is_wayland ()) - return; - - devices = gsd_x11_device_manager_get_gdk_devices (GSD_X11_DEVICE_MANAGER (manager->priv->device_manager), - gsd_device, &n_gdk_devices); - - for (i = 0; i < n_gdk_devices; i++) { - GsdWacomDevice *wacom_device; - GsdWacomDeviceType type; - GSettings *settings; - - wacom_device = g_hash_table_lookup (manager->priv->devices, devices[i]); - - if (!wacom_device) - continue; - - settings = gsd_wacom_device_get_settings (wacom_device); - type = gsd_wacom_device_get_device_type (wacom_device); - - if (type != WACOM_TYPE_TOUCH && type != WACOM_TYPE_PAD) - set_keep_aspect (wacom_device, g_settings_get_boolean (settings, KEY_KEEP_ASPECT)); - } - - g_free (devices); -} - static gboolean gsd_wacom_manager_idle_cb (GsdWacomManager *manager) { @@ -1661,14 +280,6 @@ gsd_wacom_manager_idle_cb (GsdWacomManager *manager) manager->priv->device_mapper = gsd_device_mapper_get (); - manager->priv->mapping_changed_id = - g_signal_connect (manager->priv->device_mapper, "device-changed", - G_CALLBACK (device_mapping_changed), manager); - - manager->priv->warned_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - manager->priv->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); - set_devicepresence_handler (manager); devices = gsd_device_manager_list_devices (manager->priv->device_manager, @@ -1677,13 +288,6 @@ gsd_wacom_manager_idle_cb (GsdWacomManager *manager) device_added_cb (manager->priv->device_manager, l->data, manager); g_list_free (devices); - if (!gnome_settings_is_wayland ()) { - /* Start filtering the button events */ - gdk_window_add_filter (gdk_screen_get_root_window (manager->priv->screen), - (GdkFilterFunc) filter_button_events, - manager); - } - gnome_settings_profile_end (NULL); manager->priv->start_idle_id = 0; @@ -1691,87 +295,6 @@ gsd_wacom_manager_idle_cb (GsdWacomManager *manager) return FALSE; } -/* - * The monitors-changed signal is emitted when the number, size or - * position of the monitors attached to the screen change. - */ -static void -on_screen_changed_cb (GnomeRRScreen *rr_screen, - GsdWacomManager *manager) -{ - GList *devices, *l; - - /* - * A ::changed signal may be received at startup before - * the devices get added, in this case simply ignore the - * notification - */ - if (manager->priv->devices == NULL) - return; - - g_debug ("Screen configuration changed"); - devices = g_hash_table_get_values (manager->priv->devices); - for (l = devices; l != NULL; l = l->next) { - GsdWacomDevice *device = l->data; - GsdWacomDeviceType type; - GSettings *settings; - - type = gsd_wacom_device_get_device_type (device); - if (type == WACOM_TYPE_CURSOR || type == WACOM_TYPE_PAD) - continue; - - settings = gsd_wacom_device_get_settings (device); - /* Ignore touch devices as they do not share the same range of values for area */ - if (type != WACOM_TYPE_TOUCH) { - if (gsd_wacom_device_is_screen_tablet (device) == FALSE) { - set_keep_aspect (device, g_settings_get_boolean (settings, KEY_KEEP_ASPECT)); - } - - set_area (device, g_settings_get_value (settings, KEY_AREA)); - } - } - g_list_free (devices); -} - -static void -on_rr_screen_acquired (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - GsdWacomManager *manager = user_data; - GError *error = NULL; - - manager->priv->rr_screen = gnome_rr_screen_new_finish (result, &error); - if (manager->priv->rr_screen == NULL) { - g_warning ("Failed to create GnomeRRScreen: %s", error->message); - g_error_free (error); - return; - } - - g_signal_connect (manager->priv->rr_screen, - "changed", - G_CALLBACK (on_screen_changed_cb), - manager); -} - -static void -init_screen (GsdWacomManager *manager) -{ - GdkScreen *screen; - - screen = gdk_screen_get_default (); - if (screen == NULL) { - return; - } - manager->priv->screen = screen; - - /* - * We keep GnomeRRScreen to monitor changes such as rotation - * which are not reported by Gdk's "monitors-changed" callback - */ - gnome_rr_screen_new_async (screen, on_rr_screen_acquired, manager); -} - static void on_bus_gotten (GObject *source_object, GAsyncResult *res, @@ -1835,17 +358,6 @@ gsd_wacom_manager_start (GsdWacomManager *manager, { gnome_settings_profile_start (NULL); - if (supports_xinput2_devices (&manager->priv->opcode) == FALSE) { - g_debug ("No Xinput2 support, disabling plugin"); - return TRUE; - } - - if (supports_xtest () == FALSE) { - g_debug ("No XTest extension support, disabling plugin"); - return TRUE; - } - - init_screen (manager); register_manager (manager_object); manager->priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_wacom_manager_idle_cb, manager); @@ -1860,9 +372,6 @@ void gsd_wacom_manager_stop (GsdWacomManager *manager) { GsdWacomManagerPrivate *p = manager->priv; - GsdWacomDeviceType type; - GsdWacomDevice *device; - GHashTableIter iter; g_debug ("Stopping wacom manager"); @@ -1879,33 +388,9 @@ gsd_wacom_manager_stop (GsdWacomManager *manager) if (p->device_manager != NULL) { g_signal_handler_disconnect (p->device_manager, p->device_added_id); - g_signal_handler_disconnect (p->device_manager, p->device_changed_id); g_signal_handler_disconnect (p->device_manager, p->device_removed_id); p->device_manager = NULL; } - - if (!gnome_settings_is_wayland ()) { - g_hash_table_iter_init (&iter, manager->priv->devices); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) { - type = gsd_wacom_device_get_device_type (device); - if (type == WACOM_TYPE_PAD) { - GdkDevice *gdk_device; - - gdk_device = gsd_wacom_device_get_gdk_device (device); - grab_button (gdk_x11_device_get_id (gdk_device), - FALSE, manager->priv->screen); - } - } - - gdk_window_remove_filter (gdk_screen_get_root_window (p->screen), - (GdkFilterFunc) filter_button_events, - manager); - } - - g_signal_handlers_disconnect_by_func (p->rr_screen, on_screen_changed_cb, manager); - - g_clear_pointer (&p->osd_window, gtk_widget_destroy); } static void @@ -1922,26 +407,6 @@ gsd_wacom_manager_finalize (GObject *object) gsd_wacom_manager_stop (wacom_manager); - if (wacom_manager->priv->mapping_changed_id) { - g_signal_handler_disconnect (wacom_manager->priv->device_mapper, - wacom_manager->priv->mapping_changed_id); - } - - if (wacom_manager->priv->warned_devices) { - g_hash_table_destroy (wacom_manager->priv->warned_devices); - wacom_manager->priv->warned_devices = NULL; - } - - if (wacom_manager->priv->devices) { - g_hash_table_destroy (wacom_manager->priv->devices); - wacom_manager->priv->devices = NULL; - } - - if (wacom_manager->priv->rr_screen != NULL) { - g_clear_object (&wacom_manager->priv->rr_screen); - wacom_manager->priv->rr_screen = NULL; - } - if (wacom_manager->priv->start_idle_id != 0) g_source_remove (wacom_manager->priv->start_idle_id); diff --git a/plugins/wacom/gsd-wacom-oled.c b/plugins/wacom/gsd-wacom-oled.c index b4b5a4ff..e3cac8ba 100644 --- a/plugins/wacom/gsd-wacom-oled.c +++ b/plugins/wacom/gsd-wacom-oled.c @@ -29,12 +29,12 @@ #include <libwacom/libwacom.h> #include <gtk/gtk.h> -#include "gsd-wacom-device.h" +#include "gsd-device-manager.h" #include "gsd-wacom-oled.h" #define MAGIC_BASE64 "base64:" /*Label starting with base64: is treated as already encoded*/ #define MAGIC_BASE64_LEN strlen(MAGIC_BASE64) -#define ROTATION_KEY "rotation" +#define LEFT_HANDED_KEY "left-handed" static void oled_surface_to_image (guchar *image, @@ -100,7 +100,7 @@ oled_split_text (char *label, static void oled_render_text (char *label, guchar *image, - GsdWacomRotation rotation) + gboolean left_handed) { cairo_t *cr; cairo_surface_t *surface; @@ -122,8 +122,7 @@ oled_render_text (char *label, /* Rotate text so it's seen correctly on the device, or at * least from top to bottom for LTR text in vertical modes. */ - if (rotation == GSD_WACOM_ROTATION_HALF || - rotation == GSD_WACOM_ROTATION_CCW) { + if (left_handed) { cairo_translate (cr, OLED_WIDTH, OLED_HEIGHT); cairo_scale (cr, -1, -1); } @@ -209,66 +208,61 @@ gsd_wacom_oled_gdkpixbuf_to_base64 (GdkPixbuf *pixbuf) static char * oled_encode_image (char *label, - GsdWacomRotation rotation) + gboolean left_handed) { unsigned char *image; image = g_malloc (MAX_IMAGE_SIZE); /* convert label to image */ - oled_render_text (label, image, rotation); + oled_render_text (label, image, left_handed); return (g_base64_encode (image, MAX_IMAGE_SIZE)); } -void -set_oled (GsdWacomDevice *device, - char *button_id, - char *label) +gboolean +set_oled (GsdDevice *device, + guint button, + char *label, + GError **error) { - GsdWacomRotation device_rotation; - GError *error = NULL; + gboolean left_handed = FALSE; GSettings *settings; const char *path; char *command; gboolean ret; char *buffer; + gint status; #ifndef HAVE_GUDEV /* Not implemented on non-Linux systems */ - return; + return TRUE; #endif - char *button_id_1; - int button_id_short; - button_id_1 = g_strdup (button_id); - button_id_short = (int)button_id_1[6]; - button_id_short = button_id_short - 'A' - 1; - if (g_str_has_prefix (label, MAGIC_BASE64)) { buffer = g_strdup (label + MAGIC_BASE64_LEN); } else { - settings = gsd_wacom_device_get_settings (device); - device_rotation = g_settings_get_enum (settings, ROTATION_KEY); - buffer = oled_encode_image (label, device_rotation); + settings = gsd_device_get_settings (device); + left_handed = g_settings_get_boolean (settings, LEFT_HANDED_KEY); + buffer = oled_encode_image (label, left_handed); } - path = gsd_wacom_device_get_path (device); + path = gsd_device_get_device_file (device); - g_debug ("Setting OLED label '%s' on button %d (device %s)", label, button_id_short, path); + g_debug ("Setting OLED label '%s' on button %d (device %s)", label, button, path); command = g_strdup_printf ("pkexec " LIBEXECDIR "/gsd-wacom-oled-helper --path %s --button %d --buffer %s", - path, button_id_short, buffer); + path, button, buffer); ret = g_spawn_command_line_sync (command, NULL, NULL, - NULL, - &error); + &status, + error); - if (ret == FALSE) { - g_debug ("Failed to launch '%s': %s", command, error->message); - g_error_free (error); - } + if (ret == TRUE && status != 0) + ret = FALSE; g_free (command); + + return ret; } diff --git a/plugins/wacom/gsd-wacom-oled.h b/plugins/wacom/gsd-wacom-oled.h index f71176a0..c8db138f 100644 --- a/plugins/wacom/gsd-wacom-oled.h +++ b/plugins/wacom/gsd-wacom-oled.h @@ -18,13 +18,14 @@ */ #include "gsd-wacom-oled-constants.h" +#include "gsd-device-manager.h" #ifndef __GSD_WACOM_OLED_H #define __GSD_WACOM_OLED_H G_BEGIN_DECLS -void set_oled (GsdWacomDevice *device, char *button_id, char *label); +gboolean set_oled (GsdDevice *device, guint button, char *label, GError **error); char *gsd_wacom_oled_gdkpixbuf_to_base64 (GdkPixbuf *pixbuf); G_END_DECLS diff --git a/plugins/wacom/gsd-wacom-osd-window.c b/plugins/wacom/gsd-wacom-osd-window.c deleted file mode 100644 index d0814b0f..00000000 --- a/plugins/wacom/gsd-wacom-osd-window.c +++ /dev/null @@ -1,2104 +0,0 @@ -/* - * Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. - * - * Author: Olivier Fourdan <ofourdan@redhat.com> - * - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <cairo.h> -#include <librsvg/rsvg.h> - -#include "gsd-wacom-osd-window.h" -#include "gsd-wacom-device.h" -#include "gsd-wacom-button-editor.h" -#include "gsd-enums.h" - -#define ROTATION_KEY "rotation" -#define ACTION_TYPE_KEY "action-type" -#define CUSTOM_ACTION_KEY "custom-action" -#define CUSTOM_ELEVATOR_ACTION_KEY "custom-elevator-action" -#define RES_PATH "/org/gnome/settings-daemon/plugins/wacom/" - -#define BACK_OPACITY 0.8 -#define OPACITY_IN_EDITION "0.5" -#define INACTIVE_COLOR "#ededed" -#define ACTIVE_COLOR "#729fcf" -#define STROKE_COLOR "#000000" -#define DARK_COLOR "#535353" -#define BACK_COLOR "#000000" - -#define BUTTON_HIGHLIGHT_DURATION 250 /* ms */ -#define BUTTON_TRANSITION_DURATION 150 /* ms */ -#define BUTTON_TIMER_STEP 25 /* ms */ -#define BUTTON_FULL_TRANSITION 1.0 /* % */ - -#define CURSOR_HIDE_TIMEOUT 2 /* seconds */ - -#define CSS_NORMAL_BUTTON \ - "%s.%s {\n" \ - " opacity: %s\n" \ - "}\n" - -#define CSS_EDITING_BUTTON \ - "%s.%s {\n" \ - " stroke: %s !important;\n" \ - " fill: %s !important;\n" \ - "}\n" - -static struct { - const gchar *color_name; - const gchar *color_value; -} css_color_table[] = { - { "inactive_color", INACTIVE_COLOR }, - { "active_color", ACTIVE_COLOR }, - { "stroke_color", STROKE_COLOR }, - { "dark_color", DARK_COLOR }, - { "back_color", BACK_COLOR } -}; - -static gchar * -replace_string (gchar **string, const gchar *search, const char *replacement) -{ - GRegex *regex; - gchar *res; - - g_return_val_if_fail (*string != NULL, NULL); - g_return_val_if_fail (string != NULL, NULL); - g_return_val_if_fail (search != NULL, *string); - g_return_val_if_fail (replacement != NULL, *string); - - regex = g_regex_new (search, 0, 0, NULL); - res = g_regex_replace_literal (regex, *string, -1, 0, replacement, 0, NULL); - g_regex_unref (regex); - /* The given string is freed and replaced by the resulting replacement */ - g_free (*string); - *string = res; - - return res; -} - -static gchar -get_last_char (gchar *string) -{ - size_t pos; - - g_return_val_if_fail (string != NULL, '\0'); - pos = strlen (string); - g_return_val_if_fail (pos > 0, '\0'); - - return string[pos - 1]; -} - -static double -get_rotation_in_radian (GsdWacomRotation rotation) -{ - switch (rotation) { - case GSD_WACOM_ROTATION_NONE: - return 0.0; - break; - case GSD_WACOM_ROTATION_HALF: - return G_PI; - break; - /* We only support left-handed/right-handed */ - case GSD_WACOM_ROTATION_CCW: - case GSD_WACOM_ROTATION_CW: - default: - break; - } - - /* Fallback */ - return 0.0; -} - -static gboolean -get_sub_location (RsvgHandle *handle, - const char *sub, - cairo_t *cr, - double *x, - double *y) -{ - RsvgPositionData position; - double tx, ty; - - if (!rsvg_handle_get_position_sub (handle, &position, sub)) - return FALSE; - - tx = (double) position.x; - ty = (double) position.y; - cairo_user_to_device (cr, &tx, &ty); - - if (x) - *x = tx; - if (y) - *y = ty; - - return TRUE; -} - -static gboolean -get_image_size (const char *filename, int *width, int *height) -{ - RsvgHandle *handle; - RsvgDimensionData dimensions; - GError* error = NULL; - - if (filename == NULL) - return FALSE; - - handle = rsvg_handle_new_from_file (filename, &error); - if (error != NULL) { - g_printerr ("%s\n", error->message); - g_error_free (error); - } - if (handle == NULL) - return FALSE; - - /* Compute image size */ - rsvg_handle_get_dimensions (handle, &dimensions); - g_object_unref (handle); - - if (dimensions.width == 0 || dimensions.height == 0) - return FALSE; - - if (width) - *width = dimensions.width; - - if (height) - *height = dimensions.height; - - return TRUE; -} - -static int -get_pango_vertical_offset (PangoLayout *layout) -{ - const PangoFontDescription *desc; - PangoContext *context; - PangoLanguage *language; - PangoFontMetrics *metrics; - int baseline; - int strikethrough; - int thickness; - - context = pango_layout_get_context (layout); - language = pango_language_get_default (); - desc = pango_layout_get_font_description (layout); - metrics = pango_context_get_metrics (context, desc, language); - - baseline = pango_layout_get_baseline (layout); - strikethrough = pango_font_metrics_get_strikethrough_position (metrics); - thickness = pango_font_metrics_get_underline_thickness (metrics); - - return PANGO_PIXELS (baseline - strikethrough - thickness / 2); -} - -#define GSD_TYPE_WACOM_OSD_BUTTON (gsd_wacom_osd_button_get_type ()) -#define GSD_WACOM_OSD_BUTTON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_WACOM_OSD_BUTTON, GsdWacomOSDButton)) -#define GSD_WACOM_OSD_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_WACOM_OSD_BUTTON, GsdWacomOSDButtonClass)) -#define GSD_IS_WACOM_OSD_BUTTON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_WACOM_OSD_BUTTON)) -#define GSD_IS_WACOM_OSD_BUTTON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_WACOM_OSD_BUTTON)) -#define GSD_WACOM_OSD_BUTTON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_WACOM_OSD_BUTTON, GsdWacomOSDButtonClass)) - -typedef struct GsdWacomOSDButtonPrivate GsdWacomOSDButtonPrivate; - -typedef struct { - GObject parent; - GsdWacomOSDButtonPrivate *priv; -} GsdWacomOSDButton; - -typedef struct { - GObjectClass parent_class; -} GsdWacomOSDButtonClass; - -GType gsd_wacom_osd_button_get_type (void) G_GNUC_CONST; - -enum { - PROP_OSD_BUTTON_0, - PROP_OSD_BUTTON_ID, - PROP_OSD_BUTTON_CLASS, - PROP_OSD_BUTTON_LABEL, - PROP_OSD_BUTTON_ACTIVE, - PROP_OSD_BUTTON_VISIBLE -}; - -#define GSD_WACOM_OSD_BUTTON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - GSD_TYPE_WACOM_OSD_BUTTON, \ - GsdWacomOSDButtonPrivate)) -#define MATCH_ID(b,s) (g_strcmp0 (b->priv->id, s) == 0) - -struct GsdWacomOSDButtonPrivate { - GtkWidget *widget; - char *id; - char *class; - char *label; - double label_x; - double label_y; - GsdWacomTabletButtonType type; - GsdWacomTabletButtonPos position; - gboolean active; - gboolean visible; - GdkRGBA active_color; - GdkRGBA inactive_color; - - /* Animations */ - gboolean next_state; /* what the next state should be, "active" or not */ - guint timeout_id; /* ms */ - gint elapsed_time; /* ms */ - gdouble transition_percentage; /* 0.0 to 1.0 */ -}; - -static void gsd_wacom_osd_button_class_init (GsdWacomOSDButtonClass *klass); -static void gsd_wacom_osd_button_init (GsdWacomOSDButton *osd_button); -static void gsd_wacom_osd_button_finalize (GObject *object); - -G_DEFINE_TYPE (GsdWacomOSDButton, gsd_wacom_osd_button, G_TYPE_OBJECT) - -static void -gsd_wacom_osd_button_set_id (GsdWacomOSDButton *osd_button, - const gchar *id) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->id = g_strdup (id); -} - -static void -gsd_wacom_osd_button_set_class (GsdWacomOSDButton *osd_button, - const gchar *class) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->class = g_strdup (class); -} - -static gchar* -gsd_wacom_osd_button_get_label_class (GsdWacomOSDButton *osd_button) -{ - gchar *label_class; - - label_class = g_strconcat ("#Label", osd_button->priv->class, NULL); - - return (label_class); -} - -static void -gsd_wacom_osd_button_set_label (GsdWacomOSDButton *osd_button, - const gchar *str) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - g_free (osd_button->priv->label); - osd_button->priv->label = g_strdup (str ? str : ""); -} - -static void -gsd_wacom_osd_button_set_button_type (GsdWacomOSDButton *osd_button, - GsdWacomTabletButtonType type) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->type = type; -} - -static void -gsd_wacom_osd_button_set_position (GsdWacomOSDButton *osd_button, - GsdWacomTabletButtonPos position) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->position = position; -} - -static void -gsd_wacom_osd_button_set_location (GsdWacomOSDButton *osd_button, - double x, - double y) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->label_x = x; - osd_button->priv->label_y = y; -} - -static void -gsd_wacom_osd_button_redraw (GsdWacomOSDButton *osd_button) -{ - GdkWindow *window; - - g_return_if_fail (GTK_IS_WIDGET (osd_button->priv->widget)); - - window = gtk_widget_get_window (GTK_WIDGET (osd_button->priv->widget)); - gdk_window_invalidate_rect (window, NULL, FALSE); -} - -static gboolean -gsd_wacom_osd_button_timer (GsdWacomOSDButton *osd_button) -{ - gint total_timeout; - gdouble transition_step; - gboolean ret = G_SOURCE_CONTINUE; - - total_timeout = BUTTON_TRANSITION_DURATION; - /* if the state is active, then we need it to be "on" at least - * for the time of BUTTON_HIGHLIGHT_DURATION after the fade-in */ - if (osd_button->priv->active) - total_timeout += BUTTON_HIGHLIGHT_DURATION; - - transition_step = (gdouble) BUTTON_TIMER_STEP / BUTTON_TRANSITION_DURATION; - osd_button->priv->transition_percentage = MIN (osd_button->priv->transition_percentage + transition_step, - BUTTON_FULL_TRANSITION); - - osd_button->priv->elapsed_time += BUTTON_TIMER_STEP; - if (osd_button->priv->elapsed_time > total_timeout) { - /* If the next state and the current one are the same, then - * we finish this timer */ - if (osd_button->priv->active == osd_button->priv->next_state) { - ret = G_SOURCE_REMOVE; - osd_button->priv->timeout_id = 0; - } else - osd_button->priv->active = osd_button->priv->next_state; - - osd_button->priv->elapsed_time = 0; - osd_button->priv->transition_percentage = 0; - } - - gsd_wacom_osd_button_redraw (osd_button); - - return ret; -} - -static void -invert_button_color_transition (GsdWacomOSDButton *osd_button) -{ - osd_button->priv->elapsed_time = (BUTTON_HIGHLIGHT_DURATION + BUTTON_TRANSITION_DURATION) - osd_button->priv->elapsed_time; - osd_button->priv->transition_percentage = BUTTON_FULL_TRANSITION - osd_button->priv->transition_percentage; -} - -static void -extend_on_state (GsdWacomOSDButton *osd_button) -{ - osd_button->priv->elapsed_time = BUTTON_TRANSITION_DURATION; - osd_button->priv->transition_percentage = BUTTON_FULL_TRANSITION; -} - -static void -gsd_wacom_osd_button_set_active (GsdWacomOSDButton *osd_button, - gboolean active) -{ - gboolean previous_state; - - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->next_state = active; - previous_state = osd_button->priv->active; - if (osd_button->priv->timeout_id == 0) { - osd_button->priv->active = active; - osd_button->priv->timeout_id = g_timeout_add (BUTTON_TIMER_STEP, - (GSourceFunc) gsd_wacom_osd_button_timer, - osd_button); - g_source_set_name_by_id (osd_button->priv->timeout_id, "[gnome-settings-daemon] gsd_wacom_osd_button_timer"); - } else if (osd_button->priv->next_state) { - /* it was on and now should be on again */ - if (previous_state == active) { - /* if the button has transitioned to on already, then it - * needs to remain on for the default amount of time again */ - if (osd_button->priv->elapsed_time > BUTTON_TRANSITION_DURATION) - extend_on_state (osd_button); - } else { - /* if we have an on-going timeout which was fading out and - * now we need to fade it in again, we just invert the transition*/ - invert_button_color_transition (osd_button); - } - } -} - -static void -gsd_wacom_osd_button_set_visible (GsdWacomOSDButton *osd_button, - gboolean visible) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - osd_button->priv->visible = visible; -} - -static GsdWacomOSDButton * -gsd_wacom_osd_button_new (GtkWidget *widget, - gchar *id) -{ - GsdWacomOSDButton *osd_button; - - osd_button = GSD_WACOM_OSD_BUTTON (g_object_new (GSD_TYPE_WACOM_OSD_BUTTON, - "id", id, - NULL)); - osd_button->priv->widget = widget; - - return osd_button; -} - -static void -gsd_wacom_osd_button_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GsdWacomOSDButton *osd_button; - - osd_button = GSD_WACOM_OSD_BUTTON (object); - - switch (prop_id) { - case PROP_OSD_BUTTON_ID: - gsd_wacom_osd_button_set_id (osd_button, g_value_get_string (value)); - break; - case PROP_OSD_BUTTON_CLASS: - gsd_wacom_osd_button_set_class (osd_button, g_value_get_string (value)); - break; - case PROP_OSD_BUTTON_LABEL: - gsd_wacom_osd_button_set_label (osd_button, g_value_get_string (value)); - break; - case PROP_OSD_BUTTON_ACTIVE: - gsd_wacom_osd_button_set_active (osd_button, g_value_get_boolean (value)); - break; - case PROP_OSD_BUTTON_VISIBLE: - gsd_wacom_osd_button_set_visible (osd_button, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gsd_wacom_osd_button_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GsdWacomOSDButton *osd_button; - - osd_button = GSD_WACOM_OSD_BUTTON (object); - - switch (prop_id) { - case PROP_OSD_BUTTON_ID: - g_value_set_string (value, osd_button->priv->id); - break; - case PROP_OSD_BUTTON_CLASS: - g_value_set_string (value, osd_button->priv->class); - break; - case PROP_OSD_BUTTON_LABEL: - g_value_set_string (value, osd_button->priv->label); - break; - case PROP_OSD_BUTTON_ACTIVE: - g_value_set_boolean (value, osd_button->priv->active); - break; - case PROP_OSD_BUTTON_VISIBLE: - g_value_set_boolean (value, osd_button->priv->visible); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gsd_wacom_osd_button_class_init (GsdWacomOSDButtonClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = gsd_wacom_osd_button_set_property; - object_class->get_property = gsd_wacom_osd_button_get_property; - object_class->finalize = gsd_wacom_osd_button_finalize; - - g_object_class_install_property (object_class, - PROP_OSD_BUTTON_ID, - g_param_spec_string ("id", - "Button Id", - "The Wacom Button ID", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_OSD_BUTTON_CLASS, - g_param_spec_string ("class", - "Button Class", - "The Wacom Button Class", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_OSD_BUTTON_LABEL, - g_param_spec_string ("label", - "Label", - "The button label", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_OSD_BUTTON_ACTIVE, - g_param_spec_boolean ("active", - "Active", - "Whether the button is active", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_OSD_BUTTON_VISIBLE, - g_param_spec_boolean ("visible", - "Visible", - "Whether the button is visible", - TRUE, - G_PARAM_READWRITE)); - - g_type_class_add_private (klass, sizeof (GsdWacomOSDButtonPrivate)); -} - -static void -gsd_wacom_osd_button_init (GsdWacomOSDButton *osd_button) -{ - osd_button->priv = GSD_WACOM_OSD_BUTTON_GET_PRIVATE (osd_button); - - gdk_rgba_parse (&osd_button->priv->active_color, ACTIVE_COLOR); - gdk_rgba_parse (&osd_button->priv->inactive_color, INACTIVE_COLOR); -} - -static void -gsd_wacom_osd_button_finalize (GObject *object) -{ - GsdWacomOSDButton *osd_button; - GsdWacomOSDButtonPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (object)); - - osd_button = GSD_WACOM_OSD_BUTTON (object); - - g_return_if_fail (osd_button->priv != NULL); - - priv = osd_button->priv; - - if (priv->timeout_id > 0) - g_source_remove (priv->timeout_id); - g_clear_pointer (&priv->id, g_free); - g_clear_pointer (&priv->class, g_free); - g_clear_pointer (&priv->label, g_free); - - G_OBJECT_CLASS (gsd_wacom_osd_button_parent_class)->finalize (object); -} - -/* Compute the new actual position once rotation is applied */ -static GsdWacomTabletButtonPos -get_actual_position (GsdWacomTabletButtonPos position, - GsdWacomRotation rotation) -{ - switch (rotation) { - case GSD_WACOM_ROTATION_NONE: - return position; - break; - case GSD_WACOM_ROTATION_HALF: - if (position == WACOM_TABLET_BUTTON_POS_LEFT) - return WACOM_TABLET_BUTTON_POS_RIGHT; - if (position == WACOM_TABLET_BUTTON_POS_RIGHT) - return WACOM_TABLET_BUTTON_POS_LEFT; - if (position == WACOM_TABLET_BUTTON_POS_TOP) - return WACOM_TABLET_BUTTON_POS_BOTTOM; - if (position == WACOM_TABLET_BUTTON_POS_BOTTOM) - return WACOM_TABLET_BUTTON_POS_TOP; - break; - /* We only support left-handed/right-handed */ - case GSD_WACOM_ROTATION_CCW: - case GSD_WACOM_ROTATION_CW: - default: - break; - } - /* fallback */ - return position; -} - -static gchar * -rgb_color_to_hex (GdkRGBA *color) -{ - gchar *hex_color; - - hex_color = g_strdup_printf ("#%02X%02X%02X", - (guint) (color->red * 255), - (guint) (color->green * 255), - (guint) (color->blue * 255)); - - return hex_color; -} - -static GdkRGBA * -transition_rgba_colors (GdkRGBA *from_rgba, - GdkRGBA *to_rgba, - gdouble transition_percentage) -{ - GdkRGBA *new_color = gdk_rgba_copy (from_rgba); - - if (transition_percentage == 0.0) - return new_color; - - new_color->red -= (from_rgba->red - to_rgba->red) * transition_percentage; - new_color->green -= (from_rgba->green - to_rgba->green) * transition_percentage; - new_color->blue -= (from_rgba->blue - to_rgba->blue) * transition_percentage; - - return new_color; -} - -static gchar * -gsd_wacom_osd_button_get_color_str (GsdWacomOSDButton *osd_button) -{ - GdkRGBA *current_color, *from_color, *to_color; - gboolean free_current_color = FALSE; - gchar *color_str; - - /* If we got an on-going transition, then we need to apply it */ - if (osd_button->priv->timeout_id > 0) { - if (osd_button->priv->active) { - from_color = &osd_button->priv->inactive_color; - to_color = &osd_button->priv->active_color; - } else { - from_color = &osd_button->priv->active_color; - to_color = &osd_button->priv->inactive_color; - } - - current_color = transition_rgba_colors (from_color, to_color, osd_button->priv->transition_percentage); - - free_current_color = TRUE; - } else - current_color = osd_button->priv->active ? &osd_button->priv->active_color : &osd_button->priv->inactive_color; - - color_str = rgb_color_to_hex (current_color); - - if (free_current_color) - gdk_rgba_free (current_color); - - return color_str; -} - -static void -gsd_wacom_osd_button_draw_label (GsdWacomOSDButton *osd_button, - GtkStyleContext *style_context, - PangoContext *pango_context, - cairo_t *cr, - GsdWacomRotation rotation) -{ - GsdWacomOSDButtonPrivate *priv; - PangoLayout *layout; - PangoRectangle logical_rect; - GsdWacomTabletButtonPos actual_position; - double lx, ly; - gchar *markup, *color_str; - - g_return_if_fail (GSD_IS_WACOM_OSD_BUTTON (osd_button)); - - priv = osd_button->priv; - if (priv->visible == FALSE) - return; - - actual_position = get_actual_position (priv->position, rotation); - layout = pango_layout_new (pango_context); - color_str = gsd_wacom_osd_button_get_color_str (osd_button); - markup = g_strdup_printf ("<span foreground=\"%s\" weight=\"normal\">%s</span>", color_str, priv->label); - g_free (color_str); - pango_layout_set_markup (layout, markup, -1); - g_free (markup); - - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - switch (actual_position) { - case WACOM_TABLET_BUTTON_POS_LEFT: - pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); - lx = priv->label_x + logical_rect.x; - ly = priv->label_y + logical_rect.y - get_pango_vertical_offset (layout); - break; - case WACOM_TABLET_BUTTON_POS_RIGHT: - pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); - lx = priv->label_x + logical_rect.x - logical_rect.width; - ly = priv->label_y + logical_rect.y - get_pango_vertical_offset (layout); - break; - case WACOM_TABLET_BUTTON_POS_TOP: - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - lx = priv->label_x + logical_rect.x - logical_rect.width / 2; - ly = priv->label_y + logical_rect.y; - break; - case WACOM_TABLET_BUTTON_POS_BOTTOM: - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - lx = priv->label_x + logical_rect.x - logical_rect.width / 2; - ly = priv->label_y + logical_rect.y - logical_rect.height; - break; - default: - g_warning ("Unhandled button position"); - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - lx = priv->label_x + logical_rect.x - logical_rect.width / 2; - ly = priv->label_y + logical_rect.y - logical_rect.height / 2; - break; - } - gtk_render_layout (style_context, cr, lx, ly, layout); - g_object_unref (layout); -} - -enum { - PROP_OSD_WINDOW_0, - PROP_OSD_WINDOW_MESSAGE, - PROP_OSD_WINDOW_GSD_WACOM_DEVICE, - PROP_OSD_WINDOW_EDITION_MODE -}; - -#define GSD_WACOM_OSD_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - GSD_TYPE_WACOM_OSD_WINDOW, \ - GsdWacomOSDWindowPrivate)) - -struct GsdWacomOSDWindowPrivate -{ - RsvgHandle *handle; - GsdWacomDevice *pad; - GsdWacomRotation rotation; - GdkRectangle screen_area; - GdkRectangle monitor_area; - GdkRectangle tablet_area; - char *message; - char *edition_mode_message; - char *regular_mode_message; - GList *buttons; - guint cursor_timeout; - gboolean edition_mode; - GsdWacomOSDButton *current_button; - GtkWidget *editor; - GtkWidget *change_mode_button; -}; - -static void gsd_wacom_osd_window_class_init (GsdWacomOSDWindowClass *klass); -static void gsd_wacom_osd_window_init (GsdWacomOSDWindow *osd_window); -static void gsd_wacom_osd_window_finalize (GObject *object); - -G_DEFINE_TYPE (GsdWacomOSDWindow, gsd_wacom_osd_window, GTK_TYPE_WINDOW) - -static gboolean -osd_window_editing_button (GsdWacomOSDWindow *self) -{ - return self->priv->edition_mode && gtk_widget_get_visible (self->priv->editor); -} - -static RsvgHandle * -load_rsvg_with_base (const char *css_string, - const char *original_layout_path, - GError **error) -{ - RsvgHandle *handle; - char *dirname; - - handle = rsvg_handle_new (); - - dirname = g_path_get_dirname (original_layout_path); - rsvg_handle_set_base_uri (handle, dirname); - g_free (dirname); - - if (!rsvg_handle_write (handle, - (guint8 *) css_string, - strlen (css_string), - error)) { - g_object_unref (handle); - return NULL; - } - if (!rsvg_handle_close (handle, error)) { - g_object_unref (handle); - return NULL; - } - - return handle; -} - -static void -gsd_wacom_osd_window_update (GsdWacomOSDWindow *osd_window) -{ - GError *error = NULL; - gchar *width, *height; - gchar *buttons_section; - gchar *css_string; - const gchar *layout_file; - GBytes *css_data; - guint i; - GList *l; - - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - g_return_if_fail (GSD_IS_WACOM_DEVICE (osd_window->priv->pad)); - - css_data = g_resources_lookup_data (RES_PATH "tablet-layout.css", 0, &error); - if (error != NULL) { - g_printerr ("GResource error: %s\n", error->message); - g_clear_pointer (&error, g_error_free); - } - if (css_data == NULL) - return; - css_string = g_strdup ((gchar *) g_bytes_get_data (css_data, NULL)); - g_bytes_unref(css_data); - - width = g_strdup_printf ("%d", osd_window->priv->tablet_area.width); - replace_string (&css_string, "layout_width", width); - g_free (width); - - height = g_strdup_printf ("%d", osd_window->priv->tablet_area.height); - replace_string (&css_string, "layout_height", height); - g_free (height); - - /* Build the buttons section */ - buttons_section = g_strdup (""); - for (l = osd_window->priv->buttons; l != NULL; l = l->next) { - gchar *color_str; - GsdWacomOSDButton *osd_button = l->data; - - if (osd_button->priv->visible == FALSE) - continue; - - if (osd_window_editing_button (osd_window) && - osd_button != osd_window->priv->current_button) { - buttons_section = g_strdup_printf (CSS_NORMAL_BUTTON, - buttons_section, - osd_button->priv->class, - OPACITY_IN_EDITION); - } else { - color_str = gsd_wacom_osd_button_get_color_str (osd_button); - buttons_section = g_strdup_printf (CSS_EDITING_BUTTON, - buttons_section, - osd_button->priv->class, - color_str, - color_str); - g_free (color_str); - } - } - replace_string (&css_string, "buttons_section", buttons_section); - g_free (buttons_section); - - for (i = 0; i < G_N_ELEMENTS (css_color_table); i++) - replace_string (&css_string, - css_color_table[i].color_name, - css_color_table[i].color_value); - - layout_file = gsd_wacom_device_get_layout_path (osd_window->priv->pad); - g_debug ("Using layout path: %s", layout_file); - replace_string (&css_string, "layout_file", layout_file); - - /* Render the SVG with the CSS applied */ - g_clear_object (&osd_window->priv->handle); - osd_window->priv->handle = load_rsvg_with_base (css_string, layout_file, &error); - if (osd_window->priv->handle == NULL) { - g_debug ("CSS applied:\n%s\n", css_string); - g_printerr ("RSVG error: %s\n", error->message); - g_clear_error (&error); - } - g_free (css_string); -} - -static void -gsd_wacom_osd_window_draw_message (GsdWacomOSDWindow *osd_window, - GtkStyleContext *style_context, - PangoContext *pango_context, - cairo_t *cr) -{ - GdkRectangle *monitor_area = &osd_window->priv->monitor_area; - PangoRectangle logical_rect; - PangoLayout *layout; - char *markup; - double x; - double y; - - if (osd_window->priv->message == NULL || osd_window_editing_button (osd_window)) - return; - - layout = pango_layout_new (pango_context); - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - - markup = g_strdup_printf ("<span foreground=\"white\">%s</span>", osd_window->priv->message); - pango_layout_set_markup (layout, markup, -1); - g_free (markup); - - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - x = (monitor_area->width - logical_rect.width) / 2 + logical_rect.x; - y = (monitor_area->height - logical_rect.height) / 2 + logical_rect.y; - - gtk_render_layout (style_context, cr, x, y, layout); - g_object_unref (layout); -} - -static void -gsd_wacom_osd_window_draw_labels (GsdWacomOSDWindow *osd_window, - GtkStyleContext *style_context, - PangoContext *pango_context, - cairo_t *cr) -{ - GList *l; - - for (l = osd_window->priv->buttons; l != NULL; l = l->next) { - GsdWacomOSDButton *osd_button = l->data; - - if (osd_button->priv->visible == FALSE) - continue; - - gsd_wacom_osd_button_draw_label (osd_button, - style_context, - pango_context, - cr, - osd_window->priv->rotation); - } -} - -static void -gsd_wacom_osd_window_place_buttons (GsdWacomOSDWindow *osd_window, - cairo_t *cr) -{ - GList *l; - - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - - for (l = osd_window->priv->buttons; l != NULL; l = l->next) { - GsdWacomOSDButton *osd_button = l->data; - double label_x, label_y; - gchar *sub; - - sub = gsd_wacom_osd_button_get_label_class (osd_button); - if (!get_sub_location (osd_window->priv->handle, sub, cr, &label_x, &label_y)) { - g_warning ("Failed to retrieve %s position", sub); - g_free (sub); - continue; - } - g_free (sub); - gsd_wacom_osd_button_set_location (osd_button, label_x, label_y); - } -} - -/* Note: this function does modify the given cairo context */ -static void -gsd_wacom_osd_window_adjust_cairo (GsdWacomOSDWindow *osd_window, - cairo_t *cr) -{ - double scale, twidth, theight; - GdkRectangle *tablet_area = &osd_window->priv->tablet_area; - GdkRectangle *screen_area = &osd_window->priv->screen_area; - GdkRectangle *monitor_area = &osd_window->priv->monitor_area; - - /* Rotate */ - cairo_rotate (cr, get_rotation_in_radian (osd_window->priv->rotation)); - - /* Scale to fit in window */ - scale = MIN ((double) monitor_area->width / tablet_area->width, - (double) monitor_area->height / tablet_area->height); - cairo_scale (cr, scale, scale); - - /* Center the result in window */ - twidth = (double) tablet_area->width; - theight = (double) tablet_area->height; - cairo_user_to_device_distance (cr, &twidth, &theight); - - twidth = ((double) monitor_area->width - twidth) / 2.0; - theight = ((double) monitor_area->height - theight) / 2.0; - cairo_device_to_user_distance (cr, &twidth, &theight); - - twidth = twidth + (double) (monitor_area->x - screen_area->x); - theight = theight + (double) (monitor_area->y - screen_area->y); - - cairo_translate (cr, twidth, theight); -} - -static gboolean -gsd_wacom_osd_window_draw (GtkWidget *widget, - cairo_t *cr) -{ - GsdWacomOSDWindow *osd_window = GSD_WACOM_OSD_WINDOW (widget); - - g_return_val_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window), FALSE); - g_return_val_if_fail (GSD_IS_WACOM_DEVICE (osd_window->priv->pad), FALSE); - - if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget))) { - GtkStyleContext *style_context; - PangoContext *pango_context; - - style_context = gtk_widget_get_style_context (widget); - pango_context = gtk_widget_get_pango_context (widget); - - cairo_set_source_rgba (cr, 0, 0, 0, BACK_OPACITY); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - - /* Save original matrix */ - cairo_save (cr); - - /* Apply new cairo transformation matrix */ - gsd_wacom_osd_window_adjust_cairo (osd_window, cr); - - /* And render the tablet layout */ - gsd_wacom_osd_window_update (osd_window); - rsvg_handle_render_cairo (osd_window->priv->handle, cr); - - gsd_wacom_osd_window_place_buttons (osd_window, cr); - - /* Reset to original matrix */ - cairo_restore (cr); - - /* Draw button labels and message */ - gsd_wacom_osd_window_draw_labels (osd_window, - style_context, - pango_context, - cr); - gsd_wacom_osd_window_draw_message (osd_window, - style_context, - pango_context, - cr); - } - - GTK_WIDGET_CLASS (gsd_wacom_osd_window_parent_class)->draw (widget, cr); - - return FALSE; -} - -static gchar * -get_escaped_accel_shortcut (const gchar *accel) -{ - guint keyval; - GdkModifierType mask; - gchar *str, *label; - - if (accel == NULL || accel[0] == '\0') - return g_strdup (C_("Action type", "None")); - - gtk_accelerator_parse (accel, &keyval, &mask); - - str = gtk_accelerator_get_label (keyval, mask); - label = g_markup_printf_escaped (C_("Action type", "Send Keystroke %s"), str); - g_free (str); - - return label; -} - -static gchar * -get_tablet_button_label_normal (GsdWacomDevice *device, - GsdWacomTabletButton *button) -{ - GsdWacomActionType type; - gchar *name, *str; - - type = g_settings_get_enum (button->settings, ACTION_TYPE_KEY); - if (type == GSD_WACOM_ACTION_TYPE_NONE) - return g_strdup (C_("Action type", "None")); - - if (type == GSD_WACOM_ACTION_TYPE_HELP) - return g_strdup (C_("Action type", "Show On-Screen Help")); - - if (type == GSD_WACOM_ACTION_TYPE_SWITCH_MONITOR) - return g_strdup (C_("Action type", "Switch Monitor")); - - str = g_settings_get_string (button->settings, CUSTOM_ACTION_KEY); - if (str == NULL || *str == '\0') { - g_free (str); - return g_strdup (C_("Action type", "None")); - } - - name = get_escaped_accel_shortcut (str); - g_free (str); - - return name; -} - -static gchar * -get_tablet_button_label_touch (GsdWacomDevice *device, - GsdWacomTabletButton *button, - GtkDirectionType dir) -{ - char **strv, *name, *str; - - strv = g_settings_get_strv (button->settings, CUSTOM_ELEVATOR_ACTION_KEY); - name = NULL; - - if (strv) { - if (g_strv_length (strv) >= 1 && dir == GTK_DIR_UP) - name = g_strdup (strv[0]); - else if (g_strv_length (strv) >= 2 && dir == GTK_DIR_DOWN) - name = g_strdup (strv[1]); - g_strfreev (strv); - } - - str = get_escaped_accel_shortcut (name); - g_free (name); - name = str; - - /* With multiple modes, also show the current mode for that action */ - if (gsd_wacom_device_get_num_modes (device, button->group_id) > 1) { - name = g_strdup_printf (_("Mode %d: %s"), button->idx + 1, str); - g_free (str); - } - - return name; -} - -static gchar * -get_tablet_button_label (GsdWacomDevice *device, - GsdWacomTabletButton *button, - GtkDirectionType dir) -{ - g_return_val_if_fail (button, NULL); - - if (!button->settings) - goto out; - - switch (button->type) { - case WACOM_TABLET_BUTTON_TYPE_NORMAL: - return get_tablet_button_label_normal (device, button); - break; - case WACOM_TABLET_BUTTON_TYPE_RING: - case WACOM_TABLET_BUTTON_TYPE_STRIP: - return get_tablet_button_label_touch (device, button, dir); - break; - case WACOM_TABLET_BUTTON_TYPE_HARDCODED: - default: - break; - } -out: - return g_strdup (button->name); -} - -static gchar* -get_tablet_button_class_name (GsdWacomTabletButton *tablet_button, - GtkDirectionType dir) -{ - gchar *id; - gchar c; - - id = tablet_button->id; - switch (tablet_button->type) { - case WACOM_TABLET_BUTTON_TYPE_RING: - if (id[0] == 'l') /* left-ring */ - return g_strdup_printf ("Ring%s", (dir == GTK_DIR_UP ? "CCW" : "CW")); - if (id[0] == 'r') /* right-ring */ - return g_strdup_printf ("Ring2%s", (dir == GTK_DIR_UP ? "CCW" : "CW")); - g_warning ("Unknown ring type '%s'", id); - return NULL; - break; - case WACOM_TABLET_BUTTON_TYPE_STRIP: - if (id[0] == 'l') /* left-strip */ - return g_strdup_printf ("Strip%s", (dir == GTK_DIR_UP ? "Up" : "Down")); - if (id[0] == 'r') /* right-strip */ - return g_strdup_printf ("Strip2%s", (dir == GTK_DIR_UP ? "Up" : "Down")); - g_warning ("Unknown strip type '%s'", id); - return NULL; - break; - case WACOM_TABLET_BUTTON_TYPE_NORMAL: - case WACOM_TABLET_BUTTON_TYPE_HARDCODED: - c = get_last_char (id); - return g_strdup_printf ("%c", g_ascii_toupper (c)); - break; - default: - g_warning ("Unknown button type '%s'", id); - break; - } - - return NULL; -} - -static gchar* -get_tablet_button_id_name (GsdWacomTabletButton *tablet_button, - GtkDirectionType dir) -{ - gchar *id; - gchar c; - - id = tablet_button->id; - switch (tablet_button->type) { - case WACOM_TABLET_BUTTON_TYPE_RING: - return g_strconcat (id, (dir == GTK_DIR_UP ? "-ccw" : "-cw"), NULL); - break; - case WACOM_TABLET_BUTTON_TYPE_STRIP: - return g_strconcat (id, (dir == GTK_DIR_UP ? "-up" : "-down"), NULL); - break; - case WACOM_TABLET_BUTTON_TYPE_NORMAL: - case WACOM_TABLET_BUTTON_TYPE_HARDCODED: - c = get_last_char (id); - return g_strdup_printf ("%c", g_ascii_toupper (c)); - break; - default: - g_warning ("Unknown button type '%s'", id); - break; - } - - return NULL; -} - -static gint -get_elevator_current_mode (GsdWacomOSDWindow *osd_window, - GsdWacomTabletButton *elevator_button) -{ - GList *list, *l; - gint mode; - - mode = 1; - /* Search in the list of buttons the corresponding - * mode-switch button and get the current mode - */ - list = gsd_wacom_device_get_buttons (osd_window->priv->pad); - for (l = list; l != NULL; l = l->next) { - GsdWacomTabletButton *tablet_button = l->data; - - if (tablet_button->type != WACOM_TABLET_BUTTON_TYPE_HARDCODED) - continue; - if (elevator_button->group_id != tablet_button->group_id) - continue; - mode = gsd_wacom_device_get_current_mode (osd_window->priv->pad, - tablet_button->group_id); - break; - } - g_list_free (list); - - return mode; -} - -static void -redraw_window (GsdWacomOSDWindow *self) -{ - GdkWindow *window; - - window = gtk_widget_get_window (GTK_WIDGET (self)); - if (window) - gdk_window_invalidate_rect (window, NULL, FALSE); -} - -static GsdWacomOSDButton * -gsd_wacom_osd_window_add_button_with_dir (GsdWacomOSDWindow *osd_window, - GsdWacomTabletButton *tablet_button, - GtkDirectionType dir) -{ - GsdWacomOSDButton *osd_button; - gchar *str; - - str = get_tablet_button_id_name (tablet_button, dir); - osd_button = gsd_wacom_osd_button_new (GTK_WIDGET (osd_window), str); - g_free (str); - - str = get_tablet_button_class_name (tablet_button, dir); - gsd_wacom_osd_button_set_class (osd_button, str); - g_free (str); - - str = get_tablet_button_label (osd_window->priv->pad, tablet_button, dir); - gsd_wacom_osd_button_set_label (osd_button, str); - g_free (str); - - gsd_wacom_osd_button_set_button_type (osd_button, tablet_button->type); - gsd_wacom_osd_button_set_position (osd_button, tablet_button->pos); - osd_window->priv->buttons = g_list_append (osd_window->priv->buttons, osd_button); - - return osd_button; -} - -static void -gsd_wacom_osd_window_add_tablet_button (GsdWacomOSDWindow *osd_window, - GsdWacomTabletButton *tablet_button) -{ - GsdWacomOSDButton *osd_button; - gint mode; - - switch (tablet_button->type) { - case WACOM_TABLET_BUTTON_TYPE_NORMAL: - case WACOM_TABLET_BUTTON_TYPE_HARDCODED: - osd_button = gsd_wacom_osd_window_add_button_with_dir (osd_window, - tablet_button, - 0); - gsd_wacom_osd_button_set_visible (osd_button, TRUE); - break; - case WACOM_TABLET_BUTTON_TYPE_RING: - case WACOM_TABLET_BUTTON_TYPE_STRIP: - mode = get_elevator_current_mode (osd_window, tablet_button) - 1; - - /* Add 2 buttons per elevator, one "Up"... */ - osd_button = gsd_wacom_osd_window_add_button_with_dir (osd_window, - tablet_button, - GTK_DIR_UP); - gsd_wacom_osd_button_set_visible (osd_button, tablet_button->idx == mode); - - /* ... and one "Down" */ - osd_button = gsd_wacom_osd_window_add_button_with_dir (osd_window, - tablet_button, - GTK_DIR_DOWN); - gsd_wacom_osd_button_set_visible (osd_button, tablet_button->idx == mode); - - break; - default: - g_warning ("Unknown button type"); - break; - } -} - -static char * -get_regular_mode_message (GsdWacomOSDWindow *osd_window) -{ - const gchar *name; - gchar *message; - - name = gsd_wacom_device_get_name (osd_window->priv->pad); - message = g_strdup_printf ("<big><b>%s</b></big>\n<span foreground=\"%s\">%s</span>", - name, INACTIVE_COLOR, _("(press any key to exit)")); - - return message; -} - -static char * -get_edition_mode_message (GsdWacomOSDWindow *osd_window) -{ - return g_strdup_printf ("<big><b>%s</b></big>\n<span foreground=\"%s\">%s</span>", - _("Push a button to configure"), INACTIVE_COLOR, _("(Esc to cancel)")); -} - -static void -close_editor (GsdWacomOSDWindow *self) -{ - if (self->priv->current_button) - self->priv->current_button->priv->visible = TRUE; - - gtk_widget_hide (self->priv->editor); - self->priv->current_button = NULL; -} - -static void -edition_mode_changed (GsdWacomOSDWindow *self) -{ - if (self->priv->edition_mode) - gsd_wacom_osd_window_set_message (self, self->priv->edition_mode_message); - else { - gsd_wacom_osd_window_set_message (self, self->priv->regular_mode_message); - - close_editor (self); - } - - redraw_window (self); -} - -static void -on_change_mode_button_clicked (GtkButton *button, - GsdWacomOSDWindow *window) -{ - window->priv->edition_mode = !window->priv->edition_mode; - - edition_mode_changed (window); -} - -static void -osd_window_set_cursor (GsdWacomOSDWindow *window, GdkCursorType cursor_type) -{ - GdkCursor *cursor; - GdkWindow *gdk_window; - - gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); - cursor = gdk_cursor_new (cursor_type); - gdk_window_set_cursor (gdk_window, cursor); - g_object_unref (cursor); -} - -static void -show_cursor (GsdWacomOSDWindow *window) -{ - osd_window_set_cursor (window, GDK_LEFT_PTR); -} - -static void -hide_cursor (GsdWacomOSDWindow *window) -{ - osd_window_set_cursor (window, GDK_BLANK_CURSOR); -} - -static gboolean -cursor_timeout_source_func (gpointer data) -{ - GsdWacomOSDWindow *window = GSD_WACOM_OSD_WINDOW (data); - hide_cursor (window); - window->priv->cursor_timeout = 0; - return G_SOURCE_REMOVE; -} - -static void -cursor_timeout_stop (GsdWacomOSDWindow *window) -{ - if (window->priv->cursor_timeout != 0) - g_source_remove (window->priv->cursor_timeout); - window->priv->cursor_timeout = 0; -} - -static gboolean -gsd_wacom_osd_window_motion_notify_event (GtkWidget *widget, - GdkEventMotion *event) -{ - GsdWacomOSDWindow *window; - GdkInputSource source; - - window = GSD_WACOM_OSD_WINDOW (widget); - - source = gdk_device_get_source (event->device); - if (source != GDK_SOURCE_MOUSE) - return FALSE; - - show_cursor (window); - cursor_timeout_stop (window); - window->priv->cursor_timeout = g_timeout_add_seconds (CURSOR_HIDE_TIMEOUT, - cursor_timeout_source_func, - window); - g_source_set_name_by_id (window->priv->cursor_timeout, "[gnome-settings-daemon] cursor_timeout_source_func"); - - return FALSE; -} - -/* - * Returns the rotation to apply a device to get a representation relative to - * the current rotation of the output. - * (This function is _not_ the same as in gsd-wacom-manager.c) - */ -static GsdWacomRotation -display_relative_rotation (GsdWacomRotation device_rotation, - GsdWacomRotation output_rotation) -{ - GsdWacomRotation rotations[] = { GSD_WACOM_ROTATION_HALF, - GSD_WACOM_ROTATION_CW, - GSD_WACOM_ROTATION_NONE, - GSD_WACOM_ROTATION_CCW }; - guint i; - - if (device_rotation == output_rotation) - return GSD_WACOM_ROTATION_NONE; - - if (output_rotation == GSD_WACOM_ROTATION_NONE) - return device_rotation; - - for (i = 0; i < G_N_ELEMENTS (rotations); i++) { - if (device_rotation == rotations[i]) - break; - } - - if (output_rotation == GSD_WACOM_ROTATION_HALF) - return rotations[(i + G_N_ELEMENTS (rotations) - 2) % G_N_ELEMENTS (rotations)]; - - if (output_rotation == GSD_WACOM_ROTATION_CW) - return rotations[(i + 1) % G_N_ELEMENTS (rotations)]; - - if (output_rotation == GSD_WACOM_ROTATION_CCW) - return rotations[(i + G_N_ELEMENTS (rotations) - 1) % G_N_ELEMENTS (rotations)]; - - /* fallback */ - return GSD_WACOM_ROTATION_NONE; -} - -static void -grab_keyboard (GsdWacomOSDWindow *self) -{ - GdkDevice *kbd = NULL; - GdkWindow *gdk_window; - GdkDisplay *display; - GdkDeviceManager *device_manager; - GList *devices, *l; - - gdk_window = gtk_widget_get_window (GTK_WIDGET (self)); - display = gtk_widget_get_display (GTK_WIDGET (self)); - device_manager = gdk_display_get_device_manager (display); - devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER); - - for (l = devices; l != NULL; l = l->next) { - GdkDevice *current_device; - - current_device = l->data; - if (gdk_device_get_source (current_device) == GDK_SOURCE_KEYBOARD) { - kbd = current_device; - break; - } - } - g_list_free (devices); - - g_assert (kbd); - - gdk_device_grab (kbd, gdk_window, GDK_OWNERSHIP_WINDOW, FALSE, - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, - NULL, GDK_CURRENT_TIME); -} - -static void -gsd_wacom_osd_window_show (GtkWidget *widget) -{ - GTK_WIDGET_CLASS (gsd_wacom_osd_window_parent_class)->show (widget); - - grab_keyboard (GSD_WACOM_OSD_WINDOW (widget)); -} - -static void -on_button_edited (GsdWacomButtonEditor *editor, - GsdWacomOSDWindow *self) -{ - GsdWacomTabletButton *button; - GtkDirectionType dir; - char *str; - - button = gsd_wacom_button_editor_get_button (editor, &dir); - - if (button == NULL || self->priv->current_button == NULL) - return; - - str = get_tablet_button_label (self->priv->pad, button, dir); - gsd_wacom_osd_button_set_label (self->priv->current_button, str); - g_free (str); - - gsd_wacom_osd_button_redraw (self->priv->current_button); -} - -static void -on_button_editing_done (GtkWidget *editor, - GsdWacomOSDWindow *self) -{ - close_editor (self); - redraw_window (self); - grab_keyboard (self); -} - -static gboolean -on_get_child_position (GtkOverlay *overlay, - GtkWidget *widget, - GdkRectangle *allocation, - GsdWacomOSDWindow *self) -{ - GsdWacomOSDButton *button; - GtkRequisition requisition; - GsdWacomTabletButtonPos position; - - button = self->priv->current_button; - - if (button == NULL) - return FALSE; - - gtk_widget_get_preferred_size (widget, NULL, &requisition); - - allocation->x = button->priv->label_x; - allocation->y = button->priv->label_y; - allocation->width = requisition.width; - allocation->height = requisition.height; - - position = get_actual_position (button->priv->position, self->priv->rotation); - - if (position == WACOM_TABLET_BUTTON_POS_LEFT) { - allocation->y -= requisition.height / 2.0; - } else if (position == WACOM_TABLET_BUTTON_POS_RIGHT) { - allocation->x -= requisition.width; - allocation->y -= requisition.height / 2.0; - } else if (position == WACOM_TABLET_BUTTON_POS_BOTTOM) { - allocation->x -= requisition.width / 2.0; - allocation->y -= requisition.height; - } else if (position == WACOM_TABLET_BUTTON_POS_TOP) { - allocation->x -= requisition.width / 2.0; - } - - return TRUE; -} - -static void -gsd_wacom_osd_window_realized (GtkWidget *widget, - gpointer data) -{ - GsdWacomOSDWindow *osd_window = GSD_WACOM_OSD_WINDOW (widget); - GdkWindow *gdk_window; - GdkRGBA transparent; - GdkScreen *screen; - gint monitor; - gboolean status; - - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - g_return_if_fail (GSD_IS_WACOM_DEVICE (osd_window->priv->pad)); - - if (!gtk_widget_get_realized (widget)) - return; - - screen = gtk_widget_get_screen (widget); - gdk_window = gtk_widget_get_window (widget); - - transparent.red = transparent.green = transparent.blue = 0.0; - transparent.alpha = BACK_OPACITY; - gdk_window_set_background_rgba (gdk_window, &transparent); - - hide_cursor (osd_window); - - /* Determine the monitor for that device and set appropriate fullscreen mode*/ - monitor = gsd_wacom_device_get_display_monitor (osd_window->priv->pad); - - if (monitor == GSD_WACOM_SET_ALL_MONITORS) { - /* Pick a monitor for the OSD to appear */ - monitor = gdk_screen_get_primary_monitor (screen); - } - - gdk_screen_get_monitor_geometry (screen, monitor, &osd_window->priv->screen_area); - osd_window->priv->monitor_area = osd_window->priv->screen_area; - gdk_window_set_fullscreen_mode (gdk_window, GDK_FULLSCREEN_ON_CURRENT_MONITOR); - - gtk_window_set_default_size (GTK_WINDOW (osd_window), - osd_window->priv->screen_area.width, - osd_window->priv->screen_area.height); - - status = get_image_size (gsd_wacom_device_get_layout_path (osd_window->priv->pad), - &osd_window->priv->tablet_area.width, - &osd_window->priv->tablet_area.height); - if (status == FALSE) - osd_window->priv->tablet_area = osd_window->priv->monitor_area; - - /* Position the window at its expected postion before moving - * to fullscreen, so the window will be on the right monitor. - */ - gtk_window_move (GTK_WINDOW (osd_window), - osd_window->priv->screen_area.x, - osd_window->priv->screen_area.y); - - gtk_window_fullscreen (GTK_WINDOW (osd_window)); - gtk_window_set_keep_above (GTK_WINDOW (osd_window), TRUE); -} - -static gboolean -gsd_wacom_osd_window_key_release_event (GtkWidget *widget, - GdkEventKey *event) -{ - GsdWacomOSDWindow *osd_window; - osd_window = GSD_WACOM_OSD_WINDOW (widget); - - if (event->type != GDK_KEY_RELEASE) - goto out; - - if (osd_window->priv->edition_mode) { - if (event->keyval == GDK_KEY_Escape && !gtk_widget_get_visible (osd_window->priv->editor)) - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osd_window->priv->change_mode_button), - FALSE); - - goto out; - } - - gtk_widget_destroy (widget); - - out: - GTK_WIDGET_CLASS (gsd_wacom_osd_window_parent_class)->key_release_event (widget, event); - - return FALSE; -} - -static void -gsd_wacom_osd_window_set_device (GsdWacomOSDWindow *osd_window, - GsdWacomDevice *device) -{ - GsdWacomRotation device_rotation; - GsdWacomRotation output_rotation; - GSettings *settings; - GList *list, *l; - - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - g_return_if_fail (GSD_IS_WACOM_DEVICE (device)); - - /* If we had a layout previously handled, get rid of it */ - if (osd_window->priv->handle) - g_object_unref (osd_window->priv->handle); - osd_window->priv->handle = NULL; - - /* Bind the device with the OSD window */ - if (osd_window->priv->pad) - g_object_weak_unref (G_OBJECT(osd_window->priv->pad), - (GWeakNotify) gtk_widget_destroy, - osd_window); - osd_window->priv->pad = device; - g_object_weak_ref (G_OBJECT(osd_window->priv->pad), - (GWeakNotify) gtk_widget_destroy, - osd_window); - - /* Capture current rotation, we do not update that later, OSD window is meant to be short lived */ - settings = gsd_wacom_device_get_settings (osd_window->priv->pad); - device_rotation = g_settings_get_enum (settings, ROTATION_KEY); - output_rotation = gsd_wacom_device_get_display_rotation (osd_window->priv->pad); - osd_window->priv->rotation = display_relative_rotation (device_rotation, output_rotation); - - /* Create the buttons */ - list = gsd_wacom_device_get_buttons (device); - for (l = list; l != NULL; l = l->next) { - GsdWacomTabletButton *tablet_button = l->data; - - gsd_wacom_osd_window_add_tablet_button (osd_window, tablet_button); - } - g_list_free (list); - - g_clear_pointer (&osd_window->priv->regular_mode_message, g_free); - osd_window->priv->regular_mode_message = get_regular_mode_message (osd_window); - -} - -GsdWacomDevice * -gsd_wacom_osd_window_get_device (GsdWacomOSDWindow *osd_window) -{ - g_return_val_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window), NULL); - - return osd_window->priv->pad; -} - -void -gsd_wacom_osd_window_set_message (GsdWacomOSDWindow *osd_window, - const gchar *str) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - - g_free (osd_window->priv->message); - osd_window->priv->message = g_strdup (str); -} - -const char * -gsd_wacom_osd_window_get_message (GsdWacomOSDWindow *osd_window) -{ - g_return_val_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window), NULL); - - return osd_window->priv->message; -} - -static void -gsd_wacom_osd_window_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GsdWacomOSDWindow *osd_window; - - osd_window = GSD_WACOM_OSD_WINDOW (object); - - switch (prop_id) { - case PROP_OSD_WINDOW_MESSAGE: - gsd_wacom_osd_window_set_message (osd_window, g_value_get_string (value)); - break; - case PROP_OSD_WINDOW_EDITION_MODE: - osd_window->priv->edition_mode = g_value_get_boolean (value); - break; - case PROP_OSD_WINDOW_GSD_WACOM_DEVICE: - gsd_wacom_osd_window_set_device (osd_window, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gsd_wacom_osd_window_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GsdWacomOSDWindow *osd_window; - - osd_window = GSD_WACOM_OSD_WINDOW (object); - - switch (prop_id) { - case PROP_OSD_WINDOW_MESSAGE: - g_value_set_string (value, osd_window->priv->message); - break; - case PROP_OSD_WINDOW_EDITION_MODE: - g_value_set_boolean (value, osd_window->priv->edition_mode); - break; - case PROP_OSD_WINDOW_GSD_WACOM_DEVICE: - g_value_set_object (value, (GObject*) osd_window->priv->pad); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -void -gsd_wacom_osd_window_set_active (GsdWacomOSDWindow *osd_window, - GsdWacomTabletButton *button, - GtkDirectionType dir, - gboolean active) -{ - GsdWacomOSDWindowPrivate *priv; - GList *l; - gchar *id; - - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - g_return_if_fail (button != NULL); - - priv = osd_window->priv; - - if (priv->current_button) - priv->current_button->priv->visible = TRUE; - - id = get_tablet_button_id_name (button, dir); - for (l = priv->buttons; l != NULL; l = l->next) { - GsdWacomOSDButton *osd_button = l->data; - if (MATCH_ID (osd_button, id)) { - if (priv->edition_mode && button->type != WACOM_TABLET_BUTTON_TYPE_HARDCODED) - priv->current_button = osd_button; - else - gsd_wacom_osd_button_set_active (osd_button, active); - } - } - g_free (id); - - if (priv->edition_mode) { - if (priv->current_button) - priv->current_button->priv->visible = FALSE; - - if (button->type == WACOM_TABLET_BUTTON_TYPE_HARDCODED) - return; - - gtk_widget_hide (priv->editor); - gsd_wacom_button_editor_set_button (GSD_WACOM_BUTTON_EDITOR (priv->editor), button, dir); - gtk_widget_show (priv->editor); - - redraw_window (osd_window); - - return; - } -} - -void -gsd_wacom_osd_window_set_mode (GsdWacomOSDWindow *osd_window, - gint group_id, - gint mode) -{ - GList *list, *l; - - list = gsd_wacom_device_get_buttons (osd_window->priv->pad); - for (l = list; l != NULL; l = l->next) { - GsdWacomTabletButton *tablet_button = l->data; - GList *l2; - gchar *id_up, *id_down; - - if (tablet_button->type != WACOM_TABLET_BUTTON_TYPE_STRIP && - tablet_button->type != WACOM_TABLET_BUTTON_TYPE_RING) - continue; - if (tablet_button->group_id != group_id) - continue; - - id_up = get_tablet_button_id_name (tablet_button, GTK_DIR_UP); - id_down = get_tablet_button_id_name (tablet_button, GTK_DIR_DOWN); - - for (l2 = osd_window->priv->buttons; l2 != NULL; l2 = l2->next) { - GsdWacomOSDButton *osd_button = l2->data; - gboolean visible = (tablet_button->idx == mode - 1); - - if (MATCH_ID (osd_button, id_up) || MATCH_ID (osd_button, id_down)) { - gsd_wacom_osd_button_set_visible (osd_button, visible); - - if (osd_window->priv->current_button) { - gchar *current_id; - GtkDirectionType dir; - - gsd_wacom_button_editor_get_button (GSD_WACOM_BUTTON_EDITOR (osd_window->priv->editor), &dir); - current_id = get_tablet_button_id_name (tablet_button, dir); - - if (MATCH_ID (osd_button, current_id) && visible) { - osd_window->priv->current_button = osd_button; - - gtk_widget_hide (osd_window->priv->editor); - gsd_wacom_button_editor_set_button (GSD_WACOM_BUTTON_EDITOR (osd_window->priv->editor), tablet_button, dir); - gtk_widget_show (osd_window->priv->editor); - } - } - - redraw_window (osd_window); - } - } - - g_free (id_up); - g_free (id_down); - - } - g_list_free (list); -} - -gboolean -gsd_wacom_osd_window_get_edition_mode (GsdWacomOSDWindow *osd_window) -{ - g_return_val_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window), FALSE); - - return osd_window->priv->edition_mode; -} - -void -gsd_wacom_osd_window_set_edition_mode (GsdWacomOSDWindow *osd_window, gboolean edition_mode) -{ - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (osd_window)); - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (osd_window->priv->change_mode_button), - edition_mode); -} - -GtkWidget * -gsd_wacom_osd_window_new (GsdWacomDevice *pad, - const gchar *message) -{ - GsdWacomOSDWindow *osd_window; - GdkScreen *screen; - GdkVisual *visual; - GtkWidget *button, *box, *overlay; - GtkStyleContext *style_context; - - osd_window = GSD_WACOM_OSD_WINDOW (g_object_new (GSD_TYPE_WACOM_OSD_WINDOW, - "type", GTK_WINDOW_POPUP, - "skip-pager-hint", TRUE, - "skip-taskbar-hint", TRUE, - "focus-on-map", TRUE, - "decorated", FALSE, - "deletable", FALSE, - "accept-focus", TRUE, - "wacom-device", pad, - "message", message, - NULL)); - - /* Must set the visual before realizing the window */ - gtk_widget_set_app_paintable (GTK_WIDGET (osd_window), TRUE); - screen = gdk_screen_get_default (); - visual = gdk_screen_get_rgba_visual (screen); - if (visual == NULL) - visual = gdk_screen_get_system_visual (screen); - gtk_widget_set_visual (GTK_WIDGET (osd_window), visual); - - osd_window->priv->editor = gsd_wacom_button_editor_new (); - g_signal_connect (osd_window->priv->editor, "button-edited", - G_CALLBACK (on_button_edited), - osd_window); - g_signal_connect (osd_window->priv->editor, "done-editing", - G_CALLBACK (on_button_editing_done), - osd_window); - - g_signal_connect (GTK_WIDGET (osd_window), "realize", - G_CALLBACK (gsd_wacom_osd_window_realized), - NULL); - - overlay = gtk_overlay_new (); - gtk_container_add (GTK_CONTAINER (osd_window), overlay); - - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_container_add (GTK_CONTAINER (overlay), box); - - gtk_overlay_add_overlay (GTK_OVERLAY (overlay), osd_window->priv->editor); - - button = gtk_toggle_button_new_with_label (_("Edit")); - g_object_set (button, "halign", GTK_ALIGN_CENTER, NULL); - - style_context = gtk_widget_get_style_context (button); - gtk_style_context_add_class (style_context, "osd"); - - gtk_box_pack_end (GTK_BOX (box), button, FALSE, FALSE, 12); - osd_window->priv->change_mode_button = button; - - gtk_widget_show (overlay); - gtk_widget_show (box); - gtk_widget_show (osd_window->priv->change_mode_button); - - g_signal_connect (osd_window->priv->change_mode_button, "clicked", - G_CALLBACK (on_change_mode_button_clicked), - osd_window); - - g_signal_connect (overlay, "get-child-position", - G_CALLBACK (on_get_child_position), - osd_window); - - osd_window->priv->regular_mode_message = get_regular_mode_message (osd_window); - - edition_mode_changed (osd_window); - - return GTK_WIDGET (osd_window); -} - -static void -gsd_wacom_osd_window_class_init (GsdWacomOSDWindowClass *klass) -{ - GObjectClass *gobject_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (klass); - widget_class = GTK_WIDGET_CLASS (klass); - - gobject_class->set_property = gsd_wacom_osd_window_set_property; - gobject_class->get_property = gsd_wacom_osd_window_get_property; - gobject_class->finalize = gsd_wacom_osd_window_finalize; - widget_class->draw = gsd_wacom_osd_window_draw; - widget_class->motion_notify_event = gsd_wacom_osd_window_motion_notify_event; - widget_class->show = gsd_wacom_osd_window_show; - widget_class->key_release_event = gsd_wacom_osd_window_key_release_event; - - g_object_class_install_property (gobject_class, - PROP_OSD_WINDOW_MESSAGE, - g_param_spec_string ("message", - "Window message", - "The message shown in the OSD window", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_OSD_WINDOW_GSD_WACOM_DEVICE, - g_param_spec_object ("wacom-device", - "Wacom device", - "The Wacom device represented by the OSD window", - GSD_TYPE_WACOM_DEVICE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_OSD_WINDOW_EDITION_MODE, - g_param_spec_boolean ("edition-mode", - "Edition mode", - "The edition mode of the OSD Window.", - FALSE, - G_PARAM_READWRITE)); - - - g_type_class_add_private (klass, sizeof (GsdWacomOSDWindowPrivate)); -} - -static void -gsd_wacom_osd_window_init (GsdWacomOSDWindow *osd_window) -{ - GtkSettings *settings; - osd_window->priv = GSD_WACOM_OSD_WINDOW_GET_PRIVATE (osd_window); - osd_window->priv->cursor_timeout = 0; - gtk_widget_add_events (GTK_WIDGET (osd_window), GDK_POINTER_MOTION_MASK); - - osd_window->priv->edition_mode = FALSE; - - osd_window->priv->edition_mode_message = get_edition_mode_message (osd_window); - - settings = gtk_settings_get_default (); - g_object_set (G_OBJECT (settings), "gtk-application-prefer-dark-theme", TRUE, NULL); -} - -static void -gsd_wacom_osd_window_finalize (GObject *object) -{ - GsdWacomOSDWindow *osd_window; - GsdWacomOSDWindowPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSD_IS_WACOM_OSD_WINDOW (object)); - - osd_window = GSD_WACOM_OSD_WINDOW (object); - g_return_if_fail (osd_window->priv != NULL); - - priv = osd_window->priv; - cursor_timeout_stop (osd_window); - g_clear_object (&priv->handle); - g_clear_pointer (&priv->message, g_free); - g_clear_pointer (&priv->regular_mode_message, g_free); - g_clear_pointer (&priv->edition_mode_message, g_free); - - if (priv->pad) { - g_object_weak_unref (G_OBJECT(priv->pad), - (GWeakNotify) gtk_widget_destroy, - osd_window); - } - - if (priv->buttons) { - g_list_free_full (priv->buttons, g_object_unref); - priv->buttons = NULL; - } - - G_OBJECT_CLASS (gsd_wacom_osd_window_parent_class)->finalize (object); -} diff --git a/plugins/wacom/gsd-wacom-osd-window.h b/plugins/wacom/gsd-wacom-osd-window.h deleted file mode 100644 index 36b778b3..00000000 --- a/plugins/wacom/gsd-wacom-osd-window.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. - * - * Author: Olivier Fourdan <ofourdan@redhat.com> - * - */ - -#ifndef __GSD_WACOM_OSD_WINDOW_H -#define __GSD_WACOM_OSD_WINDOW_H - -#include <gtk/gtk.h> -#include <glib-object.h> -#include "gsd-wacom-device.h" - -#define GSD_TYPE_WACOM_OSD_WINDOW (gsd_wacom_osd_window_get_type ()) -#define GSD_WACOM_OSD_WINDOW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_WACOM_OSD_WINDOW, GsdWacomOSDWindow)) -#define GSD_WACOM_OSD_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_WACOM_OSD_WINDOW, GsdWacomOSDWindowClass)) -#define GSD_IS_WACOM_OSD_WINDOW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_WACOM_OSD_WINDOW)) -#define GSD_IS_WACOM_OSD_WINDOW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_WACOM_OSD_WINDOW)) -#define GSD_WACOM_OSD_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_WACOM_OSD_WINDOW, GsdWacomOSDWindowClass)) - -typedef struct GsdWacomOSDWindowPrivate GsdWacomOSDWindowPrivate; - -typedef struct -{ - GtkWindow window; - GsdWacomOSDWindowPrivate *priv; -} GsdWacomOSDWindow; - -typedef struct -{ - GtkWindowClass parent_class; -} GsdWacomOSDWindowClass; - -GType gsd_wacom_osd_window_get_type (void) G_GNUC_CONST; -GsdWacomDevice * gsd_wacom_osd_window_get_device (GsdWacomOSDWindow *osd_window); -void gsd_wacom_osd_window_set_message (GsdWacomOSDWindow *osd_window, - const gchar *str); -const char * gsd_wacom_osd_window_get_message (GsdWacomOSDWindow *osd_window); -void gsd_wacom_osd_window_set_active (GsdWacomOSDWindow *osd_window, - GsdWacomTabletButton *button, - GtkDirectionType dir, - gboolean active); -void gsd_wacom_osd_window_set_mode (GsdWacomOSDWindow *osd_window, - gint group_id, - gint mode); -gboolean gsd_wacom_osd_window_get_edition_mode (GsdWacomOSDWindow *osd_window); -void gsd_wacom_osd_window_set_edition_mode (GsdWacomOSDWindow *osd_window, - gboolean edition_mode); -GtkWidget * gsd_wacom_osd_window_new (GsdWacomDevice *pad, - const gchar *message); - -#endif /* __GSD_WACOM_OSD_WINDOW_H */ diff --git a/plugins/wacom/list-wacom.c b/plugins/wacom/list-wacom.c deleted file mode 100644 index fefa1336..00000000 --- a/plugins/wacom/list-wacom.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (C) 2011 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 <http://www.gnu.org/licenses/>. - * - * Author: Bastien Nocera <hadess@hadess.net> - * - */ - -#include "config.h" - -#include <gtk/gtk.h> - -#include "gsd-wacom-device.h" -#include "gsd-device-manager.h" -#include "gsd-device-manager-x11.h" - -static gboolean fake_devices = FALSE; -static gboolean monitor_styli = FALSE; -static gboolean option_debug = FALSE; - -static char * -get_loc (GSettings *settings) -{ - char *path, *schema, *ret; - - g_return_val_if_fail (G_IS_SETTINGS (settings), NULL); - - g_object_get (G_OBJECT (settings), - "path", &path, - "schema-id", &schema, - NULL); - ret = g_strdup_printf ("schema-id: %s (path: %s)", schema, path); - g_free (schema); - g_free (path); - - return ret; -} - -static const char * -stylus_type_to_string (GsdWacomStylusType type) -{ - switch (type) { - case WACOM_STYLUS_TYPE_UNKNOWN: - return "Unknown"; - case WACOM_STYLUS_TYPE_GENERAL: - return "General"; - case WACOM_STYLUS_TYPE_INKING: - return "Inking"; - case WACOM_STYLUS_TYPE_AIRBRUSH: - return "Airbrush"; - case WACOM_STYLUS_TYPE_CLASSIC: - return "Classic"; - case WACOM_STYLUS_TYPE_MARKER: - return "Marker"; - case WACOM_STYLUS_TYPE_STROKE: - return "Stroke"; - case WACOM_STYLUS_TYPE_PUCK: - return "Puck"; - default: - g_assert_not_reached (); - } - return NULL; -} - -static const char * -button_type_to_string (GsdWacomTabletButtonType type) -{ - switch (type) { - case WACOM_TABLET_BUTTON_TYPE_NORMAL: - return "normal"; - case WACOM_TABLET_BUTTON_TYPE_STRIP: - return "touch-strip"; - case WACOM_TABLET_BUTTON_TYPE_RING: - return "touch-ring"; - case WACOM_TABLET_BUTTON_TYPE_HARDCODED: - return "hard-coded"; - default: - g_assert_not_reached (); - } -} - -#define BOOL_AS_STR(x) (x ? "yes" : "no") - -static void -print_stylus (GsdWacomStylus *stylus, - gboolean is_current) -{ - GsdWacomDevice *device; - char *loc; - - device = gsd_wacom_stylus_get_device (stylus); - - g_print ("\t%sStylus: '%s' (Type: %s, ID: 0x%x)\n", - is_current ? "*** " : "", - gsd_wacom_stylus_get_name (stylus), - stylus_type_to_string (gsd_wacom_stylus_get_stylus_type (stylus)), - gsd_wacom_stylus_get_id (stylus)); - - loc = get_loc (gsd_wacom_stylus_get_settings (stylus)); - g_print ("\t\tSettings: %s\n", loc); - g_free (loc); - - g_print ("\t\tIcon name: %s\n", gsd_wacom_stylus_get_icon_name (stylus)); - - if (gsd_wacom_device_get_device_type (device) == WACOM_TYPE_STYLUS) { - int num_buttons; - char *buttons; - - g_print ("\t\tHas Eraser: %s\n", BOOL_AS_STR(gsd_wacom_stylus_get_has_eraser (stylus))); - - num_buttons = gsd_wacom_stylus_get_num_buttons (stylus); - if (num_buttons < 0) - num_buttons = 2; - if (num_buttons > 0) - buttons = g_strdup_printf ("%d buttons", num_buttons); - else - buttons = g_strdup ("no button"); - g_print ("\t\tButtons: %s\n", buttons); - g_free (buttons); - } -} - -static void -print_buttons (GsdWacomDevice *device) -{ - GList *buttons, *l; - - buttons = gsd_wacom_device_get_buttons (device); - if (buttons == NULL) - return; - - for (l = buttons; l != NULL; l = l->next) { - GsdWacomTabletButton *button = l->data; - gboolean has_led; - - g_print ("\tButton: %s (%s)\n", button->name, button->id); - g_print ("\t\tType: %s\n", button_type_to_string (button->type)); - if (button->group_id > 0) { - g_print ("\t\tGroup: %d", button->group_id); - if (button->idx >= 0) - g_print (" Index: %d\n", button->idx); - else - g_print ("\n"); - } - has_led = (button->type == WACOM_TABLET_BUTTON_TYPE_HARDCODED && button->status_led != GSD_WACOM_NO_LED); - if (has_led || button->has_oled) - g_print ("\t\tHas LED: %s Has OLED: %s\n", BOOL_AS_STR(has_led), BOOL_AS_STR(button->has_oled)); - if (button->settings) { - char *loc; - loc = get_loc (button->settings); - g_print ("\t\tSettings: %s\n", loc); - g_free (loc); - } - } - g_list_free (buttons); -} - -static void -last_stylus_changed (GsdWacomDevice *device, - GParamSpec *pspec, - gpointer user_data) -{ - GsdWacomStylus *stylus; - - g_object_get (device, "last-stylus", &stylus, NULL); - - g_print ("Stylus changed for device '%s'\n", - gsd_wacom_device_get_tool_name (device)); - - print_stylus (stylus, TRUE); -} - -static char ** -get_edid (GsdWacomDevice *device) -{ - GdkDevice *gdk_device; - GsdDevice *gsd_device; - GSettings *gsd_settings; - char **edid; - - gdk_device = gsd_wacom_device_get_gdk_device (device); - if (!gdk_device) - goto bail; - - gsd_device = gsd_x11_device_manager_lookup_gdk_device (GSD_X11_DEVICE_MANAGER (gsd_device_manager_get ()), - gdk_device); - if (!gsd_device) - goto bail; - - gsd_settings = gsd_device_get_settings (gsd_device); - g_object_unref (gsd_device); - - edid = g_settings_get_strv (gsd_settings, "display"); - g_object_unref (gsd_settings); - - return edid; - -bail: - return g_strsplit (",,", ",", 3); -} - -static void -list_devices (GList *devices) -{ - GList *l; - - for (l = devices; l ; l = l->next) { - GsdWacomDevice *device; - GsdWacomDeviceType type; - GSettings *settings; - char *loc, **edid; - - device = l->data; - - g_signal_connect (G_OBJECT (device), "notify::last-stylus", - G_CALLBACK (last_stylus_changed), NULL); - - g_print ("Device '%s' (type: %s)\n", - gsd_wacom_device_get_name (device), - gsd_wacom_device_type_to_string (gsd_wacom_device_get_device_type (device))); - g_print ("\tReversible: %s\n", BOOL_AS_STR (gsd_wacom_device_reversible (device))); - g_print ("\tScreen Tablet: %s\n", BOOL_AS_STR (gsd_wacom_device_is_screen_tablet (device))); - g_print ("\tIntegrated Device: %s\n", BOOL_AS_STR (gsd_wacom_device_is_isd (device))); - g_print ("\tUnknown (fallback) device: %s\n", BOOL_AS_STR(gsd_wacom_device_is_fallback (device))); - - settings = gsd_wacom_device_get_settings (device); - loc = get_loc (settings); - g_print ("\tGeneric settings: %s\n", loc); - g_free (loc); - - edid = get_edid (device); - if (!edid || g_strv_length (edid) != 3) - g_warning ("Invalid display EDID set for device"); - else { - if (*edid[0] == '\0' && *edid[1] == '\0' && *edid[2] == '\0') - g_print ("\tDisplay EDID: unset\n"); - else - g_print ("\tDisplay EDID: '%s', '%s', '%s'\n", edid[0], edid[1], edid[2]); - } - g_clear_pointer (&edid, g_strfreev); - - type = gsd_wacom_device_get_device_type (device); - if (type == WACOM_TYPE_STYLUS || - type == WACOM_TYPE_ERASER) { - GList *styli, *j; - GsdWacomStylus *current_stylus; - - g_object_get (device, "last-stylus", ¤t_stylus, NULL); - - styli = gsd_wacom_device_list_styli (device); - for (j = styli; j; j = j->next) { - GsdWacomStylus *stylus; - - stylus = j->data; - print_stylus (stylus, current_stylus == stylus); - } - g_list_free (styli); - } - - print_buttons (device); - - if (monitor_styli == FALSE) - g_object_unref (device); - } - g_list_free (devices); -} - -static void -list_actual_devices (void) -{ - GdkDeviceManager *mgr; - GList *list, *l, *devices; - - mgr = gdk_display_get_device_manager (gdk_display_get_default ()); - - list = gdk_device_manager_list_devices (mgr, GDK_DEVICE_TYPE_SLAVE); - devices = NULL; - for (l = list; l ; l = l->next) { - GsdWacomDevice *device; - - device = gsd_wacom_device_new (l->data); - if (gsd_wacom_device_get_device_type (device) == WACOM_TYPE_INVALID) { - g_object_unref (device); - continue; - } - - devices = g_list_prepend (devices, device); - } - g_list_free (list); - - list_devices (devices); -} - -static void -list_fake_devices (void) -{ - GList *devices; - - devices = gsd_wacom_device_create_fake_cintiq (); - list_devices (devices); - - devices = gsd_wacom_device_create_fake_bt (); - list_devices (devices); - - devices = gsd_wacom_device_create_fake_x201 (); - list_devices (devices); - - devices = gsd_wacom_device_create_fake_intuos4 (); - list_devices (devices); - - devices = gsd_wacom_device_create_fake_h610pro (); - list_devices (devices); -} - -int main (int argc, char **argv) -{ - GError *error = NULL; - GOptionContext *context; - const GOptionEntry entries[] = { - { "fake", 'f', 0, G_OPTION_ARG_NONE, &fake_devices, "Output fake devices", NULL }, - { "monitor", 'm', 0, G_OPTION_ARG_NONE, &monitor_styli, "Monitor changing styli", NULL }, - { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug, "Debug output", NULL }, - { NULL } - }; - - gtk_init (&argc, &argv); - - context = g_option_context_new ("- test parser functions"); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - - if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) { - g_print ("Option parsing failed: %s\n", error->message); - return 1; - } - - if (option_debug) - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); - - if (fake_devices == FALSE) - list_actual_devices (); - else - list_fake_devices (); - - if (monitor_styli) - gtk_main (); - - return 0; -} diff --git a/plugins/wacom/tablet-layout.css b/plugins/wacom/tablet-layout.css deleted file mode 100644 index 407edc7f..00000000 --- a/plugins/wacom/tablet-layout.css +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<svg version="1.1" xmlns="http://www.w3.org/2000/svg" - xmlns:xi="http://www.w3.org/2001/XInclude" - width="layout_width" - height="layout_height" > - <style type="text/css"> - .Leader { - stroke-width: .5 !important; - stroke: dark_color; - fill: none !important; - } - .Button { - stroke-width: .25; - stroke: inactive_color; - fill: inactive_color; - } - buttons_section - .Ring { - stroke-width: .5 !important; - stroke: dark_color !important; - fill: none !important; - } - .Leader { - fill: none !important; - } - .Label { - stroke: none !important; - stroke-width: .1 !important; - font-size: .1 !important; - fill: back_color !important; - } - .TouchStrip,.TouchRing { - stroke-width: .1 !important; - stroke: inactive_color !important; - fill: dark_color !important; - } - </style> - <xi:include href="layout_file" /> -</svg> diff --git a/plugins/wacom/test-osd-window.c b/plugins/wacom/test-osd-window.c deleted file mode 100644 index 8af895a6..00000000 --- a/plugins/wacom/test-osd-window.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2012 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 <http://www.gnu.org/licenses/>. - * - * Author: Olivier Fourdan <ofourdan@redhat.com> - * - */ - -#include "config.h" - -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include <dirent.h> -#include <glib/gi18n.h> -#include "gsd-wacom-osd-window.h" - -static gboolean option_debug = FALSE; - -static GsdWacomDevice * -search_pad_device (void) -{ - GdkDeviceManager *mgr; - GList *list, *l; - - mgr = gdk_display_get_device_manager (gdk_display_get_default ()); - list = gdk_device_manager_list_devices (mgr, GDK_DEVICE_TYPE_SLAVE); - for (l = list; l ; l = l->next) { - GsdWacomDevice *device; - - device = gsd_wacom_device_new (l->data); - if (gsd_wacom_device_get_device_type (device) == WACOM_TYPE_PAD) - return (device); - g_object_unref (device); - } - g_list_free (list); - - return NULL; -} - -static GsdWacomDevice * -create_fake_device (const char *tablet) -{ - GsdWacomDevice *device; - gchar *tool; - - tool = g_strdup_printf ("%s pad", tablet); - device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD, tablet, tool); - g_free (tool); - - return device; -} - -static gboolean -on_key_release_event(GtkWidget *widget, - GdkEventKey *event, - gpointer data) -{ - gtk_main_quit(); - - return FALSE; -} - -int main(int argc, char** argv) -{ - GtkWidget *widget; - GError *error = NULL; - GOptionContext *context; - GsdWacomDevice *device; - gchar *message; - gchar *tablet = NULL; - const GOptionEntry entries[] = { - { "tablet", 't', 0, G_OPTION_ARG_STRING, &tablet, "Name of the tablet to show", "<string>"}, - { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug, "Debug output", NULL }, - { NULL } - }; - - gtk_init (&argc, &argv); - - context = g_option_context_new ("- test functions"); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - g_option_context_add_group (context, gtk_get_option_group (TRUE)); - g_option_context_set_help_enabled (context, TRUE); - if (g_option_context_parse (context, &argc, &argv, &error) == FALSE) { - g_print ("%s\n", error->message); - return 1; - } - g_option_context_free (context); - - if (option_debug) - g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); - - if (tablet) - device = create_fake_device (tablet); - else - device = search_pad_device (); - - if (device == NULL) { - g_print ("No pad device found, consider using --tablet\n"); - return 1; - } - - if (gsd_wacom_device_get_layout_path (device) == NULL) { - g_print ("This device has not layout available in libwacom\n"); - return 1; - } - - message = g_strdup_printf ("<big><b>%s</b></big>\n<i>(Press a key to exit)</i>", - gsd_wacom_device_get_name (device)); - widget = gsd_wacom_osd_window_new (device, message); - g_free (message); - - g_signal_connect (widget, "key-release-event", - G_CALLBACK(on_key_release_event), NULL); - g_signal_connect (widget, "delete-event", - G_CALLBACK (gtk_main_quit), NULL); - g_signal_connect (widget, "unmap", - G_CALLBACK (gtk_main_quit), NULL); - - gtk_widget_show (widget); - gtk_main (); - - return 0; -} diff --git a/plugins/wacom/wacom.gresource.xml b/plugins/wacom/wacom.gresource.xml deleted file mode 100644 index 57ac2008..00000000 --- a/plugins/wacom/wacom.gresource.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<gresources> - <gresource prefix="/org/gnome/settings-daemon/plugins/wacom"> - <file>tablet-layout.css</file> - </gresource> -</gresources> - |