9cf4583c698f1bfc379f2350536e9e4ea12d63d0
2 /*
3 * Inkscape::DeviceManager - a view of input devices available.
4 *
5 * Copyright 2006 Jon A. Cruz <jon@joncruz.org>
6 *
7 * Released under GNU GPL, read the file 'COPYING' for more information
8 */
10 #include <glib.h>
11 #include <map>
13 #include "device-manager.h"
16 static void createFakeList();
17 GdkDevice fakeout[5];
18 static GList* fakeList = 0;
21 namespace Inkscape {
23 using std::pair;
25 static pair<gint, gint> vals[] = {
26 pair<gint, gint>(0, 1), pair<gint, gint>(1, 1 << 1), pair<gint, gint>(2, 1 << 2), pair<gint, gint>(3, 1 << 3),
27 pair<gint, gint>(4, 1 << 4), pair<gint, gint>(5, 1 << 5), pair<gint, gint>(6, 1 << 6), pair<gint, gint>(7, 1 << 7),
28 pair<gint, gint>(8, 1 << 8), pair<gint, gint>(9, 1 << 9), pair<gint, gint>(10, 1 << 10), pair<gint, gint>(11, 1 << 11),
29 pair<gint, gint>(12, 1 << 12), pair<gint, gint>(13, 1 << 13), pair<gint, gint>(14, 1 << 14), pair<gint, gint>(15, 1 << 15),
30 pair<gint, gint>(16, 1 << 16), pair<gint, gint>(17, 1 << 17), pair<gint, gint>(18, 1 << 18), pair<gint, gint>(19, 1 << 19),
31 pair<gint, gint>(20, 1 << 20), pair<gint, gint>(21, 1 << 21), pair<gint, gint>(22, 1 << 22), pair<gint, gint>(23, 1 << 23)
32 };
33 static std::map<gint, gint> bitVals(vals, &vals[G_N_ELEMENTS(vals)]);
36 InputDevice::InputDevice()
37 : Glib::Object()
38 {}
40 InputDevice::~InputDevice() {}
42 class InputDeviceImpl : public InputDevice {
43 public:
44 virtual Glib::ustring getId() const {return id;}
45 virtual Glib::ustring getName() const {return name;}
46 virtual Gdk::InputSource getSource() const {return source;}
47 virtual Gdk::InputMode getMode() const {return static_cast<Gdk::InputMode>(device->mode);}
48 virtual bool hasCursor() const {return device->has_cursor;}
49 virtual gint getNumAxes() const {return device->num_axes;}
50 virtual gint getNumKeys() const {return device->num_keys;}
51 virtual Glib::ustring getLink() const {return link;}
52 virtual void setLink( Glib::ustring const& link ) {this->link = link;}
53 virtual gint getLiveButtons() const {return liveButtons;}
54 virtual void setLiveButtons(gint buttons) {liveButtons = buttons;}
57 InputDeviceImpl(GdkDevice* device);
58 virtual ~InputDeviceImpl() {}
60 private:
61 InputDeviceImpl(InputDeviceImpl const &); // no copy
62 void operator=(InputDeviceImpl const &); // no assign
64 GdkDevice* device;
65 Glib::ustring id;
66 Glib::ustring name;
67 Gdk::InputSource source;
68 Glib::ustring link;
69 guint liveButtons;
70 };
72 class IdMatcher : public std::unary_function<InputDeviceImpl*, bool> {
73 public:
74 IdMatcher(Glib::ustring const& target):target(target) {}
75 bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());}
77 private:
78 Glib::ustring const& target;
79 };
81 class LinkMatcher : public std::unary_function<InputDeviceImpl*, bool> {
82 public:
83 LinkMatcher(Glib::ustring const& target):target(target) {}
84 bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());}
86 private:
87 Glib::ustring const& target;
88 };
90 InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
91 : InputDevice(),
92 device(device),
93 id(),
94 name(device->name ? device->name : ""),
95 source(static_cast<Gdk::InputSource>(device->source)),
96 link(),
97 liveButtons(0)
98 {
99 switch ( source ) {
100 case Gdk::SOURCE_MOUSE:
101 id = "M:";
102 break;
103 case Gdk::SOURCE_CURSOR:
104 id = "C:";
105 break;
106 case Gdk::SOURCE_PEN:
107 id = "P:";
108 break;
109 case Gdk::SOURCE_ERASER:
110 id = "E:";
111 break;
112 default:
113 id = "?:";
114 }
115 id += name;
116 }
125 class DeviceManagerImpl : public DeviceManager {
126 public:
127 DeviceManagerImpl();
128 virtual std::list<InputDevice const *> getDevices();
129 virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged();
130 virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged();
131 virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChanged();
133 virtual void addButton(Glib::ustring const & id, gint button);
134 virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link);
136 protected:
137 std::list<InputDeviceImpl*> devices;
138 sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChangedPriv;
139 sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChangedPriv;
140 sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChangedPriv;
141 };
144 DeviceManagerImpl::DeviceManagerImpl() :
145 DeviceManager(),
146 devices()
147 {
148 GList* devList = gdk_devices_list();
150 if ( !fakeList ) {
151 createFakeList();
152 }
153 // devList = fakeList;
155 for ( GList* curr = devList; curr; curr = g_list_next(curr) ) {
156 GdkDevice* dev = reinterpret_cast<GdkDevice*>(curr->data);
157 if ( dev ) {
158 // 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,
159 // dev->has_cursor?"Yes":"no", dev->num_axes, dev->num_keys);
161 InputDeviceImpl* device = new InputDeviceImpl(dev);
162 devices.push_back(device);
163 }
164 }
165 }
167 std::list<InputDevice const *> DeviceManagerImpl::getDevices()
168 {
169 std::list<InputDevice const *> tmp;
170 for ( std::list<InputDeviceImpl*>::const_iterator it = devices.begin(); it != devices.end(); ++it ) {
171 tmp.push_back(*it);
172 }
173 return tmp;
174 }
177 sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalDeviceChanged()
178 {
179 return signalDeviceChangedPriv;
180 }
182 sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalButtonsChanged()
183 {
184 return signalButtonsChangedPriv;
185 }
187 sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalLinkChanged()
188 {
189 return signalLinkChangedPriv;
190 }
192 void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
193 {
194 if ( button >= 0 && button < static_cast<gint>(bitVals.size()) ) {
195 std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
196 if ( it != devices.end() ) {
197 gint mask = bitVals[button];
198 if ( (mask & (*it)->getLiveButtons()) == 0 ) {
199 (*it)->setLiveButtons((*it)->getLiveButtons() | mask);
201 // Only signal if a new button was added
202 (*it)->reference();
203 signalButtonsChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
204 }
205 }
206 }
207 }
210 void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link)
211 {
212 std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
213 if ( it != devices.end() ) {
214 InputDeviceImpl* dev = *it;
215 // Need to be sure the target of the link exists
216 it = std::find_if(devices.begin(), devices.end(), IdMatcher(link));
217 if ( it != devices.end() ) {
218 InputDeviceImpl* targetDev = *it;
219 if ( (dev->getLink() != link) || (targetDev->getLink() != id) ) {
220 // only muck about if they aren't already linked
221 std::list<InputDeviceImpl*> changedItems;
223 // Is something else already using that link?
224 it = std::find_if(devices.begin(), devices.end(), LinkMatcher(link));
225 if ( it != devices.end() ) {
226 (*it)->setLink("");
227 changedItems.push_back(*it);
228 }
229 it = std::find_if(devices.begin(), devices.end(), LinkMatcher(id));
230 if ( it != devices.end() ) {
231 (*it)->setLink("");
232 changedItems.push_back(*it);
233 }
234 dev->setLink(link);
235 targetDev->setLink(id);
236 changedItems.push_back(targetDev);
237 changedItems.push_back(dev);
239 for ( std::list<InputDeviceImpl*>::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
240 (*iter)->reference();
241 signalLinkChangedPriv.emit(Glib::RefPtr<InputDevice>(*iter));
242 }
243 }
244 }
245 }
246 }
253 static DeviceManagerImpl* theInstance = 0;
255 DeviceManager::DeviceManager()
256 : Glib::Object()
257 {
258 }
260 DeviceManager::~DeviceManager() {
261 }
263 DeviceManager& DeviceManager::getManager() {
264 if ( !theInstance ) {
265 theInstance = new DeviceManagerImpl();
266 }
268 return *theInstance;
269 }
271 } // namespace Inkscape
278 GdkDeviceAxis padAxes[] = {{GDK_AXIS_X, 0.0, 0.0},
279 {GDK_AXIS_Y, 0.0, 0.0},
280 {GDK_AXIS_PRESSURE, 0.0, 1.0},
281 {GDK_AXIS_XTILT, -1.0, 1.0},
282 {GDK_AXIS_YTILT, -1.0, 1.0},
283 {GDK_AXIS_WHEEL, 0.0, 1.0}};
284 GdkDeviceKey padKeys[] = {{0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0},
285 {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}};
287 GdkDeviceAxis eraserAxes[] = {{GDK_AXIS_X, 0.0, 0.0},
288 {GDK_AXIS_Y, 0.0, 0.0},
289 {GDK_AXIS_PRESSURE, 0.0, 1.0},
290 {GDK_AXIS_XTILT, -1.0, 1.0},
291 {GDK_AXIS_YTILT, -1.0, 1.0},
292 {GDK_AXIS_WHEEL, 0.0, 1.0}};
293 GdkDeviceKey eraserKeys[] = {{0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0},
294 {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}};
296 GdkDeviceAxis cursorAxes[] = {{GDK_AXIS_X, 0.0, 0.0},
297 {GDK_AXIS_Y, 0.0, 0.0},
298 {GDK_AXIS_PRESSURE, 0.0, 1.0},
299 {GDK_AXIS_XTILT, -1.0, 1.0},
300 {GDK_AXIS_YTILT, -1.0, 1.0},
301 {GDK_AXIS_WHEEL, 0.0, 1.0}};
302 GdkDeviceKey cursorKeys[] = {{0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0},
303 {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}};
305 GdkDeviceAxis stylusAxes[] = {{GDK_AXIS_X, 0.0, 0.0},
306 {GDK_AXIS_Y, 0.0, 0.0},
307 {GDK_AXIS_PRESSURE, 0.0, 1.0},
308 {GDK_AXIS_XTILT, -1.0, 1.0},
309 {GDK_AXIS_YTILT, -1.0, 1.0},
310 {GDK_AXIS_WHEEL, 0.0, 1.0}};
311 GdkDeviceKey stylusKeys[] = {{0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0},
312 {0, (GdkModifierType)0}, {0, (GdkModifierType)0}, {0, (GdkModifierType)0}};
315 GdkDeviceAxis coreAxes[] = {{GDK_AXIS_X, 0.0, 0.0},
316 {GDK_AXIS_Y, 0.0, 0.0}};
318 static void createFakeList() {
319 if ( !fakeList ) {
320 fakeout[0].name = "pad";
321 fakeout[0].source = GDK_SOURCE_PEN;
322 fakeout[0].mode = GDK_MODE_SCREEN;
323 fakeout[0].has_cursor = TRUE;
324 fakeout[0].num_axes = 6;
325 fakeout[0].axes = padAxes;
326 fakeout[0].num_keys = 8;
327 fakeout[0].keys = padKeys;
329 fakeout[1].name = "eraser";
330 fakeout[1].source = GDK_SOURCE_ERASER;
331 fakeout[1].mode = GDK_MODE_SCREEN;
332 fakeout[1].has_cursor = TRUE;
333 fakeout[1].num_axes = 6;
334 fakeout[1].axes = eraserAxes;
335 fakeout[1].num_keys = 7;
336 fakeout[1].keys = eraserKeys;
338 fakeout[2].name = "cursor";
339 fakeout[2].source = GDK_SOURCE_CURSOR;
340 fakeout[2].mode = GDK_MODE_SCREEN;
341 fakeout[2].has_cursor = TRUE;
342 fakeout[2].num_axes = 6;
343 fakeout[2].axes = cursorAxes;
344 fakeout[2].num_keys = 7;
345 fakeout[2].keys = cursorKeys;
347 fakeout[3].name = "stylus";
348 fakeout[3].source = GDK_SOURCE_PEN;
349 fakeout[3].mode = GDK_MODE_SCREEN;
350 fakeout[3].has_cursor = TRUE;
351 fakeout[3].num_axes = 6;
352 fakeout[3].axes = stylusAxes;
353 fakeout[3].num_keys = 7;
354 fakeout[3].keys = stylusKeys;
356 // try to find the first *real* core pointer
357 GList* devList = gdk_devices_list();
358 while ( devList && devList->data && (((GdkDevice*)devList->data)->source != GDK_SOURCE_MOUSE) ) {
359 devList = g_list_next(devList);
360 }
361 if ( devList && devList->data ) {
362 fakeout[4] = *((GdkDevice*)devList->data);
363 } else {
364 fakeout[4].name = "Core Pointer";
365 fakeout[4].source = GDK_SOURCE_MOUSE;
366 fakeout[4].mode = GDK_MODE_SCREEN;
367 fakeout[4].has_cursor = TRUE;
368 fakeout[4].num_axes = 2;
369 fakeout[4].axes = coreAxes;
370 fakeout[4].num_keys = 0;
371 fakeout[4].keys = NULL;
372 }
374 for ( guint pos = 0; pos < G_N_ELEMENTS(fakeout); pos++) {
375 fakeList = g_list_append(fakeList, &(fakeout[pos]));
376 }
377 }
378 }
381 /*
382 Local Variables:
383 mode:c++
384 c-file-style:"stroustrup"
385 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
386 indent-tabs-mode:nil
387 fill-column:99
388 End:
389 */
390 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :