Code

Cleanup of device internal handling and API.
authorJon A. Cruz <jon@joncruz.org>
Thu, 8 Apr 2010 07:49:42 +0000 (00:49 -0700)
committerJon A. Cruz <jon@joncruz.org>
Thu, 8 Apr 2010 07:49:42 +0000 (00:49 -0700)
src/device-manager.cpp
src/device-manager.h
src/ui/dialog/input.cpp

index 09fd7cb5f788cc7970ada63da52cfcd018d361ba..29e15b05a23c4d25fc4c4b9e20cecbffa1685e44 100644 (file)
@@ -2,21 +2,33 @@
 /*
  * Inkscape::DeviceManager - a view of input devices available.
  *
- * Copyright 2006  Jon A. Cruz  <jon@joncruz.org>
+ * Copyright 2010  Jon A. Cruz  <jon@joncruz.org>
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
 #include <glib.h>
 #include <map>
+#include <set>
+#include <gtk/gtkaccelgroup.h>
 
 #include "device-manager.h"
+#include "preferences.h"
 
+#define noDEBUG_VERBOSE 1
 
 static void createFakeList();
 GdkDevice fakeout[5];
 static GList* fakeList = 0;
 
+static bool isValidDevice(GdkDevice *device)
+{
+    bool valid = true;
+    for (size_t i = 0; (i < G_N_ELEMENTS(fakeout)) && valid; i++) {
+        valid = (device != &fakeout[i]);
+    }
+    return valid;
+}
 
 namespace Inkscape {
 
@@ -33,6 +45,88 @@ static pair<gint, gint> vals[] = {
 static std::map<gint, gint> bitVals(vals, &vals[G_N_ELEMENTS(vals)]);
 
 
+static const int RUNAWAY_MAX = 1000;
+
+static Glib::ustring getBaseDeviceName(Gdk::InputSource 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 std::map<Glib::ustring, Gdk::AxisUse> &getStringToAxis()
+{
+    static bool init = false;
+    static std::map<Glib::ustring, Gdk::AxisUse> mapping;
+    if (!init) {
+        init = true;
+        mapping["ignore"]   = Gdk::AXIS_IGNORE;
+        mapping["x"]        = Gdk::AXIS_X;
+        mapping["y"]        = Gdk::AXIS_Y;
+        mapping["pressure"] = Gdk::AXIS_PRESSURE;
+        mapping["xtilt"]    = Gdk::AXIS_XTILT;
+        mapping["ytilt"]    = Gdk::AXIS_YTILT;
+        mapping["wheel"]    = Gdk::AXIS_WHEEL;
+    }
+    return mapping;
+}
+
+std::map<Gdk::AxisUse, Glib::ustring> &getAxisToString()
+{
+    static bool init = false;
+    static std::map<Gdk::AxisUse, Glib::ustring> mapping;
+    if (!init) {
+        init = true;
+        for (std::map<Glib::ustring, Gdk::AxisUse>::iterator it = getStringToAxis().begin(); it != getStringToAxis().end(); ++it) {
+            mapping.insert(std::make_pair(it->second, it->first));
+        }
+    }
+    return mapping;
+}
+
+static std::map<Glib::ustring, Gdk::InputMode> &getStringToMode()
+{
+    static bool init = false;
+    static std::map<Glib::ustring, Gdk::InputMode> mapping;
+    if (!init) {
+        init = true;
+        mapping["disabled"] = Gdk::MODE_DISABLED;
+        mapping["screen"]   = Gdk::MODE_SCREEN;
+        mapping["window"]   = Gdk::MODE_WINDOW;
+    }
+    return mapping;
+}
+
+std::map<Gdk::InputMode, Glib::ustring> &getModeToString()
+{
+    static bool init = false;
+    static std::map<Gdk::InputMode, Glib::ustring> mapping;
+    if (!init) {
+        init = true;
+        for (std::map<Glib::ustring, Gdk::InputMode>::iterator it = getStringToMode().begin(); it != getStringToMode().end(); ++it) {
+            mapping.insert(std::make_pair(it->second, it->first));
+        }
+    }
+    return mapping;
+}
+
+
+
 InputDevice::InputDevice()
     : Glib::Object()
 {}
@@ -41,6 +135,9 @@ InputDevice::~InputDevice() {}
 
 class InputDeviceImpl : public InputDevice {
 public:
+    InputDeviceImpl(GdkDevice* device, std::set<Glib::ustring> &knownIDs);
+    virtual ~InputDeviceImpl() {}
+
     virtual Glib::ustring getId() const {return id;}
     virtual Glib::ustring getName() const {return name;}
     virtual Gdk::InputSource getSource() const {return source;}
@@ -55,14 +152,15 @@ public:
     virtual gint getLiveButtons() const {return liveButtons;}
     virtual void setLiveButtons(gint buttons) {liveButtons = buttons;}
 
-
-    InputDeviceImpl(GdkDevice* device);
-    virtual ~InputDeviceImpl() {}
+    // internal methods not on public superclass:
+    virtual GdkDevice *getDevice() { return device; }
 
 private:
     InputDeviceImpl(InputDeviceImpl const &); // no copy
     void operator=(InputDeviceImpl const &); // no assign
 
+    static Glib::ustring createId(Glib::ustring const &id, Gdk::InputSource source, std::set<Glib::ustring> &knownIDs);
+
     GdkDevice* device;
     Glib::ustring id;
     Glib::ustring name;
@@ -72,25 +170,25 @@ private:
     guint liveButtons;
 };
 
-class IdMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+class IdMatcher : public std::unary_function<Glib::RefPtr<InputDeviceImpl>&, bool> {
 public:
     IdMatcher(Glib::ustring const& target):target(target) {}
-    bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());}
+    bool operator ()(Glib::RefPtr<InputDeviceImpl>& dev) {return dev && (target == dev->getId());}
 
 private:
     Glib::ustring const& target;
 };
 
-class LinkMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+class LinkMatcher : public std::unary_function<Glib::RefPtr<InputDeviceImpl>&, bool> {
 public:
     LinkMatcher(Glib::ustring const& target):target(target) {}
-    bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());}
+    bool operator ()(Glib::RefPtr<InputDeviceImpl>& dev) {return dev && (target == dev->getLink());}
 
 private:
     Glib::ustring const& target;
 };
 
-InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
+InputDeviceImpl::InputDeviceImpl(GdkDevice* device, std::set<Glib::ustring> &knownIDs)
     : InputDevice(),
       device(device),
       id(),
@@ -100,27 +198,54 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
       liveAxes(0),
       liveButtons(0)
 {
+    id = createId(name, source, knownIDs);
+}
+
+
+Glib::ustring InputDeviceImpl::createId(Glib::ustring const &id,
+                                        Gdk::InputSource source,
+                                        std::set<Glib::ustring> &knownIDs)
+{
+    // Start with only allowing printable ASCII. Check later for more refinements.
+    bool badName = id.empty() || !id.is_ascii();
+    for (Glib::ustring::const_iterator it = id.begin(); (it != id.end()) && !badName; ++it) {
+        badName = *it < 0x20;
+    }
+
+    Glib::ustring base;
     switch ( source ) {
         case Gdk::SOURCE_MOUSE:
-            id = "M:";
+            base = "M:";
             break;
         case Gdk::SOURCE_CURSOR:
-            id = "C:";
+            base = "C:";
             break;
         case Gdk::SOURCE_PEN:
-            id = "P:";
+            base = "P:";
             break;
         case Gdk::SOURCE_ERASER:
-            id = "E:";
+            base = "E:";
             break;
         default:
-            id = "?:";
+            base = "?:";
     }
-    id += name;
-}
 
+    if (badName) {
+        base += getBaseDeviceName(source);
+    } else {
+        base += id;
+    }
 
+    // now ensure that all IDs become unique in a session.
+    int num = 1;
+    Glib::ustring result = base;
+    while ((knownIDs.find(result) != knownIDs.end()) && (num < RUNAWAY_MAX)) {
+        result = Glib::ustring::compose("%1%2", base, ++num);
+    }
 
+    knownIDs.insert(result);
+    return result;
+}
 
 
 
@@ -129,7 +254,12 @@ InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
 class DeviceManagerImpl : public DeviceManager {
 public:
     DeviceManagerImpl();
-    virtual std::list<InputDevice const *> getDevices();
+
+    virtual void loadConfig();
+    virtual void saveConfig();
+
+    virtual std::list<Glib::RefPtr<InputDevice const> > getDevices();
+
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged();
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChanged();
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged();
@@ -139,8 +269,13 @@ public:
     virtual void addButton(Glib::ustring const & id, gint button);
     virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link);
 
+    virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode );
+    virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use );
+    virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods );
+
 protected:
-    std::list<InputDeviceImpl*> devices;
+    std::list<Glib::RefPtr<InputDeviceImpl> > devices;
+
     sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChangedPriv;
     sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChangedPriv;
     sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChangedPriv;
@@ -157,29 +292,153 @@ DeviceManagerImpl::DeviceManagerImpl() :
     if ( !fakeList ) {
         createFakeList();
     }
-//     devList = fakeList;
+    //devList = fakeList;
+
+    std::set<Glib::ustring> knownIDs;
 
     for ( GList* curr = devList; curr; curr = g_list_next(curr) ) {
         GdkDevice* dev = reinterpret_cast<GdkDevice*>(curr->data);
         if ( dev ) {
-//             g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode,
-//                       dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys);
+#if DEBUG_VERBOSE
+            g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->name, dev->source, dev->mode,
+                      dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys);
+#endif
+
+            InputDeviceImpl* device = new InputDeviceImpl(dev, knownIDs);
+            device->reference();
+            devices.push_back(Glib::RefPtr<InputDeviceImpl>(device));
+        }
+    }
+}
+
+void DeviceManagerImpl::loadConfig()
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+    for (std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = devices.begin(); it != devices.end(); ++it) {
+        if ((*it)->getSource() != Gdk::SOURCE_MOUSE) {
+            Glib::ustring path = "/devices/" + (*it)->getId();
+
+            Gdk::InputMode mode = Gdk::MODE_DISABLED;
+            Glib::ustring val = prefs->getString(path + "/mode");
+            if (getStringToMode().find(val) != getStringToMode().end()) {
+                mode = getStringToMode()[val];
+            }
+            if ((*it)->getMode() != mode) {
+                setMode( (*it)->getId(), mode );
+            }
 
-            InputDeviceImpl* device = new InputDeviceImpl(dev);
-            devices.push_back(device);
+            //
+
+            val = prefs->getString(path + "/axes");
+            if (!val.empty()) {
+                std::vector<Glib::ustring> parts = Glib::Regex::split_simple(";", val);
+                for (size_t i = 0; i < parts.size(); ++i) {
+                    Glib::ustring name = parts[i];
+                    if (getStringToAxis().find(name) != getStringToAxis().end()) {
+                        Gdk::AxisUse use = getStringToAxis()[name];
+                        setAxisUse( (*it)->getId(), i, use );
+                    }
+                }
+            }
+
+            val = prefs->getString(path + "/keys");
+            if (!val.empty()) {
+                std::vector<Glib::ustring> parts = Glib::Regex::split_simple(";", val);
+                for (size_t i = 0; i < parts.size(); ++i) {
+                    Glib::ustring keyStr = parts[i];
+                    if (!keyStr.empty()) {
+                        guint key = 0;
+                        GdkModifierType mods = static_cast<GdkModifierType>(0);
+                        gtk_accelerator_parse( keyStr.c_str(), &key, &mods );
+                        setKey( (*it)->getId(), i, key, static_cast<Gdk::ModifierType>(mods) );
+                    }
+                }
+            }
         }
     }
 }
 
-std::list<InputDevice const *> DeviceManagerImpl::getDevices()
+void DeviceManagerImpl::saveConfig()
 {
-    std::list<InputDevice const *> tmp;
-    for ( std::list<InputDeviceImpl*>::const_iterator it = devices.begin(); it != devices.end(); ++it ) {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+    for (std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = devices.begin(); it != devices.end(); ++it) {
+        if ((*it)->getSource() != Gdk::SOURCE_MOUSE) {
+            Glib::ustring path = "/devices/" + (*it)->getId();
+
+            prefs->setString( path + "/mode", getModeToString()[(*it)->getMode()].c_str() );
+
+            Glib::ustring tmp;
+            for (gint i = 0; i < (*it)->getNumAxes(); ++i) {
+                if (i > 0) {
+                    tmp += ";";
+                }
+                tmp += getAxisToString()[static_cast<Gdk::AxisUse>((*it)->getDevice()->axes[i].use)];
+            }
+            prefs->setString( path + "/axes", tmp );
+
+            tmp = "";
+            for (gint i = 0; i < (*it)->getNumKeys(); ++i) {
+                if (i > 0) {
+                    tmp += ";";
+                }
+                tmp += gtk_accelerator_name((*it)->getDevice()->keys[i].keyval, (*it)->getDevice()->keys[i].modifiers);
+            }
+            prefs->setString( path + "/keys", tmp );
+        }
+    }
+}
+
+std::list<Glib::RefPtr<InputDevice const> > DeviceManagerImpl::getDevices()
+{
+    std::list<Glib::RefPtr<InputDevice const> > tmp;
+    for ( std::list<Glib::RefPtr<InputDeviceImpl> >::const_iterator it = devices.begin(); it != devices.end(); ++it ) {
         tmp.push_back(*it);
     }
     return tmp;
 }
 
+void DeviceManagerImpl::setMode( Glib::ustring const & id, Gdk::InputMode mode )
+{
+    std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+    if ( it != devices.end() ) {
+        if (isValidDevice((*it)->getDevice())) {
+            bool success = gdk_device_set_mode((*it)->getDevice(), static_cast<GdkInputMode>(mode));
+            if (success) {
+                //(*it)->setMode(mode);
+                signalDeviceChangedPriv.emit(*it);
+            } else {
+                g_warning("Unable to set mode on extended input device [%s]", (*it)->getId().c_str());
+            }
+        }
+    }
+}
+
+void DeviceManagerImpl::setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use )
+{
+    std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+    if ( it != devices.end() ) {
+        if (isValidDevice((*it)->getDevice())) {
+            gdk_device_set_axis_use((*it)->getDevice(), index, static_cast<GdkAxisUse>(use));
+            signalDeviceChangedPriv.emit(*it);
+        }
+    }
+}
+
+void DeviceManagerImpl::setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods )
+{
+    //static void setDeviceKey( GdkDevice* device, guint index, guint keyval, GdkModifierType modifiers )
+    //
+
+    std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+    if ( it != devices.end() ) {
+        if (isValidDevice((*it)->getDevice())) {
+            gdk_device_set_key((*it)->getDevice(), index, keyval, static_cast<GdkModifierType>(mods));
+            signalDeviceChangedPriv.emit(*it);
+        }
+    }
+}
 
 sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalDeviceChanged()
 {
@@ -204,7 +463,7 @@ sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalL
 void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
 {
     if ( axis >= 0 && axis < static_cast<gint>(bitVals.size()) ) {
-        std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+        std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
         if ( it != devices.end() ) {
             gint mask = bitVals[axis];
             if ( (mask & (*it)->getLiveAxes()) == 0 ) {
@@ -212,7 +471,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
 
                 // Only signal if a new axis was added
                 (*it)->reference();
-                signalAxesChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
+                signalAxesChangedPriv.emit(*it);
             }
         }
     }
@@ -221,7 +480,7 @@ void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis)
 void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
 {
     if ( button >= 0 && button < static_cast<gint>(bitVals.size()) ) {
-        std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+        std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
         if ( it != devices.end() ) {
             gint mask = bitVals[button];
             if ( (mask & (*it)->getLiveButtons()) == 0 ) {
@@ -229,7 +488,7 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
 
                 // Only signal if a new button was added
                 (*it)->reference();
-                signalButtonsChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
+                signalButtonsChangedPriv.emit(*it);
             }
         }
     }
@@ -237,12 +496,11 @@ void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
 
 void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link)
 {
-    std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+    std::list<Glib::RefPtr<InputDeviceImpl> >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
     if ( it != devices.end() ) {
-        InputDeviceImpl* dev = *it;
-
+        Glib::RefPtr<InputDeviceImpl> dev = *it;
 
-        InputDeviceImpl* targetDev = 0;
+        Glib::RefPtr<InputDeviceImpl> targetDev;
         if ( !link.empty() ) {
             // Need to be sure the target of the link exists
             it = std::find_if(devices.begin(), devices.end(), IdMatcher(link));
@@ -255,7 +513,7 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons
         if ( (link.empty() && !dev->getLink().empty())
              || (targetDev && (targetDev->getLink() != id)) ) {
             // only muck about if they aren't already linked
-            std::list<InputDeviceImpl*> changedItems;
+            std::list<Glib::RefPtr<InputDeviceImpl> > changedItems;
 
             if ( targetDev ) {
             // Is something else already using that link?
@@ -277,9 +535,9 @@ void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring cons
             dev->setLink(link);
             changedItems.push_back(dev);
 
-            for ( std::list<InputDeviceImpl*>::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
+            for ( std::list<Glib::RefPtr<InputDeviceImpl> >::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
                 (*iter)->reference();
-                signalLinkChangedPriv.emit(Glib::RefPtr<InputDevice>(*iter));
+                signalLinkChangedPriv.emit(*iter);
             }
         }
     }
index 1bfb5120c109ea6ddb2ec6a4ea195452143f0a6c..c32a79bfa82e63fe84ebfbb65b230f81e3044423 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Inkscape::DeviceManager - a view of input devices available.
  *
- * Copyright 2006  Jon A. Cruz  <jon@joncruz.org>
+ * Copyright 2010  Jon A. Cruz  <jon@joncruz.org>
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -42,7 +42,11 @@ class DeviceManager : public Glib::Object {
 public:
     static DeviceManager& getManager();
 
-    virtual std::list<InputDevice const *> getDevices() = 0;
+    virtual void loadConfig() = 0;
+    virtual void saveConfig() = 0;
+
+    virtual std::list<Glib::RefPtr<InputDevice const> > getDevices() = 0;
+
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged() = 0;
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalAxesChanged() = 0;
     virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged() = 0;
@@ -52,6 +56,10 @@ public:
     virtual void addButton(Glib::ustring const & id, gint button) = 0;
     virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) = 0;
 
+    virtual void setMode( Glib::ustring const & id, Gdk::InputMode mode ) = 0;
+    virtual void setAxisUse( Glib::ustring const & id, guint index, Gdk::AxisUse use ) = 0;
+    virtual void setKey( Glib::ustring const & id, guint index, guint keyval, Gdk::ModifierType mods ) = 0;
+
 protected:
     DeviceManager();
     virtual ~DeviceManager();
index ae8594e5008b245f6b25025136143e4ec5ec3a45..555b18349a61594953e47093510e5a1cf066f5ab 100644 (file)
@@ -329,7 +329,7 @@ public:
     Gtk::TreeModelColumn<Glib::ustring>                filename;
     Gtk::TreeModelColumn<Glib::ustring>                description;
     Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> >  thumbnail;
-    Gtk::TreeModelColumn<InputDevice const *>          device;
+    Gtk::TreeModelColumn<Glib::RefPtr<InputDevice const> > device;
 
     MyModelColumns() { add(filename); add(description); add(thumbnail); add(device); }
 };
@@ -640,7 +640,7 @@ InputDialogImpl::InputDialogImpl() :
 
 
 
-    std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
+    std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
     if ( !devList.empty() ) {
         row = *(store->append());
         row[cols.description] = "Hardware";
@@ -650,8 +650,8 @@ InputDialogImpl::InputDialogImpl() :
         childrow[cols.description] = "Tablet";
         childrow[cols.thumbnail] = tabletPix;
 
-        for ( std::list<InputDevice const *>::iterator it = devList.begin(); it != devList.end(); ++it ) {
-            InputDevice const* dev = *it;
+        for ( std::list<Glib::RefPtr<InputDevice const> >::iterator it = devList.begin(); it != devList.end(); ++it ) {
+            Glib::RefPtr<InputDevice const> dev = *it;
             if ( dev ) {
 //                 g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->getName().c_str(), dev->getSource(), dev->getMode(),
 //                           dev->hasCursor() ? "Yes":"no", dev->getNumAxes(), dev->getNumKeys());
@@ -741,7 +741,7 @@ bool InputDialogImpl::findDevice(const Gtk::TreeModel::iterator& iter,
                                  Gtk::TreeModel::iterator* result)
 {
     bool stop = false;
-    const InputDevice* dev = (*iter)[cols.device];
+    Glib::RefPtr<InputDevice const> dev = (*iter)[cols.device];
     if ( dev && (dev->getId() == id) ) {
         if ( result ) {
             *result = iter;
@@ -756,7 +756,7 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter,
                                        Gtk::TreeModel::iterator* result)
 {
     bool stop = false;
-    const InputDevice* dev = (*iter)[cols.device];
+    Glib::RefPtr<InputDevice const> dev = (*iter)[cols.device];
     if ( dev && (dev->getLink() == link) ) {
         if ( result ) {
             *result = iter;
@@ -783,8 +783,8 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
 //             g_message("Item %s is unlinked", device->getId().c_str());
             if ( deviceIter->parent() != tabletIter ) {
                 // Not the child of the tablet. move on up
-                
-                InputDevice const *dev = (*deviceIter)[cols.device];
+
+                Glib::RefPtr<InputDevice const> dev = (*deviceIter)[cols.device];
                 Glib::ustring descr = (*deviceIter)[cols.description];
                 Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[cols.thumbnail];
 
@@ -808,7 +808,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
                 (*newGroup)[cols.description] = "Pen";
                 (*newGroup)[cols.thumbnail] = penPix;
 
-                InputDevice const *dev = (*deviceIter)[cols.device];
+                Glib::RefPtr<InputDevice const> dev = (*deviceIter)[cols.device];
                 Glib::ustring descr = (*deviceIter)[cols.description];
                 Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[cols.thumbnail];
 
@@ -817,7 +817,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& device)
                 deviceRow[cols.thumbnail] = thumb;
                 deviceRow[cols.device] = dev;
 
-                
+
                 Gtk::TreeModel::iterator linkIter;
                 store->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>(
                                          sigc::mem_fun(*this, &InputDialogImpl::findDeviceByLink),
@@ -856,15 +856,15 @@ void InputDialogImpl::linkComboChanged() {
     if (iter) {
         Gtk::TreeModel::Row row = *iter;
         Glib::ustring val = row[cols.description];
-        InputDevice const * dev = row[cols.device];
+        Glib::RefPtr<InputDevice const> dev = row[cols.device];
         if ( dev ) {
             if ( linkCombo.get_active_row_number() == 0 ) {
                 // It is the "None" entry
                 DeviceManager::getManager().setLinkedTo(dev->getId(), "");
             } else {
                 Glib::ustring linkName = linkCombo.get_active_text();
-                std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
-                for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+                std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
+                for ( std::list<Glib::RefPtr<InputDevice const> >::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
                     if ( linkName == (*it)->getName() ) {
                         DeviceManager::getManager().setLinkedTo(dev->getId(), (*it)->getId());
                         break;
@@ -882,7 +882,7 @@ void InputDialogImpl::resyncToSelection() {
     if (iter) {
         Gtk::TreeModel::Row row = *iter;
         Glib::ustring val = row[cols.description];
-        InputDevice const * dev = row[cols.device];
+        Glib::RefPtr<InputDevice const> dev = row[cols.device];
         if ( dev ) {
             devDetails.set_sensitive(true);
 
@@ -892,8 +892,8 @@ void InputDialogImpl::resyncToSelection() {
             linkCombo.set_active(0);
             if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
                 Glib::ustring linked = dev->getLink();
-                std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
-                for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+                std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices();
+                for ( std::list<Glib::RefPtr<InputDevice const> >::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
                     if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) {
                         linkCombo.append_text((*it)->getName().c_str());
                         if ( (linked.length() > 0) && (linked == (*it)->getId()) ) {
@@ -964,7 +964,7 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev )
         if (iter) {
             Gtk::TreeModel::Row row = *iter;
             Glib::ustring val = row[cols.description];
-            InputDevice const * idev = row[cols.device];
+            Glib::RefPtr<InputDevice const> idev = row[cols.device];
             if ( !idev || (idev->getId() != key) ) {
                 dev = 0;
             }