Code

Minor cleanup and addition of tablet debugging code.
authorJon A. Cruz <jon@joncruz.org>
Sun, 14 Mar 2010 02:18:39 +0000 (18:18 -0800)
committerJon A. Cruz <jon@joncruz.org>
Sun, 14 Mar 2010 02:18:39 +0000 (18:18 -0800)
src/dialogs/input.cpp

index a8892bde428e5039c0a4c9de7470ab8757c606e5..d34655ecc9e9e1435fb399e0a7a1adcd86a52526 100644 (file)
@@ -17,6 +17,7 @@
 #include <gtk/gtksignal.h>
 #include <gtk/gtkinputdialog.h>
 #include <glibmm/ustring.h>
+#include <list>
 
 #include "macros.h"
 #include "verbs.h"
@@ -36,6 +37,74 @@ static win_data wd;
 static gint x = -1000, y = -1000, w = 0, h = 0;
 static Glib::ustring const prefs_path = "/dialogs/input/";
 
+#define noTEST_WITH_GOOD_TABLET 1
+#define noTEST_WITH_BAD_TABLET 1
+
+#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
+static int testDeviceCount = 0;
+static GdkDevice* testDevices = 0;
+
+// Defined at the end of the file to keep debugging out of the way.
+static void initTestDevices();
+#endif
+
+static std::list<GdkDevice *> getInputDevices()
+{
+    std::list<GdkDevice*> devices;
+
+#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
+    initTestDevices();
+    for (int i = 0; i < testDeviceCount; i++) {
+        devices.push_back(&testDevices[i]);
+    }
+#else
+    for (GList *ptr = gdk_devices_list(); ptr; ptr = ptr->next) {
+        GdkDevice *device = static_cast<GdkDevice *>(ptr->data);
+        devices.push_back(device);
+    }
+#endif
+
+    return devices;
+}
+
+// wrap these GDK calls to be able to intercept for testing.
+
+static bool setDeviceMode( GdkDevice *device, GdkInputMode mode )
+{
+#if defined(TEST_WITH_GOOD_TABLET) || defined(TEST_WITH_BAD_TABLET)
+    (void)device;
+    (void)mode;
+    bool retVal = true; // Can't let the Gdk call be called with bad data
+#else
+    bool retVal = gdk_device_set_mode(device, mode);
+#endif
+    return retVal;
+}
+
+static void setDeviceAxisUse( GdkDevice *device, guint index, GdkAxisUse use )
+{
+#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET)
+    (void)device;
+    (void)index;
+    (void)use;
+#else
+    gdk_device_set_axis_use(device, index, use);
+#endif
+}
+
+static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers )
+{
+#if defined(TEST_WITH_GOOD_TABLET) && !defined(TEST_WITH_BAD_TABLET)
+    (void)device;
+    (void)index;
+    (void)keyval;
+    (void)modifiers;
+#else
+    gdk_device_set_key(device, index, keyval, modifiers);
+#endif
+}
+
+
 static void
 sp_input_dialog_destroy (GtkObject */*object*/, gpointer /*data*/)
 {
@@ -76,11 +145,12 @@ static Glib::ustring sanitized_device_path(gchar const *str)
     // This might break if someone has two tablets with broken names, but it's
     // not possible to do anything 100% correct then.
     bool broken = false;
-    if (!str || *str == 0) {
+
+    if (!str || (*str == 0)) {
         broken = true;
     } else {
         for (gchar const *s = str; *s; ++s) {
-            if (*s < 0x20 || *s >= 0x7f) {
+            if ((*s < 0x20) || (*s >= 0x7f)) {
                 broken = true;
                 break;
             }
@@ -96,30 +166,36 @@ static Glib::ustring sanitized_device_path(gchar const *str)
     return device_path;
 }
 
-void
-sp_input_load_from_preferences (void)
+void sp_input_load_from_preferences(void)
 {
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
-    for (GList *list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
-        GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
+    std::list<GdkDevice *> devices = getInputDevices();
+    for (std::list<GdkDevice *>::iterator it = devices.begin(); it != devices.end(); ++it) {
+        GdkDevice *device = *it;
+
+//         g_message("    s:%d m:%d hc:%d a:%d k:%d [%s]", device->source, device->mode, device->has_cursor, device->num_axes, device->num_keys, device->name);
+//         for (int i = 0; i < device->num_axes; i++) {
+//             GdkDeviceAxis &axis = device->axes[i];
+//             g_message("        axis[%d] u:%d  min:%f max:%f", i, axis.use, axis.min, axis.max);
+//         }
 
         Glib::ustring device_path = sanitized_device_path(device->name);
+//         if (device_path != (Glib::ustring("/devices/") + device->name)) {
+//             g_message("        re-name [%s]", device_path.c_str());
+//         }
 
-        GdkInputMode mode;
         Glib::ustring device_mode = prefs->getString(device_path + "/mode");
 
-        if (device_mode.empty())
-            mode = GDK_MODE_DISABLED;
-        else if (device_mode == "screen")
+        GdkInputMode mode = GDK_MODE_DISABLED;
+        if (device_mode == "screen") {
             mode = GDK_MODE_SCREEN;
-        else if (device_mode == "window")
+        } else if (device_mode == "window") {
             mode = GDK_MODE_WINDOW;
-        else
-            mode = GDK_MODE_DISABLED;
+        }
 
         if (device->mode != mode) {
-            gdk_device_set_mode(device, mode);
+            setDeviceMode(device, mode);
         }
 
         Glib::ustring::size_type pos0, pos1;
@@ -130,16 +206,18 @@ sp_input_load_from_preferences (void)
         pos0 = pos1 = 0;
         for (gint i=0; i < device->num_axes; i++) {
             pos1 = axes_str.find(';', pos0);
-            if (pos1 == Glib::ustring::npos)
+            if (pos1 == Glib::ustring::npos) {
                 break;  // Too few axis specifications
+            }
 
             axis_use = GDK_AXIS_IGNORE;
-            for (gint j=0; j < GDK_AXIS_LAST; j++)
+            for (gint j=0; j < GDK_AXIS_LAST; j++) {
                 if (!strcmp(axes_str.substr(pos0, pos1-pos0).c_str(), axis_use_strings[j])) {
                     axis_use = static_cast<GdkAxisUse>(j);
                     break;
                 }
-            gdk_device_set_axis_use(device, i, axis_use);
+            }
+            setDeviceAxisUse(device, i, axis_use);
             pos0 = pos1 + 1;
         }
 
@@ -150,23 +228,24 @@ sp_input_load_from_preferences (void)
         pos0 = pos1 = 0;
         for (gint i=0; i < device->num_keys; i++) {
             pos1 = keys_str.find(';', pos0);
-            if (pos1 == Glib::ustring::npos)
+            if (pos1 == Glib::ustring::npos) {
                 break;  // Too few key specifications
+            }
 
             gtk_accelerator_parse(keys_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier);
-            gdk_device_set_key(device, i, keyval, modifier);
+            setDeviceKey(device, i, keyval, modifier);
             pos0 = pos1 + 1;
         }
     }
 }
 
-void
-sp_input_save_to_preferences (void)
+void sp_input_save_to_preferences(void)
 {
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
-    for (GList *list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) {
-        GdkDevice *device = static_cast<GdkDevice *>(list_ptr->data);
+    std::list<GdkDevice *> devices = getInputDevices();
+    for (std::list<GdkDevice *>::iterator it = devices.begin(); it != devices.end(); ++it) {
+        GdkDevice *device = *it;
 
         Glib::ustring device_path = sanitized_device_path(device->name);
 
@@ -267,6 +346,200 @@ sp_input_dialog (void)
     gtk_window_present ((GtkWindow *) dlg);
 }
 
+// /////////////////////////////////
+// For debugging:
+// /////////////////////////////////
+
+
+#if defined(TEST_WITH_GOOD_TABLET)
+static void initTestDevices()
+{
+    static bool init = false;
+    if (!init) {
+        static GdkDevice devs[5] = {};
+        int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc.
+
+        {
+            // Laptop trackpad
+            devs[i].name = g_strdup("pointer");
+            devs[i].source = GDK_SOURCE_MOUSE;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Tablet stylus
+            devs[i].name = g_strdup("pen");
+            devs[i].source = GDK_SOURCE_PEN;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0},
+                                          {GDK_AXIS_PRESSURE, 0, 1},
+                                          {GDK_AXIS_XTILT, -1, 1},
+                                          {GDK_AXIS_YTILT, -1, 1}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Puck
+            devs[i].name = g_strdup("cursor");
+            devs[i].source = GDK_SOURCE_CURSOR;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0},
+                                          {GDK_AXIS_PRESSURE, 0, 1},
+                                          {GDK_AXIS_XTILT, -1, 1},
+                                          {GDK_AXIS_YTILT, -1, 1}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Back of tablet stylus
+            devs[i].name = g_strdup("eraser");
+            devs[i].source = GDK_SOURCE_ERASER;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0},
+                                          {GDK_AXIS_PRESSURE, 0, 1},
+                                          {GDK_AXIS_XTILT, -1, 1},
+                                          {GDK_AXIS_YTILT, -1, 1}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Main (composit) mouse device
+            devs[i].name = g_strdup("Core Pointer");
+            devs[i].source = GDK_SOURCE_MOUSE;
+            devs[i].mode = GDK_MODE_SCREEN;
+            devs[i].has_cursor = 1;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        testDeviceCount = i;
+        testDevices = devs;
+        init = true;
+    }
+}
+#elif defined(TEST_WITH_BAD_TABLET)
+
+/**
+ * Uses the current time in seconds to change a name to be unique from one
+ * run of the program to the next.
+ */
+void perturbName(gchar *str)
+{
+    if (str) {
+        GTimeVal when = {0,0};
+        g_get_current_time(&when);
+        gchar *tmp = g_strdup_printf("%ld", when.tv_sec);
+
+        size_t partLen = strlen(tmp);
+        size_t len = strlen(str);
+        if (len > (partLen + 4)) {
+            size_t pos = (len - partLen) / 2;
+            for (size_t i = 0; i < partLen; i++) {
+                str[pos + i] = tmp[i];
+            }
+        }
+        g_free(tmp);
+    }
+}
+
+static void initTestDevices()
+{
+    static bool init = false;
+    if (!init) {
+        static GdkDevice devs[5] = {};
+        int i = 0; // use variable instead of constant to allow devices to be moved around, commented out, etc.
+
+        {
+            // Main (composit) mouse device
+            devs[i].name = g_strdup("Core Pointer");
+            devs[i].source = GDK_SOURCE_MOUSE;
+            devs[i].mode = GDK_MODE_SCREEN;
+            devs[i].has_cursor = 1;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Back of tablet stylus
+            devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\356\232\210\307\255\350\271\214\310\201\350\222\200\310\201\356\202\250\310\200\350\223\260\310\201\356\202\250\310\200");
+            perturbName(devs[i].name);
+            devs[i].source = GDK_SOURCE_ERASER;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0},
+                                          {GDK_AXIS_PRESSURE, 0, 1},
+                                          {GDK_AXIS_XTILT, -1, 1},
+                                          {GDK_AXIS_YTILT, -1, 1}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        {
+            // Tablet stylus
+            devs[i].name = g_strdup("\346\205\227\347\221\254\347\201\257\345\220\240\346\211\241\346\225\254t\303\265\006 \347\211\220\347\215\245\347\225\263\346\225\262\345\214\240\347\245\264\347\225\254s\357\227\230#\354\234\274C\341\221\230\307\255\343\277\214\310\202\343\230\200\310\202\331\270\310\202\343\231\260\310\202\331\270\310\202");
+            perturbName(devs[i].name);
+            devs[i].source = GDK_SOURCE_PEN;
+            devs[i].mode = GDK_MODE_DISABLED;
+            devs[i].has_cursor = 0;
+            static GdkDeviceAxis tmp[] = {{GDK_AXIS_X, 0, 0},
+                                          {GDK_AXIS_Y, 0, 0},
+                                          {GDK_AXIS_PRESSURE, 0, 1},
+                                          {GDK_AXIS_XTILT, -1, 1},
+                                          {GDK_AXIS_YTILT, -1, 1}};
+            devs[i].num_axes = G_N_ELEMENTS(tmp);
+            devs[i].axes = tmp;
+            devs[i].num_keys = 0;
+            devs[i].keys = 0;
+            i++;
+        }
+
+        testDeviceCount = i;
+        testDevices = devs;
+        init = true;
+    }
+}
+#endif
+
 
 /*
   Local Variables: