~ubuntu-branches/ubuntu/precise/gnome-control-center/precise-updates

« back to all changes in this revision

Viewing changes to panels/wacom/gsd-wacom-device.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher, Jeremy Bicha, Ken VanDine
  • Date: 2012-02-15 23:16:31 UTC
  • mfrom: (1.1.56)
  • Revision ID: package-import@ubuntu.com-20120215231631-vk7me0mhofpsq0hp
Tags: 1:3.3.5-0ubuntu1
* Upload the new serie, that will bring in quite some fixes, we revert
  some problematic or risky changes as well
* The new version includes those fixes:
  - "Change Password in User Accounts panel focuses "New password" field, 
     skipping "Current password"" (lp: #821759)
  - The dialog to add online accounts should have a title 
    (lp: #822380)
  - "Remove Profile" button clickable in Color panel when 
     no profile selected (lp: #869603)
  - Move Removable Media into System Info (lp: #835880)
  - Sound preferences: mouse scrolling balance only works for right.
    (lp: #918017)
  - gnome-control-center SIGSEGV in actualize_printers_list() 
    (lp: #903009)
  - selecting preffered applications is not an info (lp: #890143)
  - Add a keyboard shortcut by default for take screenshot of a selection"
    (lp: #625518)
* debian/patches/revert_git_datetime_port.patch:
  - revert use of datetimed, we don't use systemd and ubuntu-system-service 
    doesn't support it yet
* debian/patches/revert_git_drop_library.patch:
  - consolidate "01_allow_external_panels.patch", don't drop the library
    we use it from other components on ubuntu, the patch will be improved
    later to not use a copy of files like it does in that version
* debian/patches/revert_git_stop_using_gconf.patch,
  debian/patches/revert_ua_gsettings.patch,
  debian/patches/revert_git_keyboard_gsettings.patch:
  - revert keyboard porting to gsettings, compiz still use gconf and we
    didn't update gnome-shell to the new serie (yet)

[ Jeremy Bicha ]
* New upstream release (Thanks Rico Tzchichholz!)
* debian/control.in:
  - Bump minimum dependency versions and add libwacom dependency
* debian/rules: Build without -Wl,-z,defs
* debian/watch: Watch for unstable releases
* Refreshed patches:
  - 01_allow_external_panels.patch
  - 04_add_theme_selection.patch
  - 50_ubuntu_systemwide_prefs.patch
  - 58_ubuntu_icon_views_redesign.patch
  - 59_install_gcm_components_on_demand.patch
  - 91_configure_cheese.patch
* Dropped upstream patches:
  - 00git_handle_media_dialog_close.patch
  - 03_show_wacom_under_unity.patch
  - 90_git_sound_tab_order.patch
  - 91_git_build_use_fontconfig.patch
  - 92_git_minimal_output_height.patch
  - 93_change_window_role_on_panel_change.patch
  - 94_git_adding_shortcuts.patch
  - 95_git_ctrlw_shortcut.patch
  - git_extra_keywords.patch

[ Ken VanDine ]
* debian/patches/96_sound_nua_panel.patch
  - refreshed with latest changes from ronoc

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Red Hat, Inc.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
17
 *
 
18
 * Author: Bastien Nocera <hadess@hadess.net>
 
19
 *
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <glib.h>
 
25
#include <glib/gi18n-lib.h>
 
26
#include <gtk/gtk.h>
 
27
#include <gdk/gdk.h>
 
28
#include <gdk/gdkx.h>
 
29
#include <X11/Xatom.h>
 
30
#define GNOME_DESKTOP_USE_UNSTABLE_API
 
31
#include <libgnome-desktop/gnome-rr.h>
 
32
#include <libgnome-desktop/gnome-rr-config.h>
 
33
 
 
34
#include <libwacom/libwacom.h>
 
35
#include <X11/extensions/XInput.h>
 
36
#include <X11/extensions/XInput2.h>
 
37
 
 
38
#include "gsd-input-helper.h"
 
39
 
 
40
#include "gsd-enums.h"
 
41
#include "gsd-wacom-device.h"
 
42
 
 
43
#define GSD_WACOM_STYLUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_STYLUS, GsdWacomStylusPrivate))
 
44
 
 
45
#define WACOM_TABLET_SCHEMA "org.gnome.settings-daemon.peripherals.wacom"
 
46
#define WACOM_DEVICE_CONFIG_BASE "/org/gnome/settings-daemon/peripherals/wacom/%s/"
 
47
#define WACOM_STYLUS_SCHEMA "org.gnome.settings-daemon.peripherals.wacom.stylus"
 
48
#define WACOM_ERASER_SCHEMA "org.gnome.settings-daemon.peripherals.wacom.eraser"
 
49
 
 
50
static WacomDeviceDatabase *db = NULL;
 
51
 
 
52
struct GsdWacomStylusPrivate
 
53
{
 
54
        GsdWacomDevice *device;
 
55
        int id;
 
56
        WacomStylusType type;
 
57
        char *name;
 
58
        const char *icon_name;
 
59
        GSettings *settings;
 
60
        gboolean has_eraser;
 
61
        int num_buttons;
 
62
};
 
63
 
 
64
static void     gsd_wacom_stylus_class_init  (GsdWacomStylusClass *klass);
 
65
static void     gsd_wacom_stylus_init        (GsdWacomStylus      *wacom_stylus);
 
66
static void     gsd_wacom_stylus_finalize    (GObject              *object);
 
67
 
 
68
G_DEFINE_TYPE (GsdWacomStylus, gsd_wacom_stylus, G_TYPE_OBJECT)
 
69
 
 
70
static void
 
71
gsd_wacom_stylus_class_init (GsdWacomStylusClass *klass)
 
72
{
 
73
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
74
 
 
75
        object_class->finalize = gsd_wacom_stylus_finalize;
 
76
 
 
77
        g_type_class_add_private (klass, sizeof (GsdWacomStylusPrivate));
 
78
}
 
79
 
 
80
static void
 
81
gsd_wacom_stylus_init (GsdWacomStylus *stylus)
 
82
{
 
83
        stylus->priv = GSD_WACOM_STYLUS_GET_PRIVATE (stylus);
 
84
}
 
85
 
 
86
static void
 
87
gsd_wacom_stylus_finalize (GObject *object)
 
88
{
 
89
        GsdWacomStylus *stylus;
 
90
        GsdWacomStylusPrivate *p;
 
91
 
 
92
        g_return_if_fail (object != NULL);
 
93
        g_return_if_fail (GSD_IS_WACOM_STYLUS (object));
 
94
 
 
95
        stylus = GSD_WACOM_STYLUS (object);
 
96
 
 
97
        g_return_if_fail (stylus->priv != NULL);
 
98
 
 
99
        p = stylus->priv;
 
100
 
 
101
        if (p->settings != NULL) {
 
102
                g_object_unref (p->settings);
 
103
                p->settings = NULL;
 
104
        }
 
105
 
 
106
        g_free (p->name);
 
107
        p->name = NULL;
 
108
 
 
109
        G_OBJECT_CLASS (gsd_wacom_stylus_parent_class)->finalize (object);
 
110
}
 
111
 
 
112
static const char *
 
113
get_icon_name_from_type (WacomStylusType type)
 
114
{
 
115
        switch (type) {
 
116
        case WSTYLUS_INKING:
 
117
        case WSTYLUS_STROKE:
 
118
                /* The stroke pen is the same as the inking pen with
 
119
                 * a different nib */
 
120
                return "wacom-stylus-inking";
 
121
        case WSTYLUS_AIRBRUSH:
 
122
                return "wacom-stylus-airbrush";
 
123
        case WSTYLUS_MARKER:
 
124
                return "wacom-stylus-art-pen";
 
125
        case WSTYLUS_CLASSIC:
 
126
                return "wacom-stylus-classic";
 
127
        default:
 
128
                return "wacom-stylus";
 
129
        }
 
130
}
 
131
 
 
132
static GsdWacomStylus *
 
133
gsd_wacom_stylus_new (GsdWacomDevice    *device,
 
134
                      const WacomStylus *wstylus,
 
135
                      GSettings         *settings)
 
136
{
 
137
        GsdWacomStylus *stylus;
 
138
 
 
139
        g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
 
140
        g_return_val_if_fail (wstylus != NULL, NULL);
 
141
 
 
142
        stylus = GSD_WACOM_STYLUS (g_object_new (GSD_TYPE_WACOM_STYLUS,
 
143
                                                 NULL));
 
144
        stylus->priv->device = device;
 
145
        stylus->priv->id = libwacom_stylus_get_id (wstylus);
 
146
        stylus->priv->name = g_strdup (libwacom_stylus_get_name (wstylus));
 
147
        stylus->priv->settings = settings;
 
148
        stylus->priv->type = libwacom_stylus_get_type (wstylus);
 
149
        stylus->priv->icon_name = get_icon_name_from_type (stylus->priv->type);
 
150
        stylus->priv->has_eraser = libwacom_stylus_has_eraser (wstylus);
 
151
        stylus->priv->num_buttons = libwacom_stylus_get_num_buttons (wstylus);
 
152
 
 
153
        return stylus;
 
154
}
 
155
 
 
156
GSettings *
 
157
gsd_wacom_stylus_get_settings (GsdWacomStylus *stylus)
 
158
{
 
159
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL);
 
160
 
 
161
        return stylus->priv->settings;
 
162
}
 
163
 
 
164
const char *
 
165
gsd_wacom_stylus_get_name (GsdWacomStylus *stylus)
 
166
{
 
167
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL);
 
168
 
 
169
        return stylus->priv->name;
 
170
}
 
171
 
 
172
const char *
 
173
gsd_wacom_stylus_get_icon_name (GsdWacomStylus *stylus)
 
174
{
 
175
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL);
 
176
 
 
177
        return stylus->priv->icon_name;
 
178
}
 
179
 
 
180
GsdWacomDevice *
 
181
gsd_wacom_stylus_get_device (GsdWacomStylus *stylus)
 
182
{
 
183
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), NULL);
 
184
 
 
185
        return stylus->priv->device;
 
186
}
 
187
 
 
188
gboolean
 
189
gsd_wacom_stylus_get_has_eraser (GsdWacomStylus *stylus)
 
190
{
 
191
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), FALSE);
 
192
 
 
193
        return stylus->priv->has_eraser;
 
194
}
 
195
 
 
196
guint
 
197
gsd_wacom_stylus_get_num_buttons (GsdWacomStylus *stylus)
 
198
{
 
199
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), -1);
 
200
 
 
201
        return stylus->priv->num_buttons;
 
202
}
 
203
 
 
204
GsdWacomStylusType
 
205
gsd_wacom_stylus_get_stylus_type (GsdWacomStylus *stylus)
 
206
{
 
207
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), WACOM_STYLUS_TYPE_UNKNOWN);
 
208
 
 
209
        switch (stylus->priv->type) {
 
210
        case WSTYLUS_UNKNOWN:
 
211
                return WACOM_STYLUS_TYPE_UNKNOWN;
 
212
        case WSTYLUS_GENERAL:
 
213
                return WACOM_STYLUS_TYPE_GENERAL;
 
214
        case WSTYLUS_INKING:
 
215
                return WACOM_STYLUS_TYPE_INKING;
 
216
        case WSTYLUS_AIRBRUSH:
 
217
                return WACOM_STYLUS_TYPE_AIRBRUSH;
 
218
        case WSTYLUS_CLASSIC:
 
219
                return WACOM_STYLUS_TYPE_CLASSIC;
 
220
        case WSTYLUS_MARKER:
 
221
                return WACOM_STYLUS_TYPE_MARKER;
 
222
        case WSTYLUS_STROKE:
 
223
                return WACOM_STYLUS_TYPE_STROKE;
 
224
        case WSTYLUS_PUCK:
 
225
                return WACOM_STYLUS_TYPE_PUCK;
 
226
        default:
 
227
                g_assert_not_reached ();
 
228
        }
 
229
 
 
230
        return WACOM_STYLUS_TYPE_UNKNOWN;
 
231
}
 
232
 
 
233
int
 
234
gsd_wacom_stylus_get_id (GsdWacomStylus *stylus)
 
235
{
 
236
        g_return_val_if_fail (GSD_IS_WACOM_STYLUS (stylus), -1);
 
237
 
 
238
        return stylus->priv->id;
 
239
}
 
240
 
 
241
/* Tablet buttons */
 
242
static GsdWacomTabletButton *
 
243
gsd_wacom_tablet_button_new (const char               *name,
 
244
                             const char               *id,
 
245
                             GsdWacomTabletButtonType  type,
 
246
                             int                       group_id)
 
247
{
 
248
        GsdWacomTabletButton *ret;
 
249
 
 
250
        ret = g_new0 (GsdWacomTabletButton, 1);
 
251
        ret->name = g_strdup (name);
 
252
        ret->id = g_strdup (id);
 
253
        ret->group_id = group_id;
 
254
        ret->type = type;
 
255
 
 
256
        return ret;
 
257
}
 
258
 
 
259
void
 
260
gsd_wacom_tablet_button_free (GsdWacomTabletButton *button)
 
261
{
 
262
        g_return_if_fail (button != NULL);
 
263
 
 
264
        g_free (button->name);
 
265
        g_free (button->id);
 
266
        g_free (button);
 
267
}
 
268
 
 
269
GsdWacomTabletButton *
 
270
gsd_wacom_tablet_button_copy (GsdWacomTabletButton *button)
 
271
{
 
272
        GsdWacomTabletButton *ret;
 
273
 
 
274
        g_return_val_if_fail (button != NULL, NULL);
 
275
 
 
276
        ret = g_new0 (GsdWacomTabletButton, 1);
 
277
        ret->name = g_strdup (button->name);
 
278
        ret->id = button->id;
 
279
        ret->type = button->type;
 
280
        ret->group_id = button->group_id;
 
281
 
 
282
        return ret;
 
283
}
 
284
 
 
285
#define GSD_WACOM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_WACOM_DEVICE, GsdWacomDevicePrivate))
 
286
 
 
287
/* we support two types of settings:
 
288
 * Tablet-wide settings: applied to each tool on the tablet. e.g. rotation
 
289
 * Tool-specific settings: applied to one tool only.
 
290
 */
 
291
#define SETTINGS_WACOM_DIR         "org.gnome.settings-daemon.peripherals.wacom"
 
292
#define SETTINGS_STYLUS_DIR        "stylus"
 
293
#define SETTINGS_ERASER_DIR        "eraser"
 
294
 
 
295
struct GsdWacomDevicePrivate
 
296
{
 
297
        GdkDevice *gdk_device;
 
298
        int device_id;
 
299
        int opcode;
 
300
 
 
301
        GsdWacomDeviceType type;
 
302
        char *name;
 
303
        char *icon_name;
 
304
        char *tool_name;
 
305
        gboolean reversible;
 
306
        gboolean is_screen_tablet;
 
307
        GList *styli;
 
308
        GsdWacomStylus *last_stylus;
 
309
        GList *buttons;
 
310
        GSettings *wacom_settings;
 
311
};
 
312
 
 
313
enum {
 
314
        PROP_0,
 
315
        PROP_GDK_DEVICE,
 
316
        PROP_LAST_STYLUS
 
317
};
 
318
 
 
319
static void     gsd_wacom_device_class_init  (GsdWacomDeviceClass *klass);
 
320
static void     gsd_wacom_device_init        (GsdWacomDevice      *wacom_device);
 
321
static void     gsd_wacom_device_finalize    (GObject              *object);
 
322
 
 
323
G_DEFINE_TYPE (GsdWacomDevice, gsd_wacom_device, G_TYPE_OBJECT)
 
324
 
 
325
static GdkFilterReturn
 
326
filter_events (XEvent         *xevent,
 
327
               GdkEvent       *event,
 
328
               GsdWacomDevice *device)
 
329
{
 
330
        XIEvent             *xiev;
 
331
        XIPropertyEvent     *pev;
 
332
        XGenericEventCookie *cookie;
 
333
        char                *name;
 
334
        int                  tool_id;
 
335
 
 
336
        /* verify we have a property event */
 
337
        if (xevent->type != GenericEvent)
 
338
                return GDK_FILTER_CONTINUE;
 
339
 
 
340
        cookie = &xevent->xcookie;
 
341
        if (cookie->extension != device->priv->opcode)
 
342
                return GDK_FILTER_CONTINUE;
 
343
 
 
344
        xiev = (XIEvent *) xevent->xcookie.data;
 
345
 
 
346
        if (xiev->evtype != XI_PropertyEvent)
 
347
                return GDK_FILTER_CONTINUE;
 
348
 
 
349
        pev = (XIPropertyEvent *) xiev;
 
350
 
 
351
        /* Is the event for us? */
 
352
        if (pev->deviceid != device->priv->device_id)
 
353
                return GDK_FILTER_CONTINUE;
 
354
 
 
355
        name = XGetAtomName (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), pev->property);
 
356
        if (name == NULL ||
 
357
            g_strcmp0 (name, WACOM_SERIAL_IDS_PROP) != 0) {
 
358
                return GDK_FILTER_CONTINUE;
 
359
        }
 
360
        XFree (name);
 
361
 
 
362
        tool_id = xdevice_get_last_tool_id (device->priv->device_id);
 
363
        if (tool_id == -1) {
 
364
                g_warning ("Failed to get value for changed stylus ID on device '%d", device->priv->device_id);
 
365
                return GDK_FILTER_CONTINUE;
 
366
        }
 
367
        gsd_wacom_device_set_current_stylus (device, tool_id);
 
368
 
 
369
        return GDK_FILTER_CONTINUE;
 
370
}
 
371
 
 
372
static gboolean
 
373
setup_property_notify (GsdWacomDevice *device)
 
374
{
 
375
        Display *dpy;
 
376
        XIEventMask evmask;
 
377
        unsigned char bitmask[2] = { 0 };
 
378
        int tool_id;
 
379
 
 
380
        XISetMask (bitmask, XI_PropertyEvent);
 
381
 
 
382
        evmask.deviceid = device->priv->device_id;
 
383
        evmask.mask_len = sizeof (bitmask);
 
384
        evmask.mask = bitmask;
 
385
 
 
386
        dpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
387
        XISelectEvents (dpy, DefaultRootWindow(dpy), &evmask, 1);
 
388
 
 
389
        gdk_window_add_filter (NULL,
 
390
                               (GdkFilterFunc) filter_events,
 
391
                               device);
 
392
 
 
393
        tool_id = xdevice_get_last_tool_id (device->priv->device_id);
 
394
        if (tool_id == -1) {
 
395
                g_warning ("Failed to get value for changed stylus ID on device '%d", device->priv->device_id);
 
396
                return TRUE;
 
397
        }
 
398
        gsd_wacom_device_set_current_stylus (device, tool_id);
 
399
 
 
400
        return TRUE;
 
401
}
 
402
 
 
403
static GsdWacomDeviceType
 
404
get_device_type (XDeviceInfo *dev)
 
405
{
 
406
        GsdWacomDeviceType ret;
 
407
        static Atom stylus, cursor, eraser, pad, touch, prop;
 
408
        XDevice *device;
 
409
        Atom realtype;
 
410
        int realformat;
 
411
        unsigned long nitems, bytes_after;
 
412
        unsigned char *data = NULL;
 
413
        int rc;
 
414
 
 
415
        ret = WACOM_TYPE_INVALID;
 
416
 
 
417
        if ((dev->use == IsXPointer) || (dev->use == IsXKeyboard))
 
418
                return ret;
 
419
 
 
420
        if (!stylus)
 
421
                stylus = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "STYLUS", False);
 
422
        if (!eraser)
 
423
                eraser = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "ERASER", False);
 
424
        if (!cursor)
 
425
                cursor = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "CURSOR", False);
 
426
        if (!pad)
 
427
                pad = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "PAD", False);
 
428
        if (!touch)
 
429
                touch = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "TOUCH", False);
 
430
        if (!prop)
 
431
                prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Wacom Tool Type", False);
 
432
 
 
433
        if (dev->type == stylus)
 
434
                ret = WACOM_TYPE_STYLUS;
 
435
        else if (dev->type == eraser)
 
436
                ret = WACOM_TYPE_ERASER;
 
437
        else if (dev->type == cursor)
 
438
                ret = WACOM_TYPE_CURSOR;
 
439
        else if (dev->type == pad)
 
440
                ret = WACOM_TYPE_PAD;
 
441
        else if (dev->type == touch)
 
442
                ret = WACOM_TYPE_TOUCH;
 
443
 
 
444
        if (ret == WACOM_TYPE_INVALID)
 
445
                return ret;
 
446
 
 
447
        /* There is currently no good way of detecting the driver for a device
 
448
         * other than checking for a driver-specific property.
 
449
         * Wacom Tool Type exists on all tools
 
450
         */
 
451
        gdk_error_trap_push ();
 
452
        device = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), dev->id);
 
453
        if (gdk_error_trap_pop () || (device == NULL))
 
454
                return ret;
 
455
 
 
456
        gdk_error_trap_push ();
 
457
 
 
458
        rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
 
459
                                 device, prop, 0, 1, False,
 
460
                                 XA_ATOM, &realtype, &realformat, &nitems,
 
461
                                 &bytes_after, &data);
 
462
        if (gdk_error_trap_pop () || rc != Success || realtype == None) {
 
463
                XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device);
 
464
                ret = WACOM_TYPE_INVALID;
 
465
        }
 
466
 
 
467
        XFree (data);
 
468
 
 
469
        return ret;
 
470
}
 
471
 
 
472
/* Finds an output which matches the given EDID information. Any NULL
 
473
 * parameter will be interpreted to match any value.
 
474
 */
 
475
static GnomeRROutputInfo*
 
476
find_output_by_edid (const gchar *vendor, const gchar *product, const gchar *serial)
 
477
{
 
478
        GError *error = NULL;
 
479
        GnomeRRScreen *rr_screen;
 
480
        GnomeRRConfig *rr_config;
 
481
        GnomeRROutputInfo **rr_output_info;
 
482
        GnomeRROutputInfo *retval = NULL;
 
483
 
 
484
        /* TODO: Check the value of 'error' */
 
485
        rr_screen = gnome_rr_screen_new (gdk_screen_get_default (), &error);
 
486
        rr_config = gnome_rr_config_new_current (rr_screen, &error);
 
487
        rr_output_info = gnome_rr_config_get_outputs (rr_config);
 
488
 
 
489
        for (; *rr_output_info != NULL; rr_output_info++) {
 
490
                gchar *o_vendor;
 
491
                gchar *o_product;
 
492
                gchar *o_serial;
 
493
                gboolean match;
 
494
 
 
495
                o_vendor = g_malloc0 (4);
 
496
                gnome_rr_output_info_get_vendor (*rr_output_info, o_vendor);
 
497
                o_product = g_strdup_printf ("%d", gnome_rr_output_info_get_product (*rr_output_info));
 
498
                o_serial  = g_strdup_printf ("%d", gnome_rr_output_info_get_serial  (*rr_output_info));
 
499
 
 
500
                g_debug ("Checking for match between '%s','%s','%s' and '%s','%s','%s'", \
 
501
                         vendor,product,serial, o_vendor,o_product,o_serial);
 
502
 
 
503
                match = (vendor  == NULL || g_strcmp0 (vendor,  o_vendor)  == 0) && \
 
504
                        (product == NULL || g_strcmp0 (product, o_product) == 0) && \
 
505
                        (serial  == NULL || g_strcmp0 (serial,  o_serial)  == 0);
 
506
 
 
507
                g_free (o_vendor);
 
508
                g_free (o_product);
 
509
                g_free (o_serial);
 
510
 
 
511
                if (match) {
 
512
                        retval = g_object_ref (*rr_output_info);
 
513
                        break;
 
514
                }
 
515
        }
 
516
 
 
517
        g_object_unref (rr_config);
 
518
 
 
519
        return retval;
 
520
}
 
521
 
 
522
static GnomeRROutputInfo*
 
523
find_output_by_heuristic (GsdWacomDevice *device)
 
524
{
 
525
        GnomeRROutputInfo *rr_output_info;
 
526
 
 
527
        /* TODO: This heuristic will fail for non-Wacom display
 
528
         * tablets and may give the wrong result if multiple Wacom
 
529
         * display tablets are connected.
 
530
         */
 
531
        rr_output_info = find_output_by_edid("WAC", NULL, NULL);
 
532
        return rr_output_info;
 
533
}
 
534
 
 
535
static GnomeRROutputInfo*
 
536
find_output_by_display (GsdWacomDevice *device)
 
537
{
 
538
        gsize n;
 
539
        GSettings *tablet;
 
540
        GVariant *display;
 
541
        const gchar **edid;
 
542
 
 
543
        if (device == NULL)
 
544
                return NULL;
 
545
 
 
546
        tablet   = device->priv->wacom_settings;
 
547
        display  = g_settings_get_value (tablet, "display");
 
548
        edid     = g_variant_get_strv (display, &n);
 
549
 
 
550
        if (n != 3) {
 
551
                g_critical ("Expected 'display' key to store %d values; got %"G_GSIZE_FORMAT".", 3, n);
 
552
                return NULL;
 
553
        }
 
554
 
 
555
        if (strlen(edid[0]) == 0 || strlen(edid[1]) == 0 || strlen(edid[2]) == 0) {
 
556
                g_warning ("EDID not completely defined.");
 
557
                return NULL;
 
558
        }
 
559
 
 
560
        return find_output_by_edid (edid[0], edid[1], edid[2]);
 
561
}
 
562
 
 
563
static void
 
564
set_display_by_output (GsdWacomDevice    *device,
 
565
                       GnomeRROutputInfo *rr_output_info)
 
566
{
 
567
        GSettings   *tablet;
 
568
        GVariant    *c_array;
 
569
        GVariant    *n_array;
 
570
        gsize        nvalues;
 
571
        gchar       *o_vendor, *o_product, *o_serial;
 
572
        const gchar *values[3];
 
573
 
 
574
        tablet  = gsd_wacom_device_get_settings (device);
 
575
        c_array = g_settings_get_value (tablet, "display");
 
576
        g_variant_get_strv (c_array, &nvalues);
 
577
        if (nvalues != 3) {
 
578
                g_warning("Unable set set display property. Got %"G_GSIZE_FORMAT" items; expected %d items.\n", nvalues, 4);
 
579
                return;
 
580
        }
 
581
 
 
582
        if (rr_output_info == NULL)
 
583
        {
 
584
                o_vendor  = g_strdup ("");
 
585
                o_product = g_strdup ("");
 
586
                o_serial  = g_strdup ("");
 
587
        }
 
588
        else
 
589
        {
 
590
                o_vendor = g_malloc0 (4);
 
591
                gnome_rr_output_info_get_vendor (rr_output_info, o_vendor);
 
592
                o_product = g_strdup_printf ("%d", gnome_rr_output_info_get_product (rr_output_info));
 
593
                o_serial  = g_strdup_printf ("%d", gnome_rr_output_info_get_serial  (rr_output_info));
 
594
        }
 
595
 
 
596
        values[0] = o_vendor;
 
597
        values[1] = o_product;
 
598
        values[2] = o_serial;
 
599
        n_array = g_variant_new_strv((const gchar * const *) &values, 3);
 
600
        g_settings_set_value (tablet, "display", n_array);
 
601
 
 
602
        g_free (o_vendor);
 
603
        g_free (o_product);
 
604
        g_free (o_serial);
 
605
}
 
606
 
 
607
static GnomeRROutputInfo*
 
608
find_output (GsdWacomDevice *device)
 
609
{
 
610
        GnomeRROutputInfo *rr_output_info;
 
611
 
 
612
        rr_output_info = find_output_by_display(device);
 
613
 
 
614
        if (rr_output_info == NULL)
 
615
        {
 
616
                g_warning ("No strict EDID match was found.");
 
617
 
 
618
                if (gsd_wacom_device_is_screen_tablet (device))
 
619
                {
 
620
                        rr_output_info = find_output_by_heuristic (device);
 
621
                        if (rr_output_info == NULL)
 
622
                        {
 
623
                                g_warning ("No fuzzy match based on heuristics was found.");
 
624
                        }
 
625
                        else
 
626
                        {
 
627
                                g_warning("Automatically mapping tablet to heuristically-found display.");
 
628
                                set_display_by_output (device, rr_output_info);
 
629
                        }
 
630
                }
 
631
        }
 
632
 
 
633
        return rr_output_info;
 
634
}
 
635
 
 
636
static void
 
637
calculate_transformation_matrix (const GdkRectangle mapped, const GdkRectangle desktop, float matrix[NUM_ELEMS_MATRIX])
 
638
{
 
639
        float x_scale = (float)mapped.x / desktop.width;
 
640
        float y_scale = (float)mapped.y / desktop.height;
 
641
        float width_scale  = (float)mapped.width / desktop.width;
 
642
        float height_scale = (float)mapped.height / desktop.height;
 
643
 
 
644
        matrix[0] = width_scale;
 
645
        matrix[1] = 0.0f;
 
646
        matrix[2] = x_scale;
 
647
 
 
648
        matrix[3] = 0.0f;
 
649
        matrix[4] = height_scale;
 
650
        matrix[5] = y_scale;
 
651
 
 
652
        matrix[6] = 0.0f;
 
653
        matrix[7] = 0.0f;
 
654
        matrix[8] = 1.0f;
 
655
 
 
656
        g_debug ("Matrix is %f,%f,%f,%f,%f,%f,%f,%f,%f.",
 
657
                 matrix[0], matrix[1], matrix[2],
 
658
                 matrix[3], matrix[4], matrix[5],
 
659
                 matrix[6], matrix[7], matrix[8]);
 
660
 
 
661
        return;
 
662
}
 
663
 
 
664
gint
 
665
gsd_wacom_device_get_display_monitor (GsdWacomDevice *device)
 
666
{
 
667
        gint area[4];
 
668
        gboolean is_active;
 
669
        GnomeRROutputInfo *rr_output_info;
 
670
 
 
671
        rr_output_info = find_output(device);
 
672
        if (rr_output_info == NULL)
 
673
                return -1;
 
674
 
 
675
        is_active = gnome_rr_output_info_is_active (rr_output_info);
 
676
        gnome_rr_output_info_get_geometry (rr_output_info, &area[0], &area[1], &area[2], &area[3]);
 
677
 
 
678
        g_object_unref (rr_output_info);
 
679
 
 
680
        if (!is_active)
 
681
        {
 
682
                g_warning ("Output is not active.");
 
683
                return -1;
 
684
        }
 
685
 
 
686
        if (area[2] <= 0 || area[3] <= 0)
 
687
        {
 
688
                g_warning ("Output has non-positive area.");
 
689
                return -1;
 
690
        }
 
691
 
 
692
        g_debug ("Area: %d,%d %dx%d", area[0], area[1], area[2], area[3]);
 
693
        return gdk_screen_get_monitor_at_point (gdk_screen_get_default (), area[0], area[1]);
 
694
}
 
695
 
 
696
gboolean
 
697
gsd_wacom_device_get_display_matrix (GsdWacomDevice *device, float matrix[NUM_ELEMS_MATRIX])
 
698
{
 
699
        int monitor;
 
700
        GdkRectangle display;
 
701
        GdkRectangle desktop;
 
702
        GdkScreen *screen = gdk_screen_get_default ();
 
703
 
 
704
        matrix[0] = 1.0f;
 
705
        matrix[1] = 0.0f;
 
706
        matrix[2] = 0.0f;
 
707
        matrix[3] = 0.0f;
 
708
        matrix[4] = 1.0f;
 
709
        matrix[5] = 0.0f;
 
710
        matrix[6] = 0.0f;
 
711
        matrix[7] = 0.0f;
 
712
        matrix[8] = 1.0f;
 
713
 
 
714
        monitor = gsd_wacom_device_get_display_monitor (device);
 
715
        if (monitor < 0)
 
716
                return FALSE;
 
717
 
 
718
        desktop.x = 0;
 
719
        desktop.y = 0;
 
720
        desktop.width = gdk_screen_get_width (screen);
 
721
        desktop.height = gdk_screen_get_height (screen);
 
722
 
 
723
        gdk_screen_get_monitor_geometry (screen, monitor, &display);
 
724
        calculate_transformation_matrix (display, desktop, matrix);
 
725
        return TRUE;
 
726
}
 
727
 
 
728
static void
 
729
add_stylus_to_device (GsdWacomDevice *device,
 
730
                      const char     *settings_path,
 
731
                      int             id)
 
732
{
 
733
        const WacomStylus *wstylus;
 
734
 
 
735
        wstylus = libwacom_stylus_get_for_id (db, id);
 
736
        if (wstylus) {
 
737
                GsdWacomStylus *stylus;
 
738
                char *stylus_settings_path;
 
739
                GSettings *settings;
 
740
 
 
741
                if (device->priv->type == WACOM_TYPE_STYLUS &&
 
742
                    libwacom_stylus_is_eraser (wstylus))
 
743
                        return;
 
744
                if (device->priv->type == WACOM_TYPE_ERASER &&
 
745
                    libwacom_stylus_is_eraser (wstylus) == FALSE)
 
746
                        return;
 
747
 
 
748
                stylus_settings_path = g_strdup_printf ("%s0x%x/", settings_path, id);
 
749
                if (device->priv->type == WACOM_TYPE_STYLUS) {
 
750
                        settings = g_settings_new_with_path (WACOM_STYLUS_SCHEMA, stylus_settings_path);
 
751
                        stylus = gsd_wacom_stylus_new (device, wstylus, settings);
 
752
                } else {
 
753
                        settings = g_settings_new_with_path (WACOM_ERASER_SCHEMA, stylus_settings_path);
 
754
                        stylus = gsd_wacom_stylus_new (device, wstylus, settings);
 
755
                }
 
756
                g_free (stylus_settings_path);
 
757
                device->priv->styli = g_list_prepend (device->priv->styli, stylus);
 
758
        }
 
759
}
 
760
 
 
761
static int
 
762
flags_to_group (WacomButtonFlags flags)
 
763
{
 
764
        if (flags & WACOM_BUTTON_RING_MODESWITCH)
 
765
                return 1;
 
766
        if (flags & WACOM_BUTTON_RING2_MODESWITCH)
 
767
                return 2;
 
768
        if (flags & WACOM_BUTTON_TOUCHSTRIP_MODESWITCH)
 
769
                return 3;
 
770
        if (flags & WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH)
 
771
                return 4;
 
772
 
 
773
        return 0;
 
774
}
 
775
 
 
776
static GList *
 
777
gsd_wacom_device_add_ring_modes (WacomDevice *wacom_device,
 
778
                                 WacomButtonFlags  direction)
 
779
{
 
780
        GList *l;
 
781
        guint num_modes;
 
782
        guint i;
 
783
        char *name, *id;
 
784
 
 
785
        l = NULL;
 
786
 
 
787
        if ((direction & WACOM_BUTTON_POSITION_LEFT) && libwacom_has_ring (wacom_device)) {
 
788
                num_modes = libwacom_get_ring_num_modes (wacom_device);
 
789
                for (i = 1; i <= num_modes; i++) {
 
790
                        name = g_strdup_printf (_("Left Ring Mode #%d"), i);
 
791
                        id = g_strdup_printf ("left-ring-mode-%d", i);
 
792
                        l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_ELEVATOR, flags_to_group (WACOM_BUTTON_RING_MODESWITCH)));
 
793
                }
 
794
        } else if ((direction & WACOM_BUTTON_POSITION_RIGHT) && libwacom_has_ring2 (wacom_device)) {
 
795
                num_modes = libwacom_get_ring2_num_modes (wacom_device);
 
796
                for (i = 1; i <= num_modes; i++) {
 
797
                        name = g_strdup_printf (_("Right Ring Mode #%d"), i);
 
798
                        id = g_strdup_printf ("right-ring-mode-%d", i);
 
799
                        l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_ELEVATOR, flags_to_group (WACOM_BUTTON_RING2_MODESWITCH)));
 
800
                }
 
801
        }
 
802
 
 
803
        return l;
 
804
}
 
805
 
 
806
static GList *
 
807
gsd_wacom_device_add_strip_modes (WacomDevice *wacom_device,
 
808
                                  WacomButtonFlags  direction)
 
809
{
 
810
        GList *l;
 
811
        guint num_modes;
 
812
        guint num_strips;
 
813
        guint i;
 
814
        char *name, *id;
 
815
 
 
816
        l = NULL;
 
817
        num_strips = libwacom_get_num_strips (wacom_device);
 
818
        if (num_strips > 2)
 
819
                g_warning ("Unhandled number of touchstrips: %d", num_strips);
 
820
 
 
821
        if ((direction & WACOM_BUTTON_POSITION_LEFT) && num_strips >= 1) {
 
822
                num_modes = libwacom_get_strips_num_modes (wacom_device);
 
823
                for (i = 1; i <= num_modes; i++) {
 
824
                        name = g_strdup_printf (_("Left Touchstrip Mode #%d"), i);
 
825
                        id = g_strdup_printf ("left-strip-mode-%d", i);
 
826
                        l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_ELEVATOR, flags_to_group (WACOM_BUTTON_TOUCHSTRIP_MODESWITCH)));
 
827
                }
 
828
        } else if ((direction & WACOM_BUTTON_POSITION_RIGHT) && num_strips >= 2) {
 
829
                num_modes = libwacom_get_strips_num_modes (wacom_device);
 
830
                for (i = 1; i <= num_modes; i++) {
 
831
                        name = g_strdup_printf (_("Right Touchstrip Mode #%d"), i);
 
832
                        id = g_strdup_printf ("right-strip-mode-%d", i);
 
833
                        l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_ELEVATOR, flags_to_group (WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH)));
 
834
                }
 
835
        }
 
836
 
 
837
        return l;
 
838
}
 
839
 
 
840
static char *
 
841
gsd_wacom_device_modeswitch_name (WacomButtonFlags flags,
 
842
                                  guint button_num)
 
843
{
 
844
        if (flags & WACOM_BUTTON_RINGS_MODESWITCH) {
 
845
                if (flags & WACOM_BUTTON_POSITION_LEFT)
 
846
                        return g_strdup_printf (_("Left Touchring Mode Switch"));
 
847
                else
 
848
                        return g_strdup_printf (_("Right Touchring Mode Switch"));
 
849
        } else if (flags & WACOM_BUTTON_TOUCHSTRIPS_MODESWITCH) {
 
850
                if (flags & WACOM_BUTTON_POSITION_LEFT)
 
851
                        return g_strdup_printf (_("Left Touchstrip Mode Switch"));
 
852
                else
 
853
                        return g_strdup_printf (_("Right Touchstrip Mode Switch"));
 
854
        }
 
855
 
 
856
        g_warning ("Unhandled modeswitch and direction combination");
 
857
 
 
858
        return g_strdup_printf (_("Mode Switch #%d"), button_num);
 
859
}
 
860
 
 
861
static GList *
 
862
gsd_wacom_device_add_buttons_dir (WacomDevice      *wacom_device,
 
863
                                  WacomButtonFlags  direction,
 
864
                                  const char       *button_str,
 
865
                                  const char       *button_str_id)
 
866
{
 
867
        GList *l;
 
868
        guint num_buttons, i, button_num;
 
869
        char *name, *id;
 
870
 
 
871
        l = NULL;
 
872
        button_num = 1;
 
873
        num_buttons = libwacom_get_num_buttons (wacom_device);
 
874
        for (i = 'A'; i < 'A' + num_buttons; i++) {
 
875
                WacomButtonFlags flags;
 
876
 
 
877
                flags = libwacom_get_button_flag (wacom_device, i);
 
878
                if (!(flags & direction))
 
879
                        continue;
 
880
                /* Ignore mode switches */
 
881
                if (flags & WACOM_BUTTON_MODESWITCH)
 
882
                        continue;
 
883
 
 
884
                name = g_strdup_printf (button_str, button_num++);
 
885
                id = g_strdup_printf ("%s%c", button_str_id, i);
 
886
                l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_NORMAL, flags_to_group (flags)));
 
887
                g_free (name);
 
888
                g_free (id);
 
889
        }
 
890
 
 
891
        /* Handle modeswitches */
 
892
        for (i = 'A'; i < 'A' + num_buttons; i++) {
 
893
                WacomButtonFlags flags;
 
894
 
 
895
                flags = libwacom_get_button_flag (wacom_device, i);
 
896
                if (!(flags & direction))
 
897
                        continue;
 
898
                /* Ignore non-mode switches */
 
899
                if (flags & WACOM_BUTTON_MODESWITCH) {
 
900
                        char *name, *id;
 
901
 
 
902
                        name = gsd_wacom_device_modeswitch_name (flags, button_num++);
 
903
                        id = g_strdup_printf ("%s%c", button_str_id, i);
 
904
                        l = g_list_append (l, gsd_wacom_tablet_button_new (name, id, WACOM_TABLET_BUTTON_TYPE_HARDCODED, flags_to_group (flags)));
 
905
                        g_free (name);
 
906
                        g_free (id);
 
907
 
 
908
                        if (flags & WACOM_BUTTON_RINGS_MODESWITCH)
 
909
                                l = g_list_concat (l, gsd_wacom_device_add_ring_modes (wacom_device, direction));
 
910
                        else if (flags & WACOM_BUTTON_TOUCHSTRIPS_MODESWITCH)
 
911
                                l = g_list_concat (l, gsd_wacom_device_add_strip_modes (wacom_device, direction));
 
912
                        else
 
913
                                g_warning ("Unhandled modeswitches");
 
914
                }
 
915
        }
 
916
 
 
917
        return l;
 
918
}
 
919
 
 
920
static void
 
921
gsd_wacom_device_add_buttons (GsdWacomDevice *device,
 
922
                              WacomDevice    *wacom_device)
 
923
{
 
924
        GList *l, *ret;
 
925
 
 
926
        ret = NULL;
 
927
 
 
928
        l = gsd_wacom_device_add_buttons_dir (wacom_device, WACOM_BUTTON_POSITION_LEFT, _("Left Button #%d"), "left-button");
 
929
        if (l)
 
930
                ret = l;
 
931
        l = gsd_wacom_device_add_buttons_dir (wacom_device, WACOM_BUTTON_POSITION_RIGHT, _("Right Button #%d"), "right-button");
 
932
        if (l)
 
933
                ret = g_list_concat (ret, l);
 
934
        l = gsd_wacom_device_add_buttons_dir (wacom_device, WACOM_BUTTON_POSITION_TOP, _("Top Button #%d"), "top-button");
 
935
        if (l)
 
936
                ret = g_list_concat (ret, l);
 
937
        l = gsd_wacom_device_add_buttons_dir (wacom_device, WACOM_BUTTON_POSITION_BOTTOM, _("Bottom Button #%d"), "bottom-button");
 
938
        if (l)
 
939
                ret = g_list_concat (ret, l);
 
940
 
 
941
        device->priv->buttons = ret;
 
942
}
 
943
 
 
944
static void
 
945
gsd_wacom_device_update_from_db (GsdWacomDevice *device,
 
946
                                 WacomDevice    *wacom_device,
 
947
                                 const char     *identifier)
 
948
{
 
949
        char *settings_path;
 
950
 
 
951
        settings_path = g_strdup_printf (WACOM_DEVICE_CONFIG_BASE, libwacom_get_match (wacom_device));
 
952
        device->priv->wacom_settings = g_settings_new_with_path (WACOM_TABLET_SCHEMA,
 
953
                                                                 settings_path);
 
954
 
 
955
        device->priv->name = g_strdup (libwacom_get_name (wacom_device));
 
956
        device->priv->reversible = libwacom_is_reversible (wacom_device);
 
957
        device->priv->is_screen_tablet = libwacom_is_builtin (wacom_device);
 
958
        if (device->priv->is_screen_tablet) {
 
959
                if (libwacom_get_class (wacom_device) == WCLASS_CINTIQ)
 
960
                        device->priv->icon_name = g_strdup ("wacom-tablet-cintiq");
 
961
                else
 
962
                        device->priv->icon_name = g_strdup ("wacom-tablet-pc");
 
963
        } else {
 
964
                device->priv->icon_name = g_strdup ("wacom-tablet");
 
965
        }
 
966
 
 
967
        if (device->priv->type == WACOM_TYPE_PAD)
 
968
                gsd_wacom_device_add_buttons (device, wacom_device);
 
969
 
 
970
        if (device->priv->type == WACOM_TYPE_STYLUS ||
 
971
            device->priv->type == WACOM_TYPE_ERASER) {
 
972
                int *ids;
 
973
                int num_styli;
 
974
                guint i;
 
975
 
 
976
                ids = libwacom_get_supported_styli(wacom_device, &num_styli);
 
977
                for (i = 0; i < num_styli; i++)
 
978
                        add_stylus_to_device (device, settings_path, ids[i]);
 
979
                /* Create a fallback stylus if we don't have one */
 
980
                if (num_styli == 0)
 
981
                        add_stylus_to_device (device, settings_path,
 
982
                                              device->priv->type == WACOM_TYPE_STYLUS ?
 
983
                                              WACOM_STYLUS_FALLBACK_ID : WACOM_ERASER_FALLBACK_ID);
 
984
 
 
985
                device->priv->styli = g_list_reverse (device->priv->styli);
 
986
        }
 
987
        g_free (settings_path);
 
988
}
 
989
 
 
990
static GObject *
 
991
gsd_wacom_device_constructor (GType                     type,
 
992
                              guint                      n_construct_properties,
 
993
                              GObjectConstructParam     *construct_properties)
 
994
{
 
995
        GsdWacomDevice *device;
 
996
        GdkDeviceManager *device_manager;
 
997
        XDeviceInfo *device_info;
 
998
        WacomDevice *wacom_device;
 
999
        int n_devices;
 
1000
        guint i;
 
1001
        char *path;
 
1002
 
 
1003
        device = GSD_WACOM_DEVICE (G_OBJECT_CLASS (gsd_wacom_device_parent_class)->constructor (type,
 
1004
                                                                                                n_construct_properties,
 
1005
                                                                                                construct_properties));
 
1006
 
 
1007
        if (device->priv->gdk_device == NULL)
 
1008
                return G_OBJECT (device);
 
1009
 
 
1010
        device_manager = gdk_display_get_device_manager (gdk_display_get_default ());
 
1011
        g_object_get (device_manager, "opcode", &device->priv->opcode, NULL);
 
1012
 
 
1013
        g_object_get (device->priv->gdk_device, "device-id", &device->priv->device_id, NULL);
 
1014
 
 
1015
        device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices);
 
1016
        if (device_info == NULL) {
 
1017
                g_warning ("Could not list any input devices through XListInputDevices()");
 
1018
                goto end;
 
1019
        }
 
1020
 
 
1021
        for (i = 0; i < n_devices; i++) {
 
1022
                if (device_info[i].id == device->priv->device_id) {
 
1023
                        device->priv->type = get_device_type (&device_info[i]);
 
1024
                        device->priv->tool_name = g_strdup (device_info[i].name);
 
1025
                        break;
 
1026
                }
 
1027
        }
 
1028
 
 
1029
        XFreeDeviceList (device_info);
 
1030
 
 
1031
        if (device->priv->type == WACOM_TYPE_INVALID)
 
1032
                goto end;
 
1033
 
 
1034
        path = xdevice_get_device_node (device->priv->device_id);
 
1035
        if (path == NULL) {
 
1036
                g_warning ("Could not get the device node path for ID '%d'", device->priv->device_id);
 
1037
                device->priv->type = WACOM_TYPE_INVALID;
 
1038
                goto end;
 
1039
        }
 
1040
 
 
1041
        if (db == NULL)
 
1042
                db = libwacom_database_new ();
 
1043
 
 
1044
        wacom_device = libwacom_new_from_path (db, path, FALSE, NULL);
 
1045
        if (!wacom_device) {
 
1046
                WacomError *wacom_error;
 
1047
 
 
1048
                g_debug ("Creating fallback driver for wacom tablet '%s' ('%s')",
 
1049
                         gdk_device_get_name (device->priv->gdk_device),
 
1050
                         path);
 
1051
 
 
1052
                wacom_error = libwacom_error_new ();
 
1053
                wacom_device = libwacom_new_from_path (db, path, TRUE, wacom_error);
 
1054
                if (wacom_device == NULL) {
 
1055
                        g_warning ("Failed to create fallback wacom device for '%s': %s (%d)",
 
1056
                                   path,
 
1057
                                   libwacom_error_get_message (wacom_error),
 
1058
                                   libwacom_error_get_code (wacom_error));
 
1059
                        g_free (path);
 
1060
                        libwacom_error_free (&wacom_error);
 
1061
                        device->priv->type = WACOM_TYPE_INVALID;
 
1062
                        goto end;
 
1063
                }
 
1064
        }
 
1065
 
 
1066
        gsd_wacom_device_update_from_db (device, wacom_device, path);
 
1067
        libwacom_destroy (wacom_device);
 
1068
        g_free (path);
 
1069
 
 
1070
        if (device->priv->type == WACOM_TYPE_STYLUS ||
 
1071
            device->priv->type == WACOM_TYPE_ERASER) {
 
1072
                setup_property_notify (device);
 
1073
        }
 
1074
 
 
1075
end:
 
1076
        return G_OBJECT (device);
 
1077
}
 
1078
 
 
1079
static void
 
1080
gsd_wacom_device_set_property (GObject        *object,
 
1081
                               guint           prop_id,
 
1082
                               const GValue   *value,
 
1083
                               GParamSpec     *pspec)
 
1084
{
 
1085
        GsdWacomDevice *device;
 
1086
 
 
1087
        device = GSD_WACOM_DEVICE (object);
 
1088
 
 
1089
        switch (prop_id) {
 
1090
        case PROP_GDK_DEVICE:
 
1091
                device->priv->gdk_device = g_value_get_pointer (value);
 
1092
                break;
 
1093
        case PROP_LAST_STYLUS:
 
1094
                device->priv->last_stylus = g_value_get_pointer (value);
 
1095
                break;
 
1096
        default:
 
1097
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
1098
                break;
 
1099
        }
 
1100
}
 
1101
 
 
1102
static void
 
1103
gsd_wacom_device_get_property (GObject        *object,
 
1104
                               guint           prop_id,
 
1105
                               GValue         *value,
 
1106
                               GParamSpec     *pspec)
 
1107
{
 
1108
        GsdWacomDevice *device;
 
1109
 
 
1110
        device = GSD_WACOM_DEVICE (object);
 
1111
 
 
1112
        switch (prop_id) {
 
1113
        case PROP_GDK_DEVICE:
 
1114
                g_value_set_pointer (value, device->priv->gdk_device);
 
1115
                break;
 
1116
        case PROP_LAST_STYLUS:
 
1117
                g_value_set_pointer (value, device->priv->last_stylus);
 
1118
                break;
 
1119
        default:
 
1120
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
1121
                break;
 
1122
        }
 
1123
}
 
1124
 
 
1125
static void
 
1126
gsd_wacom_device_class_init (GsdWacomDeviceClass *klass)
 
1127
{
 
1128
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
1129
 
 
1130
        object_class->constructor = gsd_wacom_device_constructor;
 
1131
        object_class->finalize = gsd_wacom_device_finalize;
 
1132
        object_class->set_property = gsd_wacom_device_set_property;
 
1133
        object_class->get_property = gsd_wacom_device_get_property;
 
1134
 
 
1135
        g_type_class_add_private (klass, sizeof (GsdWacomDevicePrivate));
 
1136
 
 
1137
        g_object_class_install_property (object_class, PROP_GDK_DEVICE,
 
1138
                                         g_param_spec_pointer ("gdk-device", "gdk-device", "gdk-device",
 
1139
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
1140
        g_object_class_install_property (object_class, PROP_LAST_STYLUS,
 
1141
                                         g_param_spec_pointer ("last-stylus", "last-stylus", "last-stylus",
 
1142
                                                               G_PARAM_READWRITE));
 
1143
}
 
1144
 
 
1145
static void
 
1146
gsd_wacom_device_init (GsdWacomDevice *device)
 
1147
{
 
1148
        device->priv = GSD_WACOM_DEVICE_GET_PRIVATE (device);
 
1149
        device->priv->type = WACOM_TYPE_INVALID;
 
1150
}
 
1151
 
 
1152
static void
 
1153
gsd_wacom_device_finalize (GObject *object)
 
1154
{
 
1155
        GsdWacomDevice *device;
 
1156
        GsdWacomDevicePrivate *p;
 
1157
 
 
1158
        g_return_if_fail (object != NULL);
 
1159
        g_return_if_fail (GSD_IS_WACOM_DEVICE (object));
 
1160
 
 
1161
        device = GSD_WACOM_DEVICE (object);
 
1162
 
 
1163
        g_return_if_fail (device->priv != NULL);
 
1164
 
 
1165
        p = device->priv;
 
1166
 
 
1167
        if (p->wacom_settings != NULL) {
 
1168
                g_object_unref (p->wacom_settings);
 
1169
                p->wacom_settings = NULL;
 
1170
        }
 
1171
 
 
1172
        g_list_foreach (p->buttons, (GFunc) gsd_wacom_tablet_button_free, NULL);
 
1173
        g_list_free (p->buttons);
 
1174
 
 
1175
        g_free (p->name);
 
1176
        p->name = NULL;
 
1177
 
 
1178
        g_free (p->tool_name);
 
1179
        p->tool_name = NULL;
 
1180
 
 
1181
        g_free (p->icon_name);
 
1182
        p->icon_name = NULL;
 
1183
 
 
1184
        gdk_window_remove_filter (NULL,
 
1185
                                  (GdkFilterFunc) filter_events,
 
1186
                                  device);
 
1187
 
 
1188
        G_OBJECT_CLASS (gsd_wacom_device_parent_class)->finalize (object);
 
1189
}
 
1190
 
 
1191
GsdWacomDevice *
 
1192
gsd_wacom_device_new (GdkDevice *device)
 
1193
{
 
1194
        return GSD_WACOM_DEVICE (g_object_new (GSD_TYPE_WACOM_DEVICE,
 
1195
                                               "gdk-device", device,
 
1196
                                               NULL));
 
1197
}
 
1198
 
 
1199
GList *
 
1200
gsd_wacom_device_list_styli (GsdWacomDevice *device)
 
1201
{
 
1202
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1203
 
 
1204
        return g_list_copy (device->priv->styli);
 
1205
}
 
1206
 
 
1207
GsdWacomStylus *
 
1208
gsd_wacom_device_get_stylus_for_type (GsdWacomDevice     *device,
 
1209
                                      GsdWacomStylusType  type)
 
1210
{
 
1211
        GList *l;
 
1212
 
 
1213
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1214
 
 
1215
        for (l = device->priv->styli; l != NULL; l = l->next) {
 
1216
                GsdWacomStylus *stylus = l->data;
 
1217
 
 
1218
                if (gsd_wacom_stylus_get_stylus_type (stylus) == type)
 
1219
                        return stylus;
 
1220
        }
 
1221
        return NULL;
 
1222
}
 
1223
 
 
1224
const char *
 
1225
gsd_wacom_device_get_name (GsdWacomDevice *device)
 
1226
{
 
1227
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1228
 
 
1229
        return device->priv->name;
 
1230
}
 
1231
 
 
1232
const char *
 
1233
gsd_wacom_device_get_icon_name (GsdWacomDevice *device)
 
1234
{
 
1235
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1236
 
 
1237
        return device->priv->icon_name;
 
1238
}
 
1239
 
 
1240
const char *
 
1241
gsd_wacom_device_get_tool_name (GsdWacomDevice *device)
 
1242
{
 
1243
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1244
 
 
1245
        return device->priv->tool_name;
 
1246
}
 
1247
 
 
1248
gboolean
 
1249
gsd_wacom_device_reversible (GsdWacomDevice *device)
 
1250
{
 
1251
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE);
 
1252
 
 
1253
        return device->priv->reversible;
 
1254
}
 
1255
 
 
1256
gboolean
 
1257
gsd_wacom_device_is_screen_tablet (GsdWacomDevice *device)
 
1258
{
 
1259
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), FALSE);
 
1260
 
 
1261
        return device->priv->is_screen_tablet;
 
1262
}
 
1263
 
 
1264
GSettings *
 
1265
gsd_wacom_device_get_settings (GsdWacomDevice *device)
 
1266
{
 
1267
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1268
 
 
1269
        return device->priv->wacom_settings;
 
1270
}
 
1271
 
 
1272
void
 
1273
gsd_wacom_device_set_current_stylus (GsdWacomDevice *device,
 
1274
                                     int             stylus_id)
 
1275
{
 
1276
        GList *l;
 
1277
        GsdWacomStylus *stylus;
 
1278
 
 
1279
        g_return_if_fail (GSD_IS_WACOM_DEVICE (device));
 
1280
 
 
1281
        /* Don't change anything if the stylus is already set */
 
1282
        if (device->priv->last_stylus != NULL) {
 
1283
                GsdWacomStylus *stylus = device->priv->last_stylus;
 
1284
                if (stylus->priv->id == stylus_id)
 
1285
                        return;
 
1286
        }
 
1287
 
 
1288
        for (l = device->priv->styli; l; l = l->next) {
 
1289
                stylus = l->data;
 
1290
 
 
1291
                /* Set a nice default if 0x0 */
 
1292
                if (stylus_id == 0x0 &&
 
1293
                    stylus->priv->type == WSTYLUS_GENERAL) {
 
1294
                        g_object_set (device, "last-stylus", stylus, NULL);
 
1295
                        return;
 
1296
                }
 
1297
 
 
1298
                if (stylus->priv->id == stylus_id) {
 
1299
                        g_object_set (device, "last-stylus", stylus, NULL);
 
1300
                        return;
 
1301
                }
 
1302
        }
 
1303
 
 
1304
        /* Setting the default stylus to be the generic one */
 
1305
        for (l = device->priv->styli; l; l = l->next) {
 
1306
                stylus = l->data;
 
1307
 
 
1308
                /* Set a nice default if 0x0 */
 
1309
                if (stylus->priv->type == WSTYLUS_GENERAL) {
 
1310
                        g_debug ("Could not find stylus ID 0x%x for tablet '%s', setting general pen ID 0x%x instead",
 
1311
                                 stylus_id, device->priv->name, stylus->priv->id);
 
1312
                        g_object_set (device, "last-stylus", stylus, NULL);
 
1313
                        return;
 
1314
                }
 
1315
        }
 
1316
 
 
1317
        g_warning ("Could not set the current stylus ID 0x%x for tablet '%s', no general pen found",
 
1318
                   stylus_id, device->priv->name);
 
1319
 
 
1320
        /* Setting the default stylus to be the first one */
 
1321
        g_assert (device->priv->styli);
 
1322
 
 
1323
        stylus = device->priv->styli->data;
 
1324
        g_object_set (device, "last-stylus", stylus, NULL);
 
1325
}
 
1326
 
 
1327
GsdWacomDeviceType
 
1328
gsd_wacom_device_get_device_type (GsdWacomDevice *device)
 
1329
{
 
1330
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), WACOM_TYPE_INVALID);
 
1331
 
 
1332
        return device->priv->type;
 
1333
}
 
1334
 
 
1335
gint *
 
1336
gsd_wacom_device_get_area (GsdWacomDevice *device)
 
1337
{
 
1338
        int i, id;
 
1339
        XDevice *xdevice;
 
1340
        Atom area, realtype;
 
1341
        int rc, realformat;
 
1342
        unsigned long nitems, bytes_after;
 
1343
        unsigned char *data = NULL;
 
1344
        gint *device_area;
 
1345
 
 
1346
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1347
 
 
1348
        g_object_get (device->priv->gdk_device, "device-id", &id, NULL);
 
1349
 
 
1350
        area = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Wacom Tablet Area", False);
 
1351
 
 
1352
        gdk_error_trap_push ();
 
1353
        xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id);
 
1354
        if (gdk_error_trap_pop () || (device == NULL))
 
1355
                return NULL;
 
1356
 
 
1357
        gdk_error_trap_push ();
 
1358
        rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
 
1359
                                 xdevice, area, 0, 4, False,
 
1360
                                 XA_INTEGER, &realtype, &realformat, &nitems,
 
1361
                                 &bytes_after, &data);
 
1362
        if (gdk_error_trap_pop () || rc != Success || realtype == None || bytes_after != 0 || nitems != 4) {
 
1363
                XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
 
1364
                return NULL;
 
1365
        }
 
1366
 
 
1367
        device_area = g_new0 (int, nitems);
 
1368
        for (i = 0; i < nitems; i++)
 
1369
                device_area[i] = ((long*)data)[i];
 
1370
 
 
1371
        XFree (data);
 
1372
        XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice);
 
1373
 
 
1374
        return device_area;
 
1375
}
 
1376
 
 
1377
const char *
 
1378
gsd_wacom_device_type_to_string (GsdWacomDeviceType type)
 
1379
{
 
1380
        switch (type) {
 
1381
        case WACOM_TYPE_INVALID:
 
1382
                return "Invalid";
 
1383
        case WACOM_TYPE_STYLUS:
 
1384
                return "Stylus";
 
1385
        case WACOM_TYPE_ERASER:
 
1386
                return "Eraser";
 
1387
        case WACOM_TYPE_CURSOR:
 
1388
                return "Cursor";
 
1389
        case WACOM_TYPE_PAD:
 
1390
                return "Pad";
 
1391
        case WACOM_TYPE_TOUCH:
 
1392
                return "Touch";
 
1393
        default:
 
1394
                return "Unknown type";
 
1395
        }
 
1396
}
 
1397
 
 
1398
GList *
 
1399
gsd_wacom_device_get_buttons (GsdWacomDevice *device)
 
1400
{
 
1401
        g_return_val_if_fail (GSD_IS_WACOM_DEVICE (device), NULL);
 
1402
 
 
1403
        return g_list_copy (device->priv->buttons);
 
1404
}
 
1405
 
 
1406
GsdWacomDevice *
 
1407
gsd_wacom_device_create_fake (GsdWacomDeviceType  type,
 
1408
                              const char         *name,
 
1409
                              const char         *tool_name)
 
1410
{
 
1411
        GsdWacomDevice *device;
 
1412
        GsdWacomDevicePrivate *priv;
 
1413
        WacomDevice *wacom_device;
 
1414
 
 
1415
        device = GSD_WACOM_DEVICE (g_object_new (GSD_TYPE_WACOM_DEVICE, NULL));
 
1416
 
 
1417
        if (db == NULL)
 
1418
                db = libwacom_database_new ();
 
1419
 
 
1420
        wacom_device = libwacom_new_from_name (db, name, NULL);
 
1421
        if (wacom_device == NULL)
 
1422
                return NULL;
 
1423
 
 
1424
        priv = device->priv;
 
1425
        priv->type = type;
 
1426
        priv->tool_name = g_strdup (tool_name);
 
1427
        gsd_wacom_device_update_from_db (device, wacom_device, name);
 
1428
        libwacom_destroy (wacom_device);
 
1429
 
 
1430
        return device;
 
1431
}
 
1432
 
 
1433
GList *
 
1434
gsd_wacom_device_create_fake_cintiq (void)
 
1435
{
 
1436
        GsdWacomDevice *device;
 
1437
        GList *devices;
 
1438
 
 
1439
        device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS,
 
1440
                                               "Wacom Cintiq 21UX2",
 
1441
                                               "Wacom Cintiq 21UX2 stylus");
 
1442
        devices = g_list_prepend (NULL, device);
 
1443
 
 
1444
        device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER,
 
1445
                                               "Wacom Cintiq 21UX2",
 
1446
                                               "Wacom Cintiq 21UX2 eraser");
 
1447
        devices = g_list_prepend (devices, device);
 
1448
 
 
1449
        device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD,
 
1450
                                               "Wacom Cintiq 21UX2",
 
1451
                                               "Wacom Cintiq 21UX2 pad");
 
1452
        devices = g_list_prepend (devices, device);
 
1453
 
 
1454
        return devices;
 
1455
}
 
1456
 
 
1457
GList *
 
1458
gsd_wacom_device_create_fake_bt (void)
 
1459
{
 
1460
        GsdWacomDevice *device;
 
1461
        GList *devices;
 
1462
 
 
1463
        device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS,
 
1464
                                               "Wacom Graphire Wireless",
 
1465
                                               "Graphire Wireless stylus");
 
1466
        devices = g_list_prepend (NULL, device);
 
1467
 
 
1468
        device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER,
 
1469
                                               "Wacom Graphire Wireless",
 
1470
                                               "Graphire Wireless eraser");
 
1471
        devices = g_list_prepend (devices, device);
 
1472
 
 
1473
        device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD,
 
1474
                                               "Wacom Graphire Wireless",
 
1475
                                               "Graphire Wireless pad");
 
1476
        devices = g_list_prepend (devices, device);
 
1477
 
 
1478
        device = gsd_wacom_device_create_fake (WACOM_TYPE_CURSOR,
 
1479
                                               "Wacom Graphire Wireless",
 
1480
                                               "Graphire Wireless cursor");
 
1481
        devices = g_list_prepend (devices, device);
 
1482
 
 
1483
        return devices;
 
1484
}
 
1485
 
 
1486
GList *
 
1487
gsd_wacom_device_create_fake_x201 (void)
 
1488
{
 
1489
        GsdWacomDevice *device;
 
1490
        GList *devices;
 
1491
 
 
1492
        device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS,
 
1493
                                               "Wacom Serial Tablet WACf004",
 
1494
                                               "Wacom Serial Tablet WACf004 stylus");
 
1495
        devices = g_list_prepend (NULL, device);
 
1496
 
 
1497
        device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER,
 
1498
                                               "Wacom Serial Tablet WACf004",
 
1499
                                               "Wacom Serial Tablet WACf004 eraser");
 
1500
        devices = g_list_prepend (devices, device);
 
1501
 
 
1502
        return devices;
 
1503
}
 
1504
 
 
1505
GList *
 
1506
gsd_wacom_device_create_fake_intuos4 (void)
 
1507
{
 
1508
        GsdWacomDevice *device;
 
1509
        GList *devices;
 
1510
 
 
1511
        device = gsd_wacom_device_create_fake (WACOM_TYPE_STYLUS,
 
1512
                                               "Wacom Intuos4 6x9",
 
1513
                                               "Wacom Intuos4 6x9 stylus");
 
1514
        devices = g_list_prepend (NULL, device);
 
1515
 
 
1516
        device = gsd_wacom_device_create_fake (WACOM_TYPE_ERASER,
 
1517
                                               "Wacom Intuos4 6x9",
 
1518
                                               "Wacom Intuos4 6x9 eraser");
 
1519
        devices = g_list_prepend (devices, device);
 
1520
 
 
1521
        device = gsd_wacom_device_create_fake (WACOM_TYPE_PAD,
 
1522
                                               "Wacom Intuos4 6x9",
 
1523
                                               "Wacom Intuos4 6x9 pad");
 
1524
        devices = g_list_prepend (devices, device);
 
1525
 
 
1526
        device = gsd_wacom_device_create_fake (WACOM_TYPE_CURSOR,
 
1527
                                               "Wacom Intuos4 6x9",
 
1528
                                               "Wacom Intuos4 6x9 cursor");
 
1529
        devices = g_list_prepend (devices, device);
 
1530
 
 
1531
        return devices;
 
1532
}