From: Jon A. Cruz Date: Thu, 8 Apr 2010 07:49:42 +0000 (-0700) Subject: Cleanup of device internal handling and API. X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=f11c59cb3f794a30504cb373fc8239433fd7c20f;p=inkscape.git Cleanup of device internal handling and API. --- diff --git a/src/device-manager.cpp b/src/device-manager.cpp index 09fd7cb5f..29e15b05a 100644 --- a/src/device-manager.cpp +++ b/src/device-manager.cpp @@ -2,21 +2,33 @@ /* * Inkscape::DeviceManager - a view of input devices available. * - * Copyright 2006 Jon A. Cruz + * Copyright 2010 Jon A. Cruz * * Released under GNU GPL, read the file 'COPYING' for more information */ #include #include +#include +#include #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 vals[] = { static std::map 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 &getStringToAxis() +{ + static bool init = false; + static std::map 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 &getAxisToString() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + for (std::map::iterator it = getStringToAxis().begin(); it != getStringToAxis().end(); ++it) { + mapping.insert(std::make_pair(it->second, it->first)); + } + } + return mapping; +} + +static std::map &getStringToMode() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + mapping["disabled"] = Gdk::MODE_DISABLED; + mapping["screen"] = Gdk::MODE_SCREEN; + mapping["window"] = Gdk::MODE_WINDOW; + } + return mapping; +} + +std::map &getModeToString() +{ + static bool init = false; + static std::map mapping; + if (!init) { + init = true; + for (std::map::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 &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 &knownIDs); + GdkDevice* device; Glib::ustring id; Glib::ustring name; @@ -72,25 +170,25 @@ private: guint liveButtons; }; -class IdMatcher : public std::unary_function { +class IdMatcher : public std::unary_function&, bool> { public: IdMatcher(Glib::ustring const& target):target(target) {} - bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());} + bool operator ()(Glib::RefPtr& dev) {return dev && (target == dev->getId());} private: Glib::ustring const& target; }; -class LinkMatcher : public std::unary_function { +class LinkMatcher : public std::unary_function&, bool> { public: LinkMatcher(Glib::ustring const& target):target(target) {} - bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());} + bool operator ()(Glib::RefPtr& dev) {return dev && (target == dev->getLink());} private: Glib::ustring const& target; }; -InputDeviceImpl::InputDeviceImpl(GdkDevice* device) +InputDeviceImpl::InputDeviceImpl(GdkDevice* device, std::set &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 &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 getDevices(); + + virtual void loadConfig(); + virtual void saveConfig(); + + virtual std::list > getDevices(); + virtual sigc::signal& > signalDeviceChanged(); virtual sigc::signal& > signalAxesChanged(); virtual sigc::signal& > 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 devices; + std::list > devices; + sigc::signal& > signalDeviceChangedPriv; sigc::signal& > signalAxesChangedPriv; sigc::signal& > signalButtonsChangedPriv; @@ -157,29 +292,153 @@ DeviceManagerImpl::DeviceManagerImpl() : if ( !fakeList ) { createFakeList(); } -// devList = fakeList; + //devList = fakeList; + + std::set knownIDs; for ( GList* curr = devList; curr; curr = g_list_next(curr) ) { GdkDevice* dev = reinterpret_cast(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(device)); + } + } +} + +void DeviceManagerImpl::loadConfig() +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + for (std::list >::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 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 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(0); + gtk_accelerator_parse( keyStr.c_str(), &key, &mods ); + setKey( (*it)->getId(), i, key, static_cast(mods) ); + } + } + } } } } -std::list DeviceManagerImpl::getDevices() +void DeviceManagerImpl::saveConfig() { - std::list tmp; - for ( std::list::const_iterator it = devices.begin(); it != devices.end(); ++it ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + for (std::list >::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((*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 > DeviceManagerImpl::getDevices() +{ + std::list > tmp; + for ( std::list >::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 >::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(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 >::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(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 >::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(mods)); + signalDeviceChangedPriv.emit(*it); + } + } +} sigc::signal& > DeviceManagerImpl::signalDeviceChanged() { @@ -204,7 +463,7 @@ sigc::signal& > DeviceManagerImpl::signalL void DeviceManagerImpl::addAxis(Glib::ustring const & id, gint axis) { if ( axis >= 0 && axis < static_cast(bitVals.size()) ) { - std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::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(*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(bitVals.size()) ) { - std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::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(*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::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + std::list >::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); if ( it != devices.end() ) { - InputDeviceImpl* dev = *it; - + Glib::RefPtr dev = *it; - InputDeviceImpl* targetDev = 0; + Glib::RefPtr 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 changedItems; + std::list > 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::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) { + for ( std::list >::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) { (*iter)->reference(); - signalLinkChangedPriv.emit(Glib::RefPtr(*iter)); + signalLinkChangedPriv.emit(*iter); } } } diff --git a/src/device-manager.h b/src/device-manager.h index 1bfb5120c..c32a79bfa 100644 --- a/src/device-manager.h +++ b/src/device-manager.h @@ -1,7 +1,7 @@ /* * Inkscape::DeviceManager - a view of input devices available. * - * Copyright 2006 Jon A. Cruz + * Copyright 2010 Jon A. Cruz * * 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 getDevices() = 0; + virtual void loadConfig() = 0; + virtual void saveConfig() = 0; + + virtual std::list > getDevices() = 0; + virtual sigc::signal& > signalDeviceChanged() = 0; virtual sigc::signal& > signalAxesChanged() = 0; virtual sigc::signal& > 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(); diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index ae8594e50..555b18349 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -329,7 +329,7 @@ public: Gtk::TreeModelColumn filename; Gtk::TreeModelColumn description; Gtk::TreeModelColumn< Glib::RefPtr > thumbnail; - Gtk::TreeModelColumn device; + Gtk::TreeModelColumn > device; MyModelColumns() { add(filename); add(description); add(thumbnail); add(device); } }; @@ -640,7 +640,7 @@ InputDialogImpl::InputDialogImpl() : - std::list devList = Inkscape::DeviceManager::getManager().getDevices(); + std::list > 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::iterator it = devList.begin(); it != devList.end(); ++it ) { - InputDevice const* dev = *it; + for ( std::list >::iterator it = devList.begin(); it != devList.end(); ++it ) { + Glib::RefPtr 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 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 dev = (*iter)[cols.device]; if ( dev && (dev->getLink() == link) ) { if ( result ) { *result = iter; @@ -783,8 +783,8 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& 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 dev = (*deviceIter)[cols.device]; Glib::ustring descr = (*deviceIter)[cols.description]; Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; @@ -808,7 +808,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) (*newGroup)[cols.description] = "Pen"; (*newGroup)[cols.thumbnail] = penPix; - InputDevice const *dev = (*deviceIter)[cols.device]; + Glib::RefPtr dev = (*deviceIter)[cols.device]; Glib::ustring descr = (*deviceIter)[cols.description]; Glib::RefPtr thumb = (*deviceIter)[cols.thumbnail]; @@ -817,7 +817,7 @@ void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& device) deviceRow[cols.thumbnail] = thumb; deviceRow[cols.device] = dev; - + Gtk::TreeModel::iterator linkIter; store->foreach_iter( sigc::bind( 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 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 devList = Inkscape::DeviceManager::getManager().getDevices(); - for ( std::list::const_iterator it = devList.begin(); it != devList.end(); ++it ) { + std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); + for ( std::list >::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 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 devList = Inkscape::DeviceManager::getManager().getDevices(); - for ( std::list::const_iterator it = devList.begin(); it != devList.end(); ++it ) { + std::list > devList = Inkscape::DeviceManager::getManager().getDevices(); + for ( std::list >::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 idev = row[cols.device]; if ( !idev || (idev->getId() != key) ) { dev = 0; }