From d8c456f411a4a17723364e4d68effe79dc0df986 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 12 Mar 2010 01:52:36 +0100 Subject: Hopefully fix #334800 (input devices configuration not saved). Fixed bugs: - https://launchpad.net/bugs/334800 (bzr r9177) --- src/dialogs/input.cpp | 118 +++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 53 deletions(-) (limited to 'src/dialogs/input.cpp') diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp index 0b4587f55..f2ef8afe0 100644 --- a/src/dialogs/input.cpp +++ b/src/dialogs/input.cpp @@ -63,10 +63,24 @@ sp_input_dialog_delete (GtkObject */*object*/, GdkEvent */*event*/, gpointer /*d } -static const gchar *axis_use_strings[GDK_AXIS_LAST] = { +static gchar const *axis_use_strings[GDK_AXIS_LAST] = { "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel" }; +static Glib::ustring sanitized_device_path(gchar const *str) +{ + // LP #334800: device names on Windows sometimes contain funny junk like + // \x03, \xf2, etc. We need to get rid of this to properly access the settings. + gchar *escaped = g_strescape(str, NULL); + + for (gchar *s = escaped; *s; ++s) { + if (*s == '/') *s = '_'; + } + Glib::ustring device_path = Glib::ustring("/devices/") + escaped; + g_free(escaped); + return device_path; +} + void sp_input_load_from_preferences (void) { @@ -74,60 +88,59 @@ sp_input_load_from_preferences (void) for (GList *list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) { GdkDevice *device = static_cast(list_ptr->data); - //repr = sp_repr_lookup_child(devices, "id", device->name); - Glib::ustring device_path = Glib::ustring("/devices/") + device->name; - if (/*repr != NULL*/ 1) { - GdkInputMode mode; - Glib::ustring device_mode = prefs->getString(device_path + "/mode"); - - if (device_mode.empty()) - mode = GDK_MODE_DISABLED; - else if (device_mode == "screen") - mode = GDK_MODE_SCREEN; - else if (device_mode == "window") - mode = GDK_MODE_WINDOW; - else - mode = GDK_MODE_DISABLED; - - if (device->mode != mode) { - gdk_device_set_mode(device, mode); - } - Glib::ustring::size_type pos0, pos1; - GdkAxisUse axis_use; - - //temp_ptr = repr->attribute("axes"); - Glib::ustring const axes_str = prefs->getString(device_path + "/axes"); - pos0 = pos1 = 0; - for (gint i=0; i < device->num_axes; i++) { - pos1 = axes_str.find(';', pos0); - if (pos1 == Glib::ustring::npos) - break; // Too few axis specifications - - axis_use = GDK_AXIS_IGNORE; - 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(j); - break; - } - gdk_device_set_axis_use(device, i, axis_use); - pos0 = pos1 + 1; - } + Glib::ustring device_path = sanitized_device_path(device->name); - guint keyval; - GdkModifierType modifier; + GdkInputMode mode; + Glib::ustring device_mode = prefs->getString(device_path + "/mode"); - Glib::ustring const keys_str = prefs->getString(device_path + "/keys"); - pos0 = pos1 = 0; - for (gint i=0; i < device->num_keys; i++) { - pos1 = keys_str.find(';', pos0); - if (pos1 == Glib::ustring::npos) - break; // Too few key specifications + if (device_mode.empty()) + mode = GDK_MODE_DISABLED; + else if (device_mode == "screen") + mode = GDK_MODE_SCREEN; + else if (device_mode == "window") + mode = GDK_MODE_WINDOW; + else + mode = GDK_MODE_DISABLED; - gtk_accelerator_parse(keys_str.substr(pos0, pos1-pos0).c_str(), &keyval, &modifier); - gdk_device_set_key(device, i, keyval, modifier); - pos0 = pos1 + 1; - } + if (device->mode != mode) { + gdk_device_set_mode(device, mode); + } + + Glib::ustring::size_type pos0, pos1; + GdkAxisUse axis_use; + + //temp_ptr = repr->attribute("axes"); + Glib::ustring const axes_str = prefs->getString(device_path + "/axes"); + pos0 = pos1 = 0; + for (gint i=0; i < device->num_axes; i++) { + pos1 = axes_str.find(';', pos0); + if (pos1 == Glib::ustring::npos) + break; // Too few axis specifications + + axis_use = GDK_AXIS_IGNORE; + 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(j); + break; + } + gdk_device_set_axis_use(device, i, axis_use); + pos0 = pos1 + 1; + } + + guint keyval; + GdkModifierType modifier; + + Glib::ustring const keys_str = prefs->getString(device_path + "/keys"); + pos0 = pos1 = 0; + for (gint i=0; i < device->num_keys; i++) { + pos1 = keys_str.find(';', pos0); + 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); + pos0 = pos1 + 1; } } } @@ -140,8 +153,7 @@ sp_input_save_to_preferences (void) for (GList *list_ptr = gdk_devices_list(); list_ptr != NULL; list_ptr = list_ptr->next) { GdkDevice *device = static_cast(list_ptr->data); - //repr = sp_repr_lookup_child(devices, "id", device->name); - Glib::ustring device_path = Glib::ustring("/devices/") + device->name; + Glib::ustring device_path = sanitized_device_path(device->name); switch (device->mode) { default: -- cgit v1.2.3 From 8397b25b72b26593e52fd717baae3c967fc28ebf Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 13 Mar 2010 03:48:03 +0100 Subject: Try harder to fix the tablet configuration problem (bzr r9183) --- src/dialogs/input.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'src/dialogs/input.cpp') diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp index f2ef8afe0..a8892bde4 100644 --- a/src/dialogs/input.cpp +++ b/src/dialogs/input.cpp @@ -69,15 +69,30 @@ static gchar const *axis_use_strings[GDK_AXIS_LAST] = { static Glib::ustring sanitized_device_path(gchar const *str) { - // LP #334800: device names on Windows sometimes contain funny junk like - // \x03, \xf2, etc. We need to get rid of this to properly access the settings. - gchar *escaped = g_strescape(str, NULL); + // LP #334800: tablet device names on Windows sometimes contain funny junk like + // \x03, \xf2, etc. Moreover this junk changes between runs. + // If the tablet name contains unprintable or non-ASCII characters, + // we use some default name. + // 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) { + broken = true; + } else { + for (gchar const *s = str; *s; ++s) { + if (*s < 0x20 || *s >= 0x7f) { + broken = true; + break; + } + } + } - for (gchar *s = escaped; *s; ++s) { - if (*s == '/') *s = '_'; + Glib::ustring device_path = "/devices/"; + if (broken) { + device_path += "Tablet"; + } else { + device_path += str; } - Glib::ustring device_path = Glib::ustring("/devices/") + escaped; - g_free(escaped); return device_path; } -- cgit v1.2.3 From 06116ac1f52948afd3a1e000fcdc2b969c40e12a Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 13 Mar 2010 18:18:39 -0800 Subject: Minor cleanup and addition of tablet debugging code. (bzr r9185) --- src/dialogs/input.cpp | 319 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 296 insertions(+), 23 deletions(-) (limited to 'src/dialogs/input.cpp') diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp index a8892bde4..d34655ecc 100644 --- a/src/dialogs/input.cpp +++ b/src/dialogs/input.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #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 getInputDevices() +{ + std::list 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(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(list_ptr->data); + std::list devices = getInputDevices(); + for (std::list::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(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(list_ptr->data); + std::list devices = getInputDevices(); + for (std::list::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: -- cgit v1.2.3 From 18a0f4223eeffd3b9facc26c9cbbc559ff36ed35 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 13 Mar 2010 19:37:11 -0800 Subject: Create better names when intput devices are reported with broken ones. (bzr r9186) --- src/dialogs/input.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 8 deletions(-) (limited to 'src/dialogs/input.cpp') diff --git a/src/dialogs/input.cpp b/src/dialogs/input.cpp index d34655ecc..55e9704c3 100644 --- a/src/dialogs/input.cpp +++ b/src/dialogs/input.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "macros.h" #include "verbs.h" @@ -136,7 +137,31 @@ static gchar const *axis_use_strings[GDK_AXIS_LAST] = { "ignore", "x", "y", "pressure", "xtilt", "ytilt", "wheel" }; -static Glib::ustring sanitized_device_path(gchar const *str) +static const int RUNAWAY_MAX = 1000; + +static Glib::ustring getBaseDeviceName(GdkInputSource source) +{ + Glib::ustring name; + switch (source) { + case GDK_SOURCE_MOUSE: + name ="pointer"; + break; + case GDK_SOURCE_PEN: + name ="pen"; + break; + case GDK_SOURCE_ERASER: + name ="eraser"; + break; + case GDK_SOURCE_CURSOR: + name ="cursor"; + break; + default: + name = "tablet"; + } + return name; +} + +static Glib::ustring createSanitizedPath(GdkDevice* device, std::set &seenPaths) { // LP #334800: tablet device names on Windows sometimes contain funny junk like // \x03, \xf2, etc. Moreover this junk changes between runs. @@ -146,10 +171,10 @@ static Glib::ustring sanitized_device_path(gchar const *str) // not possible to do anything 100% correct then. bool broken = false; - if (!str || (*str == 0)) { + if (!device->name || (*(device->name) == 0)) { broken = true; } else { - for (gchar const *s = str; *s; ++s) { + for (gchar const *s = device->name; *s; ++s) { if ((*s < 0x20) || (*s >= 0x7f)) { broken = true; break; @@ -157,12 +182,20 @@ static Glib::ustring sanitized_device_path(gchar const *str) } } - Glib::ustring device_path = "/devices/"; + Glib::ustring device_path; if (broken) { - device_path += "Tablet"; + Glib::ustring base = Glib::ustring("/devices/") + getBaseDeviceName(device->source); + int num = 1; + device_path = base; + while ((seenPaths.find(device_path) != seenPaths.end()) && (num < RUNAWAY_MAX)) { + device_path = Glib::ustring::compose("%1%2", base, ++num); + } } else { - device_path += str; + device_path += Glib::ustring("/devices/") + device->name; } + + seenPaths.insert(device_path); + return device_path; } @@ -171,6 +204,7 @@ void sp_input_load_from_preferences(void) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); std::list devices = getInputDevices(); + std::set seenPaths; for (std::list::iterator it = devices.begin(); it != devices.end(); ++it) { GdkDevice *device = *it; @@ -180,7 +214,7 @@ void sp_input_load_from_preferences(void) // 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); + Glib::ustring device_path = createSanitizedPath(device, seenPaths); // if (device_path != (Glib::ustring("/devices/") + device->name)) { // g_message(" re-name [%s]", device_path.c_str()); // } @@ -244,10 +278,11 @@ void sp_input_save_to_preferences(void) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); std::list devices = getInputDevices(); + std::set seenPaths; for (std::list::iterator it = devices.begin(); it != devices.end(); ++it) { GdkDevice *device = *it; - Glib::ustring device_path = sanitized_device_path(device->name); + Glib::ustring device_path = createSanitizedPath(device, seenPaths); switch (device->mode) { default: @@ -533,6 +568,25 @@ static void initTestDevices() 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; -- cgit v1.2.3