[gnome-settings-daemon] wacom: Add OLED handling for Intuos4



commit a6ed61b72b11cfbdfdcf5faeac49f40abbbf983c
Author: Przemo Firszt <przemo firszt eu>
Date:   Tue Oct 2 20:35:06 2012 +0100

    wacom: Add OLED handling for Intuos4
    
    https://bugzilla.gnome.org/show_bug.cgi?id=671072

 configure.ac                                       |    5 +-
 ...ings-daemon.peripherals.wacom.gschema.xml.in.in |    5 +
 plugins/wacom/Makefile.am                          |   17 ++-
 plugins/wacom/gsd-wacom-device.c                   |   37 +++-
 plugins/wacom/gsd-wacom-device.h                   |    1 +
 plugins/wacom/gsd-wacom-manager.c                  |   42 ++++-
 plugins/wacom/gsd-wacom-oled-helper.c              |  183 +++++++++++++++
 plugins/wacom/gsd-wacom-oled.c                     |  232 ++++++++++++++++++++
 plugins/wacom/gsd-wacom-oled.h                     |   38 ++++
 ...nome.settings-daemon.plugins.wacom.policy.in.in |   15 ++
 10 files changed, 556 insertions(+), 19 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9560898..af8b3e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,6 +53,7 @@ UPOWER_GLIB_REQUIRED_VERSION=0.9.1
 PA_REQUIRED_VERSION=2.0
 LIBWACOM_REQUIRED_VERSION=0.7
 LIBRSVG_REQUIRED_VERSION=2.36.2
+PANGO_REQUIRED_VERSION=1.20.0
 UPOWER_REQUIRED_VERSION=0.9.11
 IBUS_REQUIRED_VERSION=1.4.99
 GSETTINGS_DESKTOP_SCHEMAS_REQUIRED_VERSION=3.7.2.1
@@ -253,8 +254,8 @@ case $host_os in
       have_wacom=no
     else
       if test x$enable_gudev != xno; then
-        PKG_CHECK_MODULES(WACOM, [libwacom >= $LIBWACOM_REQUIRED_VERSION x11 xi xtst gudev-1.0 
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION xorg-wacom librsvg-2.0 >= $LIBRSVG_REQUIRED_VERSION 
libnotify >= $LIBNOTIFY_REQUIRED_VERSION
-])
+        PKG_CHECK_MODULES(WACOM, [libwacom >= $LIBWACOM_REQUIRED_VERSION x11 xi xtst gudev-1.0 
gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION xorg-wacom librsvg-2.0 >= $LIBRSVG_REQUIRED_VERSION 
libnotify >= $LIBNOTIFY_REQUIRED_VERSION pango >= $PANGO_REQUIRED_VERSION])
+        PKG_CHECK_MODULES(WACOM_OLED, [gudev-1.0])
       else
         AC_MSG_ERROR([GUdev is necessary to compile Wacom support])
       fi
diff --git a/data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in.in 
b/data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in.in
index a10e069..676bb9d 100644
--- a/data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in.in
+++ b/data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in.in
@@ -107,5 +107,10 @@
       <_summary>Key combinations for a touchring or touchstrip custom action</_summary>
       <_description>The keyboard shortcuts generated when a touchring or touchstrip is used for custom 
actions (up followed by down).</_description>
     </key>
+    <key name="oled-label" type="s">
+      <default>''</default>
+      <_summary>Button label for OLED display.</_summary>
+      <_description>Label will be rendered to OLED display belonging to the button</_description>
+    </key>
   </schema>
 </schemalist>
diff --git a/plugins/wacom/Makefile.am b/plugins/wacom/Makefile.am
index 2bc050c..817db69 100644
--- a/plugins/wacom/Makefile.am
+++ b/plugins/wacom/Makefile.am
@@ -8,6 +8,8 @@ libgsdwacom_la_SOURCES =        \
        gsd-wacom-manager.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
@@ -52,18 +54,27 @@ 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
 
-EXTRA_DIST = $(gsd_wacom_led_helper_SOURCES) wacom.gresource.xml tablet-layout.css
+EXTRA_DIST = $(gsd_wacom_led_helper_SOURCES) wacom.gresource.xml tablet-layout.css \
+            $(gsd_wacom_oled_helper_SOURCES)
 
 if HAVE_GUDEV
-libexec_PROGRAMS = gsd-wacom-led-helper
+libexec_PROGRAMS = gsd-wacom-led-helper gsd-wacom-oled-helper
 
 gsd_wacom_led_helper_LDFLAGS =                         \
        $(BACKLIGHT_HELPER_LIBS)                        \
        -lm
 
+gsd_wacom_oled_helper_LDFLAGS =                                \
+       $(WACOM_OLED_LIBS)                              \
+       -lm
+
 gsd_wacom_led_helper_CFLAGS =                          \
        $(BACKLIGHT_HELPER_CFLAGS)
+
+gsd_wacom_oled_helper_CFLAGS =                         \
+       $(WACOM_OLED_CFLAGS)
 else
 libexec_PROGRAMS =
 endif
@@ -78,6 +89,8 @@ gsd_test_wacom_SOURCES =      \
        gsd-wacom-manager.h     \
        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
diff --git a/plugins/wacom/gsd-wacom-device.c b/plugins/wacom/gsd-wacom-device.c
index bd58a78..e90371a 100644
--- a/plugins/wacom/gsd-wacom-device.c
+++ b/plugins/wacom/gsd-wacom-device.c
@@ -258,7 +258,8 @@ gsd_wacom_tablet_button_new (const char               *name,
                             GsdWacomTabletButtonPos   pos,
                             int                       group_id,
                             int                       idx,
-                            int                       status_led)
+                            int                       status_led,
+                            int                       has_oled)
 {
        GsdWacomTabletButton *ret;
 
@@ -277,6 +278,7 @@ gsd_wacom_tablet_button_new (const char               *name,
        ret->type = type;
        ret->pos = pos;
        ret->status_led = status_led;
+       ret->has_oled = has_oled;
 
        return ret;
 }
@@ -1080,7 +1082,8 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
                                                                           WACOM_TABLET_BUTTON_POS_LEFT,
                                                                           group,
                                                                           0,
-                                                                          GSD_WACOM_NO_LED));
+                                                                          GSD_WACOM_NO_LED,
+                                                                          0));
                } else {
                        for (i = 1; i <= num_modes; i++) {
                                name = g_strdup_printf (_("Left Ring Mode #%d"), i);
@@ -1092,7 +1095,8 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
                                                                                   
WACOM_TABLET_BUTTON_POS_LEFT,
                                                                                   group,
                                                                                   i - 1,
-                                                                                  GSD_WACOM_NO_LED));
+                                                                                  GSD_WACOM_NO_LED,
+                                                                                  0));
                                g_free (name);
                                g_free (id);
                        }
@@ -1109,7 +1113,8 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
                                                                           WACOM_TABLET_BUTTON_POS_RIGHT,
                                                                           group,
                                                                           0,
-                                                                          GSD_WACOM_NO_LED));
+                                                                          GSD_WACOM_NO_LED,
+                                                                          0));
                } else {
                        for (i = 1; i <= num_modes; i++) {
                                name = g_strdup_printf (_("Right Ring Mode #%d"), i);
@@ -1121,7 +1126,8 @@ gsd_wacom_device_add_ring_modes (WacomDevice      *wacom_device,
                                                                                   
WACOM_TABLET_BUTTON_POS_RIGHT,
                                                                                   group,
                                                                                   i - 1,
-                                                                                  GSD_WACOM_NO_LED));
+                                                                                  GSD_WACOM_NO_LED,
+                                                                                  0));
                                g_free (name);
                                g_free (id);
                        }
@@ -1160,7 +1166,8 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
                                                                           WACOM_TABLET_BUTTON_POS_LEFT,
                                                                           group,
                                                                           0,
-                                                                          GSD_WACOM_NO_LED));
+                                                                          GSD_WACOM_NO_LED,
+                                                                          0));
                } else {
                        for (i = 1; i <= num_modes; i++) {
                                name = g_strdup_printf (_("Left Touchstrip Mode #%d"), i);
@@ -1172,7 +1179,8 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
                                                                                   
WACOM_TABLET_BUTTON_POS_LEFT,
                                                                                   group,
                                                                                   i - 1,
-                                                                                  GSD_WACOM_NO_LED));
+                                                                                  GSD_WACOM_NO_LED,
+                                                                                  0));
                                g_free (name);
                                g_free (id);
                        }
@@ -1189,7 +1197,8 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
                                                                           WACOM_TABLET_BUTTON_POS_RIGHT,
                                                                           group,
                                                                           0,
-                                                                          GSD_WACOM_NO_LED));
+                                                                          GSD_WACOM_NO_LED,
+                                                                          0));
                } else {
                        for (i = 1; i <= num_modes; i++) {
                                name = g_strdup_printf (_("Right Touchstrip Mode #%d"), i);
@@ -1201,7 +1210,8 @@ gsd_wacom_device_add_strip_modes (WacomDevice      *wacom_device,
                                                                                   
WACOM_TABLET_BUTTON_POS_RIGHT,
                                                                                   group,
                                                                                   i - 1,
-                                                                                  GSD_WACOM_NO_LED));
+                                                                                  GSD_WACOM_NO_LED,
+                                                                                  0));
                                g_free (name);
                                g_free (id);
                        }
@@ -1259,6 +1269,7 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
        GList *l;
        guint num_buttons, i, button_num;
        char *name, *id;
+       gboolean has_oled;
 
        l = NULL;
        button_num = 1;
@@ -1275,6 +1286,8 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
 
                name = g_strdup_printf (button_str, button_num++);
                id = g_strdup_printf ("%s%c", button_str_id, i);
+               if (libwacom_get_button_flag (wacom_device, i) & WACOM_BUTTON_OLED)
+                       has_oled = TRUE;
                l = g_list_append (l, gsd_wacom_tablet_button_new (name,
                                                                   id,
                                                                   settings_path,
@@ -1282,7 +1295,8 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
                                                                   gsd_wacom_device_button_pos (flags),
                                                                   flags_to_group (flags),
                                                                   -1,
-                                                                  GSD_WACOM_NO_LED));
+                                                                  GSD_WACOM_NO_LED,
+                                                                  has_oled));
                g_free (name);
                g_free (id);
        }
@@ -1310,7 +1324,8 @@ gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
                                                                   gsd_wacom_device_button_pos (flags),
                                                                   flags_to_group (flags),
                                                                   -1,
-                                                                  status_led));
+                                                                  status_led,
+                                                                  FALSE));
                g_free (name);
                g_free (id);
        }
diff --git a/plugins/wacom/gsd-wacom-device.h b/plugins/wacom/gsd-wacom-device.h
index 335945f..3657e88 100644
--- a/plugins/wacom/gsd-wacom-device.h
+++ b/plugins/wacom/gsd-wacom-device.h
@@ -123,6 +123,7 @@ typedef struct
        GsdWacomTabletButtonPos   pos;
        int                       group_id, idx;
        int                       status_led;
+       int                       has_oled;
 } GsdWacomTabletButton;
 
 void                  gsd_wacom_tablet_button_free (GsdWacomTabletButton *button);
diff --git a/plugins/wacom/gsd-wacom-manager.c b/plugins/wacom/gsd-wacom-manager.c
index 8a3a426..51fa57c 100644
--- a/plugins/wacom/gsd-wacom-manager.c
+++ b/plugins/wacom/gsd-wacom-manager.c
@@ -49,6 +49,7 @@
 #include "gnome-settings-profile.h"
 #include "gsd-wacom-manager.h"
 #include "gsd-wacom-device.h"
+#include "gsd-wacom-oled.h"
 #include "gsd-wacom-osd-window.h"
 
 #define GSD_WACOM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_MANAGER, 
GsdWacomManagerPrivate))
@@ -68,9 +69,10 @@
 #define KEY_PRESSURECURVE       "pressurecurve"
 
 /* Button settings */
-#define KEY_ACTION_TYPE         "action-type"
-#define KEY_CUSTOM_ACTION       "custom-action"
+#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
@@ -701,7 +703,7 @@ reset_pad_buttons (GsdWacomDevice *device)
 
        XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev);
 
-       /* Reset all the LEDs */
+       /* 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;
@@ -709,16 +711,36 @@ reset_pad_buttons (GsdWacomDevice *device)
                     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
+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);
+}
+
+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),
@@ -756,6 +778,18 @@ set_wacom_settings (GsdWacomManager *manager,
                id = get_device_id (device);
                reset_pad_buttons (device);
                grab_button (id, TRUE, manager->priv->screen);
+
+               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);
+
                return;
        }
 
diff --git a/plugins/wacom/gsd-wacom-oled-helper.c b/plugins/wacom/gsd-wacom-oled-helper.c
new file mode 100644
index 0000000..ea15264
--- /dev/null
+++ b/plugins/wacom/gsd-wacom-oled-helper.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2012      Przemo Firszt <przemo firszt eu>
+ *
+ * The code is derived from gsd-wacom-led-helper.c
+ * written by:
+ * Copyright (C) 2010-2011 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2012      Bastien Nocera <hadess hadess net>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <unistd.h>
+
+#include <stdlib.h>
+#include "config.h"
+
+#include <glib.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <gudev/gudev.h>
+
+static gboolean
+gsd_wacom_oled_helper_write (const gchar *filename, gchar *buffer, GError **error)
+{
+       guchar *image;
+       gint retval;
+       gsize length;
+       gint fd = -1;
+       gboolean ret = TRUE;
+
+       fd = open (filename, O_WRONLY);
+       if (fd < 0) {
+               ret = FALSE;
+               g_set_error (error, 1, 0, "failed to open filename: %s", filename);
+               goto out;
+       }
+
+       image = g_base64_decode (buffer, &length);
+       if (!image)
+               goto out;
+
+       /* write to device file */
+       retval = write (fd, image, length);
+       if (retval != length) {
+               ret = FALSE;
+               g_set_error (error, 1, 0, "writing to %s failed", filename);
+               goto out;
+       }
+out:
+       if (fd >= 0)
+               close (fd);
+       g_free (image);
+       return ret;
+}
+
+static char *
+get_oled_sysfs_path (GUdevDevice *device,
+                   int          button_num)
+{
+       char *status;
+       char *filename;
+
+       status = g_strdup_printf ("button%d_rawimg", button_num);
+       filename = g_build_filename (g_udev_device_get_sysfs_path (device), "wacom_led", status, NULL);
+       g_free (status);
+
+       return filename;
+}
+
+static char *path = NULL;
+static char *buffer = "";
+static int button_num = -1;
+
+const GOptionEntry options[] = {
+       { "path", '\0', 0, G_OPTION_ARG_FILENAME, &path, "Device path for the Wacom device", NULL },
+       { "buffer", '\0', 0, G_OPTION_ARG_STRING, &buffer, "Image to set base64 encoded", NULL },
+       { "button", '\0', 0, G_OPTION_ARG_INT, &button_num, "Which button icon to set", NULL },
+       { NULL}
+};
+
+
+int main (int argc, char **argv)
+{
+       GOptionContext *context;
+       GUdevClient *client;
+       GUdevDevice *device, *parent;
+       int uid, euid;
+       char *filename;
+       GError *error = NULL;
+       const char * const subsystems[] = { "input", NULL };
+
+       /* get calling process */
+       uid = getuid ();
+       euid = geteuid ();
+       if (uid != 0 || euid != 0) {
+               g_print ("This program can only be used by the root user\n");
+               return 1;
+       }
+
+       context = g_option_context_new (NULL);
+       g_option_context_set_summary (context, "GNOME Settings Daemon Wacom OLED Icon Helper");
+       g_option_context_add_main_entries (context, options, NULL);
+       g_option_context_parse (context, &argc, &argv, NULL);
+
+       if (path == NULL ||
+           button_num < 0) {
+               char *txt;
+
+               txt = g_option_context_get_help (context, FALSE, NULL);
+               g_print ("%s", txt);
+               g_free (txt);
+
+               g_option_context_free (context);
+
+               return 1;
+       }
+       g_option_context_free (context);
+
+       client = g_udev_client_new (subsystems);
+       device = g_udev_client_query_by_device_file (client, path);
+       if (device == NULL) {
+               g_debug ("Could not find device '%s' in udev database", path);
+               goto bail;
+       }
+
+       if (g_udev_device_get_property_as_boolean (device, "ID_INPUT_TABLET") == FALSE &&
+           g_udev_device_get_property_as_boolean (device, "ID_INPUT_TOUCHPAD") == FALSE) {
+               g_debug ("Device '%s' is not a Wacom tablet", path);
+               goto bail;
+       }
+
+       if (g_strcmp0 (g_udev_device_get_property (device, "ID_BUS"), "usb") != 0) {
+               /* FIXME handle Bluetooth OLEDs too */
+               g_debug ("Non-USB OLEDs setting is not (yet) supported");
+               goto bail;
+       }
+
+       parent = g_udev_device_get_parent_with_subsystem (device, "usb", "usb_interface");
+       if (parent == NULL) {
+               g_debug ("Could not find parent USB device for '%s'", path);
+               goto bail;
+       }
+       g_object_unref (device);
+       device = parent;
+
+       filename = get_oled_sysfs_path (device, button_num);
+       if (gsd_wacom_oled_helper_write (filename, buffer, &error) == FALSE) {
+               g_debug ("Could not set OLED icon for '%s': %s", path, error->message);
+               g_error_free (error);
+               g_free (filename);
+               goto bail;
+       }
+       g_free (filename);
+
+       g_debug ("Successfully set OLED icon for '%s', button %d", path, button_num);
+
+       g_object_unref (device);
+       g_object_unref (client);
+
+       return 0;
+
+bail:
+       if (device != NULL)
+               g_object_unref (device);
+       if (client != NULL)
+               g_object_unref (client);
+       return 1;
+}
diff --git a/plugins/wacom/gsd-wacom-oled.c b/plugins/wacom/gsd-wacom-oled.c
new file mode 100644
index 0000000..bdc2bcd
--- /dev/null
+++ b/plugins/wacom/gsd-wacom-oled.c
@@ -0,0 +1,232 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Przemo Firszt <przemo firszt eu>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <unistd.h>
+#include <math.h>
+#include <pango/pango.h>
+#include <pango/pangocairo.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libwacom/libwacom.h>
+
+#include <gtk/gtk.h>
+#include "gsd-wacom-device.h"
+#include "gsd-wacom-oled.h"
+
+static void
+oled_scramble_icon (guchar* image)
+{
+       unsigned char buf[MAX_IMAGE_SIZE];
+       int x, y, i;
+       unsigned char l1, l2, h1, h2;
+
+       for (i = 0; i < MAX_IMAGE_SIZE; i++)
+               buf[i] = image[i];
+
+       for (y = 0; y < (OLED_HEIGHT / 2); y++) {
+               for (x = 0; x < (OLED_WIDTH / 2); x++) {
+                       l1 = (0x0F & (buf[OLED_HEIGHT - 1 - x + OLED_WIDTH * y]));
+                       l2 = (0x0F & (buf[OLED_HEIGHT - 1 - x + OLED_WIDTH * y] >> 4));
+                       h1 = (0xF0 & (buf[OLED_WIDTH - 1 - x + OLED_WIDTH * y] << 4));
+                       h2 = (0xF0 & (buf[OLED_WIDTH - 1 - x + OLED_WIDTH * y]));
+
+                       image[2 * x + OLED_WIDTH * y] = h1 | l1;
+                       image[2 * x + 1 + OLED_WIDTH * y] = h2 | l2;
+               }
+       }
+}
+
+static void
+oled_surface_to_image (guchar          *image,
+                      cairo_surface_t *surface)
+{
+       unsigned char *csurf;
+       int i, x, y;
+       unsigned char lo, hi;
+
+       cairo_surface_flush (surface);
+       csurf = cairo_image_surface_get_data (surface);
+       i = 0;
+       for (y = 0; y < OLED_HEIGHT; y++) {
+               for (x = 0; x < (OLED_WIDTH / 2); x++) {
+                       hi = 0xf0 & csurf[4 * OLED_WIDTH * y + 8 * x + 1];
+                       lo = 0x0f & (csurf[4 * OLED_WIDTH * y + 8 * x + 5] >> 4);
+                       image[i] = hi | lo;
+                       i++;
+               }
+       }
+}
+
+static void
+oled_split_text (char *label,
+                char *line1,
+                char *line2)
+{
+       char delimiters[5] = "+-_ ";
+       char **token;
+       int token_len[MAX_TOKEN];
+       gsize length;
+       int i;
+
+       if (g_utf8_strlen (label, LABEL_SIZE) <= MAX_1ST_LINE_LEN) {
+               g_utf8_strncpy (line1, label, MAX_1ST_LINE_LEN);
+               return;
+       }
+
+       token = g_strsplit_set (label, delimiters, -1);
+
+       if (g_utf8_strlen (token[0], LABEL_SIZE) > MAX_1ST_LINE_LEN) {
+               g_utf8_strncpy (line1, label, MAX_1ST_LINE_LEN);
+               g_utf8_strncpy (line2, label + MAX_1ST_LINE_LEN, LABEL_SIZE - MAX_1ST_LINE_LEN);
+               return;
+       }
+
+       for (i = 0; token[i] != NULL; i++)
+               token_len[i] = g_utf8_strlen (token[i], LABEL_SIZE);
+
+       length = token_len[0];
+       i = 0;
+       while ((length + token_len[i + 1] + 1) <= MAX_1ST_LINE_LEN) {
+               i++;
+               length = length + token_len[i] + 1;
+       }
+
+       g_utf8_strncpy (line1, label, length);
+       g_utf8_strncpy (line2, label + length + 1, LABEL_SIZE - length);
+
+       return;
+}
+
+static void
+oled_render_text (char   *label,
+                 guchar *image)
+{
+       cairo_t *cr;
+       cairo_surface_t *surface;
+       PangoFontDescription *desc;
+       PangoLayout *layout;
+       int width, height;
+       double dx, dy;
+       char line1[LABEL_SIZE + 1] = "";
+       char line2[LABEL_SIZE + 1] = "";
+       char *buf;
+
+       oled_split_text (label ,line1, line2);
+
+       buf = g_strdup_printf ("%s\n%s", line1, line2);
+
+       surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, OLED_WIDTH, OLED_HEIGHT);
+       cr = cairo_create (surface);
+       cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.99);
+       cairo_paint (cr);
+
+       layout = pango_cairo_create_layout (cr);
+       pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
+       pango_layout_set_text (layout, buf, - 1);
+       g_free (buf);
+       desc = pango_font_description_new ();
+
+       pango_font_description_set_family (desc, "Terminal");
+       pango_font_description_set_absolute_size (desc, PANGO_SCALE * 11);
+       pango_layout_set_font_description (layout, desc);
+       pango_font_description_free (desc);
+       pango_layout_get_size (layout, &width, &height);
+       width = width/PANGO_SCALE;
+       cairo_new_path (cr);
+
+       dx = trunc (((double)OLED_WIDTH - width) / 2);
+
+       if (*line2 == '\0')
+               dy = 10;
+       else
+               dy = 4;
+
+       cairo_move_to (cr, dx, dy);
+       cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
+       pango_cairo_update_layout (cr, layout);
+
+       pango_cairo_layout_path (cr, layout);
+       cairo_fill (cr);
+
+       oled_surface_to_image (image, surface);
+
+       g_object_unref (layout);
+       cairo_destroy (cr);
+
+       cairo_surface_destroy (surface);
+}
+
+static char *
+oled_encode_image (char *label)
+{
+       guchar *image;
+
+       image = g_malloc (MAX_IMAGE_SIZE);
+
+       /* convert label to image */
+       oled_render_text (label, image);
+       oled_scramble_icon (image);
+
+       return (g_base64_encode (image, MAX_IMAGE_SIZE));
+}
+
+void
+set_oled (GsdWacomDevice       *device,
+         char                  *button_id,
+         char                  *label)
+{
+       GError *error = NULL;
+       const char *path;
+       char *command;
+       gboolean ret;
+       char *buffer;
+
+#ifndef HAVE_GUDEV
+       /* Not implemented on non-Linux systems */
+       return;
+#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;
+       buffer = oled_encode_image (label);
+
+       path = gsd_wacom_device_get_path (device);
+
+       g_debug ("Setting OLED label '%s' on button %d (device %s)", label, button_id_short, path);
+
+       command = g_strdup_printf ("pkexec " LIBEXECDIR "/gsd-wacom-oled-helper --path %s --button %d 
--buffer %s",
+                                  path, button_id_short, buffer);
+       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);
+       }
+
+       g_free (command);
+}
diff --git a/plugins/wacom/gsd-wacom-oled.h b/plugins/wacom/gsd-wacom-oled.h
new file mode 100644
index 0000000..1cdaf65
--- /dev/null
+++ b/plugins/wacom/gsd-wacom-oled.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Przemo Firszt <przemo firszt eu>
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GSD_WACOM_OLED_H
+#define __GSD_WACOM_OLED_H
+
+G_BEGIN_DECLS
+
+/* OLED parameters */
+#define OLED_WIDTH             64                      /*Width of OLED icon - hardware dependent*/
+#define OLED_HEIGHT            32                      /*Height of OLED icon - hardware dependent*/
+#define LABEL_SIZE             30                      /*Maximum length of text for OLED icon*/
+#define MAX_TOKEN              (LABEL_SIZE >> 1)       /*Maximum number of tokens equals half of maximum 
number of characters*/
+#define MAX_IMAGE_SIZE         1024                    /*Size of buffer for storing OLED image*/
+#define MAX_1ST_LINE_LEN       10                      /*Maximum number of characters in 1st line of OLED 
icon*/
+
+void set_oled (GsdWacomDevice *device, char *button_id, char *label);
+
+G_END_DECLS
+
+#endif /* __GSD_WACOM_OLED_H */
diff --git a/plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in 
b/plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in
index 9821827..6bf77dd 100644
--- a/plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in
+++ b/plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in
@@ -27,5 +27,20 @@
     <annotate key="org.freedesktop.policykit.exec.path">@libexecdir@/gsd-wacom-led-helper</annotate>
   </action>
 
+  <action id="org.gnome.settings-daemon.plugins.wacom.wacom-oled-helper">
+    <!-- SECURITY:
+          - A normal active user on the local machine does not need permission
+            to change the OLED images for a Wacom tablet
+     -->
+    <_description>Modify the OLED image for a Wacom tablet</_description>
+    <_message>Authentication is required to modify the OLED image for a Wacom tablet</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.policykit.exec.path">@libexecdir@/gsd-wacom-oled-helper</annotate>
+  </action>
+
 </policyconfig>
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]