From d70ad7a28e89c69b96ec96e311aeef00b0f506f2 Mon Sep 17 00:00:00 2001 From: joncruz Date: Thu, 20 Mar 2008 08:44:00 +0000 Subject: [PATCH] Adding signals and linking --- src/device-manager.cpp | 191 +++++++++++++++++++++++++++++++++++++--- src/device-manager.h | 13 ++- src/ui/dialog/input.cpp | 151 ++++++++++++++++++++++++------- 3 files changed, 309 insertions(+), 46 deletions(-) diff --git a/src/device-manager.cpp b/src/device-manager.cpp index bd34af297..9cf4583c6 100644 --- a/src/device-manager.cpp +++ b/src/device-manager.cpp @@ -8,6 +8,7 @@ */ #include +#include #include "device-manager.h" @@ -19,17 +20,39 @@ static GList* fakeList = 0; namespace Inkscape { -InputDevice::InputDevice() {} +using std::pair; + +static pair vals[] = { + pair(0, 1), pair(1, 1 << 1), pair(2, 1 << 2), pair(3, 1 << 3), + pair(4, 1 << 4), pair(5, 1 << 5), pair(6, 1 << 6), pair(7, 1 << 7), + pair(8, 1 << 8), pair(9, 1 << 9), pair(10, 1 << 10), pair(11, 1 << 11), + pair(12, 1 << 12), pair(13, 1 << 13), pair(14, 1 << 14), pair(15, 1 << 15), + pair(16, 1 << 16), pair(17, 1 << 17), pair(18, 1 << 18), pair(19, 1 << 19), + pair(20, 1 << 20), pair(21, 1 << 21), pair(22, 1 << 22), pair(23, 1 << 23) +}; +static std::map bitVals(vals, &vals[G_N_ELEMENTS(vals)]); + + +InputDevice::InputDevice() + : Glib::Object() +{} + InputDevice::~InputDevice() {} class InputDeviceImpl : public InputDevice { public: - virtual Glib::ustring getName() const {return Glib::ustring(device->name);} - virtual Gdk::InputSource getSource() const {return static_cast(device->source);} + virtual Glib::ustring getId() const {return id;} + virtual Glib::ustring getName() const {return name;} + virtual Gdk::InputSource getSource() const {return source;} virtual Gdk::InputMode getMode() const {return static_cast(device->mode);} virtual bool hasCursor() const {return device->has_cursor;} virtual gint getNumAxes() const {return device->num_axes;} virtual gint getNumKeys() const {return device->num_keys;} + virtual Glib::ustring getLink() const {return link;} + virtual void setLink( Glib::ustring const& link ) {this->link = link;} + virtual gint getLiveButtons() const {return liveButtons;} + virtual void setLiveButtons(gint buttons) {liveButtons = buttons;} + InputDeviceImpl(GdkDevice* device); virtual ~InputDeviceImpl() {} @@ -39,12 +62,57 @@ private: void operator=(InputDeviceImpl const &); // no assign GdkDevice* device; + Glib::ustring id; + Glib::ustring name; + Gdk::InputSource source; + Glib::ustring link; + guint liveButtons; +}; + +class IdMatcher : public std::unary_function { +public: + IdMatcher(Glib::ustring const& target):target(target) {} + bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());} + +private: + Glib::ustring const& target; +}; + +class LinkMatcher : public std::unary_function { +public: + LinkMatcher(Glib::ustring const& target):target(target) {} + bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());} + +private: + Glib::ustring const& target; }; InputDeviceImpl::InputDeviceImpl(GdkDevice* device) : InputDevice(), - device(device) + device(device), + id(), + name(device->name ? device->name : ""), + source(static_cast(device->source)), + link(), + liveButtons(0) { + switch ( source ) { + case Gdk::SOURCE_MOUSE: + id = "M:"; + break; + case Gdk::SOURCE_CURSOR: + id = "C:"; + break; + case Gdk::SOURCE_PEN: + id = "P:"; + break; + case Gdk::SOURCE_ERASER: + id = "E:"; + break; + default: + id = "?:"; + } + id += name; } @@ -58,11 +126,21 @@ class DeviceManagerImpl : public DeviceManager { public: DeviceManagerImpl(); virtual std::list getDevices(); + virtual sigc::signal& > signalDeviceChanged(); + virtual sigc::signal& > signalButtonsChanged(); + virtual sigc::signal& > signalLinkChanged(); + + virtual void addButton(Glib::ustring const & id, gint button); + virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link); protected: std::list devices; + sigc::signal& > signalDeviceChangedPriv; + sigc::signal& > signalButtonsChangedPriv; + sigc::signal& > signalLinkChangedPriv; }; + DeviceManagerImpl::DeviceManagerImpl() : DeviceManager(), devices() @@ -96,9 +174,87 @@ std::list DeviceManagerImpl::getDevices() } +sigc::signal& > DeviceManagerImpl::signalDeviceChanged() +{ + return signalDeviceChangedPriv; +} + +sigc::signal& > DeviceManagerImpl::signalButtonsChanged() +{ + return signalButtonsChangedPriv; +} + +sigc::signal& > DeviceManagerImpl::signalLinkChanged() +{ + return signalLinkChangedPriv; +} + +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)); + if ( it != devices.end() ) { + gint mask = bitVals[button]; + if ( (mask & (*it)->getLiveButtons()) == 0 ) { + (*it)->setLiveButtons((*it)->getLiveButtons() | mask); + + // Only signal if a new button was added + (*it)->reference(); + signalButtonsChangedPriv.emit(Glib::RefPtr(*it)); + } + } + } +} + + +void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) +{ + std::list::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id)); + if ( it != devices.end() ) { + InputDeviceImpl* dev = *it; + // Need to be sure the target of the link exists + it = std::find_if(devices.begin(), devices.end(), IdMatcher(link)); + if ( it != devices.end() ) { + InputDeviceImpl* targetDev = *it; + if ( (dev->getLink() != link) || (targetDev->getLink() != id) ) { + // only muck about if they aren't already linked + std::list changedItems; + + // Is something else already using that link? + it = std::find_if(devices.begin(), devices.end(), LinkMatcher(link)); + if ( it != devices.end() ) { + (*it)->setLink(""); + changedItems.push_back(*it); + } + it = std::find_if(devices.begin(), devices.end(), LinkMatcher(id)); + if ( it != devices.end() ) { + (*it)->setLink(""); + changedItems.push_back(*it); + } + dev->setLink(link); + targetDev->setLink(id); + changedItems.push_back(targetDev); + changedItems.push_back(dev); + + for ( std::list::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) { + (*iter)->reference(); + signalLinkChangedPriv.emit(Glib::RefPtr(*iter)); + } + } + } + } +} + + + + + + static DeviceManagerImpl* theInstance = 0; -DeviceManager::DeviceManager() { +DeviceManager::DeviceManager() + : Glib::Object() +{ } DeviceManager::~DeviceManager() { @@ -197,14 +353,23 @@ static void createFakeList() { fakeout[3].num_keys = 7; fakeout[3].keys = stylusKeys; - fakeout[4].name = "Core Pointer"; - fakeout[4].source = GDK_SOURCE_MOUSE; - fakeout[4].mode = GDK_MODE_SCREEN; - fakeout[4].has_cursor = TRUE; - fakeout[4].num_axes = 2; - fakeout[4].axes = coreAxes; - fakeout[4].num_keys = 0; - fakeout[4].keys = NULL; +// try to find the first *real* core pointer + GList* devList = gdk_devices_list(); + while ( devList && devList->data && (((GdkDevice*)devList->data)->source != GDK_SOURCE_MOUSE) ) { + devList = g_list_next(devList); + } + if ( devList && devList->data ) { + fakeout[4] = *((GdkDevice*)devList->data); + } else { + fakeout[4].name = "Core Pointer"; + fakeout[4].source = GDK_SOURCE_MOUSE; + fakeout[4].mode = GDK_MODE_SCREEN; + fakeout[4].has_cursor = TRUE; + fakeout[4].num_axes = 2; + fakeout[4].axes = coreAxes; + fakeout[4].num_keys = 0; + fakeout[4].keys = NULL; + } for ( guint pos = 0; pos < G_N_ELEMENTS(fakeout); pos++) { fakeList = g_list_append(fakeList, &(fakeout[pos])); diff --git a/src/device-manager.h b/src/device-manager.h index 0b532aae2..f441180a6 100644 --- a/src/device-manager.h +++ b/src/device-manager.h @@ -16,14 +16,17 @@ namespace Inkscape { -class InputDevice { +class InputDevice : public Glib::Object { public: + virtual Glib::ustring getId() const = 0; virtual Glib::ustring getName() const = 0; virtual Gdk::InputSource getSource() const = 0; virtual Gdk::InputMode getMode() const = 0; virtual bool hasCursor() const = 0; virtual gint getNumAxes() const = 0; virtual gint getNumKeys() const = 0; + virtual Glib::ustring getLink() const = 0; + virtual gint getLiveButtons() const = 0; protected: InputDevice(); @@ -34,11 +37,17 @@ private: void operator=(InputDevice const &); // no assign }; -class DeviceManager { +class DeviceManager : public Glib::Object { public: static DeviceManager& getManager(); virtual std::list getDevices() = 0; + virtual sigc::signal& > signalDeviceChanged() = 0; + virtual sigc::signal& > signalButtonsChanged() = 0; + virtual sigc::signal& > signalLinkChanged() = 0; + + virtual void addButton(Glib::ustring const & id, gint button) = 0; + virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) = 0; protected: DeviceManager(); diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index 8e132a2f5..f5746dbde 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -1,5 +1,29 @@ +/* XPM */ +static char * core_xpm[] = { +"16 16 4 1", +" c None", +". c #808080", +"+ c #000000", +"@ c #FFFFFF", +" ", +" ", +" ", +" .++++++. ", +" +@+@@+@+ ", +" +@+@@+@+ ", +" +.+..+.+ ", +" +@@@@@@+ ", +" +@@@@@@+ ", +" +@@@@@@+ ", +" +@@@@@@+ ", +" +@@@@@@+ ", +" .++++++. ", +" ", +" ", +" "}; + /* XPM */ static char *eraser[] = { /* columns rows colors chars-per-pixel */ @@ -268,6 +292,7 @@ public: virtual ~InputDialogImpl() {} private: + Glib::RefPtr corePix; Glib::RefPtr penPix; Glib::RefPtr mousePix; Glib::RefPtr tipPix; @@ -298,7 +323,8 @@ private: Gtk::Label devAxesCount; Gtk::ComboBoxText axesCombo; Gtk::ComboBoxText buttonCombo; - Gtk::ComboBoxText modeCombo; + Gtk::ComboBoxText linkCombo; + sigc::connection linkConnection; Gtk::Label keyVal; Gtk::Entry keyEntry; Gtk::Table devDetails; @@ -313,7 +339,11 @@ private: void updateTestButtons( Glib::ustring const& key, gint hotButton ); Glib::ustring getKeyFor( GdkDevice* device ); bool eventSnoop(GdkEvent* event); - void foo(); + void linkComboChanged(); + void resyncToSelection(); + void handleDeviceChange(const Glib::RefPtr& device); + void updateDeviceButtons(const Glib::RefPtr& device); + void updateDeviceLinks(const Glib::RefPtr& device); }; @@ -328,6 +358,7 @@ InputDialog &InputDialog::getInstance() InputDialogImpl::InputDialogImpl() : InputDialog(), + corePix(Gdk::Pixbuf::create_from_xpm_data(core_xpm)), penPix(Gdk::Pixbuf::create_from_xpm_data(pen)), mousePix(Gdk::Pixbuf::create_from_xpm_data(mouse)), tipPix(Gdk::Pixbuf::create_from_xpm_data(tip)), @@ -350,7 +381,7 @@ InputDialogImpl::InputDialogImpl() : detailScroller(), splitter(), split2(), - modeCombo(), + linkCombo(), devDetails(6, 2), confSplitter(), topHolder(), @@ -407,18 +438,17 @@ InputDialogImpl::InputDialogImpl() : rowNum++; - lbl = Gtk::manage(new Gtk::Label("Mode:")); + lbl = Gtk::manage(new Gtk::Label("Link:")); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); - modeCombo.append_text("Disabled"); - modeCombo.append_text("Screen"); - modeCombo.append_text("Window"); - modeCombo.set_active_text("Disabled"); - modeCombo.set_sensitive(false); + linkCombo.append_text("None"); + linkCombo.set_active_text("None"); + linkCombo.set_sensitive(false); + linkConnection = linkCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::linkComboChanged)); - devDetails.attach(modeCombo, 1, 2, rowNum, rowNum + 1, + devDetails.attach(linkCombo, 1, 2, rowNum, rowNum + 1, ::Gtk::FILL, ::Gtk::SHRINK); rowNum++; @@ -453,6 +483,7 @@ InputDialogImpl::InputDialogImpl() : rowNum++; +/* lbl = Gtk::manage(new Gtk::Label("Actual button count:")); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, @@ -462,6 +493,7 @@ InputDialogImpl::InputDialogImpl() : ::Gtk::SHRINK); rowNum++; +*/ devDetails.attach(keyVal, 0, 2, rowNum, rowNum + 1, ::Gtk::FILL, @@ -508,14 +540,12 @@ InputDialogImpl::InputDialogImpl() : tree.set_enable_tree_lines(); tree.set_headers_visible(false); - tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::foo)); + tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection)); std::list devList = Inkscape::DeviceManager::getManager().getDevices(); if ( !devList.empty() ) { - g_message("Found some"); - { GdkModifierType defaultModMask = static_cast(gtk_accelerator_get_default_mod_mask()); gchar* name = gtk_accelerator_name(GDK_a, defaultModMask); @@ -538,11 +568,15 @@ InputDialogImpl::InputDialogImpl() : 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()); - if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { +// if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { + if ( dev ) { deviceRow = *(store->append(childrow.children())); deviceRow[cols.description] = dev->getName(); deviceRow[cols.device] = dev; switch ( dev->getSource() ) { + case GDK_SOURCE_MOUSE: + deviceRow[cols.thumbnail] = corePix; + break; case GDK_SOURCE_PEN: if (deviceRow[cols.description] == "pad") { deviceRow[cols.thumbnail] = sidebuttonsPix; @@ -567,13 +601,60 @@ InputDialogImpl::InputDialogImpl() : } else { g_message("NO DEVICES FOUND"); } - + Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange)); + Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons)); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceLinks)); tree.expand_all(); show_all_children(); } -void InputDialogImpl::foo() { +void InputDialogImpl::handleDeviceChange(const Glib::RefPtr& /*device*/) +{ +// g_message("OUCH!!!! for %p hits %s", &device, device->getId().c_str()); +} + +void InputDialogImpl::updateDeviceButtons(const Glib::RefPtr& device) +{ + gint live = device->getLiveButtons(); + std::set existing = buttonMap[device->getId()]; + gint mask = 0x1; + for ( gint num = 0; num < 32; num++, mask <<= 1) { + if ( (mask & live) != 0 ) { + if ( existing.find(num) == existing.end() ) { + buttonMap[device->getId()].insert(num); + } + } + } + updateTestButtons(device->getId(), -1); +} + +void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr& /*device*/) +{ +// g_message("Links!!!! for %p hits %s with link of %s", &device, device->getId().c_str(), device->getLink().c_str()); +} + +void InputDialogImpl::linkComboChanged() { + Glib::RefPtr treeSel = tree.get_selection(); + Gtk::TreeModel::iterator iter = treeSel->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Glib::ustring val = row[cols.description]; + InputDevice const * dev = row[cols.device]; + if ( dev ) { + 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 ) { + if ( linkName == (*it)->getName() ) { + DeviceManager::getManager().setLinkedTo(dev->getId(), (*it)->getId()); + break; + } + } + } + } +} + +void InputDialogImpl::resyncToSelection() { bool clear = true; Glib::RefPtr treeSel = tree.get_selection(); Gtk::TreeModel::iterator iter = treeSel->get_selected(); @@ -583,20 +664,28 @@ void InputDialogImpl::foo() { InputDevice const * dev = row[cols.device]; if ( dev ) { devDetails.set_sensitive(true); - modeCombo.set_sensitive(true); - switch( dev->getMode() ) { - case GDK_MODE_DISABLED: - modeCombo.set_active(0); - break; - case GDK_MODE_SCREEN: - modeCombo.set_active(1); - break; - case GDK_MODE_WINDOW: - modeCombo.set_active(2); - break; - default: - ; + + linkConnection.block(); + linkCombo.clear_items(); + linkCombo.append_text("None"); + 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 ) { + if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) { + linkCombo.append_text((*it)->getName().c_str()); + if ( (linked.length() > 0) && (linked == (*it)->getId()) ) { + linkCombo.set_active_text((*it)->getName().c_str()); + } + } + } + linkCombo.set_sensitive(true); + } else { + linkCombo.set_sensitive(false); } + linkConnection.unblock(); + clear = false; devName.set_label(row[cols.description]); setupValueAndCombo( dev->getNumAxes(), dev->getNumAxes(), devAxesCount, axesCombo); @@ -703,6 +792,7 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event) if ( buttonMap[key].find(btnEvt->button) == buttonMap[key].end() ) { g_message("New button found for %s = %d", key.c_str(), btnEvt->button); buttonMap[key].insert(btnEvt->button); + DeviceManager::getManager().addButton(key, btnEvt->button); } hotButton = modmod ? btnEvt->button : -1; updateTestButtons(key, hotButton); @@ -748,11 +838,10 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event) if ( (lastSourceSeen != source) || (lastDevnameSeen != devName) ) { - g_message("FLIPPIES %d => %d", lastSourceSeen, source); switch (source) { case GDK_SOURCE_MOUSE: { - testThumb.set(mousePix); + testThumb.set(corePix); } break; case GDK_SOURCE_CURSOR: -- 2.30.2