~jzheng/unity-settings-daemon/unity-settings-daemon-master-touchscreen-fix

« back to all changes in this revision

Viewing changes to plugins/common/gsd-device-mapper.c

  • Committer: Joey Zheng
  • Date: 2016-05-16 04:20:07 UTC
  • Revision ID: joey.zheng@caonical.com-20160516042007-vabp76g6pddfrcb8
patch from:
https://git.gnome.org/browse/gnome-settings-daemon/commit/plugins/common/gsd-device-mapper.c?id=bf2f0d5d955f9fe5ca9f880e9f52246016e60e79
https://git.gnome.org/browse/gnome-settings-daemon/commit/?id=ab2b808
https://git.gnome.org/browse/gnome-settings-daemon/commit/?id=311849ex

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
 
 
22
#include <string.h>
 
23
#include <gtk/gtkx.h>
 
24
#include <X11/Xatom.h>
 
25
 
 
26
#if HAVE_WACOM
 
27
#include <libwacom/libwacom.h>
 
28
#endif
 
29
 
 
30
#include "gsd-device-mapper.h"
 
31
#include "gsd-input-helper.h"
 
32
#include "gsd-enums.h"
 
33
 
 
34
typedef struct _GsdInputInfo GsdInputInfo;
 
35
typedef struct _GsdOutputInfo GsdOutputInfo;
 
36
typedef struct _MappingHelper MappingHelper;
 
37
typedef struct _DeviceMapHelper DeviceMapHelper;
 
38
 
 
39
#define NUM_ELEMS_MATRIX 9
 
40
#define KEY_DISPLAY  "display"
 
41
#define KEY_ROTATION "rotation"
 
42
 
 
43
typedef enum {
 
44
        GSD_INPUT_IS_SYSTEM_INTEGRATED = 1 << 0, /* eg. laptop tablets/touchscreens */
 
45
        GSD_INPUT_IS_SCREEN_INTEGRATED = 1 << 1, /* eg. Wacom Cintiq devices */
 
46
        GSD_INPUT_IS_TOUCH             = 1 << 2, /* touch device, either touchscreen or tablet */
 
47
        GSD_INPUT_IS_PEN               = 1 << 3, /* pen device, either touchscreen or tablet */
 
48
        GSD_INPUT_IS_ERASER            = 1 << 4, /* eraser device, either touchscreen or tablet */
 
49
        GSD_INPUT_IS_PAD               = 1 << 5  /* pad device, most usually in tablets */
 
50
} GsdInputCapabilityFlags;
 
51
 
 
52
typedef enum {
 
53
        GSD_PRIO_BUILTIN,            /* Output is builtin, applies mainly to system-integrated devices */
 
54
        GSD_PRIO_EDID_MATCH_FULL,    /* Full EDID model match, eg. "Cintiq 12WX" */
 
55
        GSD_PRIO_EDID_MATCH_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
 
56
        GSD_PRIO_EDID_MATCH_VENDOR,  /* EDID vendor match, eg. "WAC" for Wacom */
 
57
        N_OUTPUT_PRIORITIES
 
58
} GsdOutputPriority;
 
59
 
 
60
struct _GsdInputInfo {
 
61
        GdkDevice *device;
 
62
        GSettings *settings;
 
63
        GsdDeviceMapper *mapper;
 
64
        GsdOutputInfo *output;
 
65
        GsdOutputInfo *guessed_output;
 
66
        guint changed_id;
 
67
        GsdInputCapabilityFlags capabilities;
 
68
};
 
69
 
 
70
struct _GsdOutputInfo {
 
71
        GnomeRROutput *output;
 
72
        GList *input_devices;
 
73
};
 
74
 
 
75
struct _DeviceMapHelper {
 
76
        GsdInputInfo *input;
 
77
        GnomeRROutput *candidates[N_OUTPUT_PRIORITIES];
 
78
        GsdOutputPriority highest_prio;
 
79
        guint n_candidates;
 
80
};
 
81
 
 
82
struct _MappingHelper {
 
83
        GArray *device_maps;
 
84
};
 
85
 
 
86
struct _GsdDeviceMapper {
 
87
        GObject parent_instance;
 
88
        GdkScreen *screen;
 
89
        GnomeRRScreen *rr_screen;
 
90
        GHashTable *input_devices; /* GdkDevice -> GsdInputInfo */
 
91
        GHashTable *output_devices; /* GnomeRROutput -> GsdOutputInfo */
 
92
#if HAVE_WACOM
 
93
        WacomDeviceDatabase *wacom_db;
 
94
#endif
 
95
};
 
96
 
 
97
struct _GsdDeviceMapperClass {
 
98
        GObjectClass parent_class;
 
99
};
 
100
 
 
101
/* Array order matches GsdWacomRotation */
 
102
struct {
 
103
        GnomeRRRotation rotation;
 
104
        /* Coordinate Transformation Matrix */
 
105
        gfloat matrix[NUM_ELEMS_MATRIX];
 
106
} rotation_matrices[] = {
 
107
        { GNOME_RR_ROTATION_0, { 1, 0, 0, 0, 1, 0, 0, 0, 1 } },
 
108
        { GNOME_RR_ROTATION_90, { 0, -1, 1, 1, 0, 0, 0, 0, 1 } },
 
109
        { GNOME_RR_ROTATION_270, { 0, 1, 0, -1, 0, 1, 0,  0, 1 } },
 
110
        { GNOME_RR_ROTATION_180, { -1, 0, 1, 0, -1, 1, 0, 0, 1 } }
 
111
};
 
112
 
 
113
enum {
 
114
        PROP_0,
 
115
        PROP_SCREEN
 
116
};
 
117
 
 
118
enum {
 
119
        DEVICE_CHANGED,
 
120
        N_SIGNALS
 
121
};
 
122
 
 
123
static guint signals[N_SIGNALS] = { 0 };
 
124
 
 
125
static void gsd_device_mapper_initable_iface_init (GInitableIface *iface);
 
126
 
 
127
G_DEFINE_TYPE_WITH_CODE (GsdDeviceMapper, gsd_device_mapper, G_TYPE_OBJECT,
 
128
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 
129
                                                gsd_device_mapper_initable_iface_init))
 
130
 
 
131
static XDevice *
 
132
open_device (GdkDevice *device)
 
133
{
 
134
        XDevice *xdev;
 
135
        int id;
 
136
 
 
137
        id = gdk_x11_device_get_id (device);
 
138
 
 
139
        gdk_error_trap_push ();
 
140
        xdev = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id);
 
141
        if (gdk_error_trap_pop () || (xdev == NULL))
 
142
                return NULL;
 
143
 
 
144
        return xdev;
 
145
}
 
146
 
 
147
static gboolean
 
148
device_apply_property (GdkDevice      *device,
 
149
                       PropertyHelper *property)
 
150
{
 
151
        gboolean retval;
 
152
        XDevice *xdev;
 
153
 
 
154
        xdev = open_device (device);
 
155
 
 
156
        if (!xdev)
 
157
                return FALSE;
 
158
 
 
159
        retval = device_set_property (xdev, gdk_device_get_name (device), property);
 
160
        XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdev);
 
161
        return retval;
 
162
}
 
163
 
 
164
static gboolean
 
165
device_set_matrix (GdkDevice *device,
 
166
                   gfloat     matrix[NUM_ELEMS_MATRIX])
 
167
{
 
168
        PropertyHelper property = {
 
169
                .name = "Coordinate Transformation Matrix",
 
170
                .nitems = 9,
 
171
                .format = 32,
 
172
                .type = gdk_x11_get_xatom_by_name ("FLOAT"),
 
173
                .data.i = (int *) matrix,
 
174
        };
 
175
 
 
176
        g_debug ("Setting '%s' matrix to:\n %f,%f,%f,\n %f,%f,%f,\n %f,%f,%f",
 
177
                 gdk_device_get_name (device),
 
178
                 matrix[0], matrix[1], matrix[2],
 
179
                 matrix[3], matrix[4], matrix[5],
 
180
                 matrix[6], matrix[7], matrix[8]);
 
181
 
 
182
        return device_apply_property (device, &property);
 
183
}
 
184
 
 
185
/* Finds an output which matches the given EDID information. Any NULL
 
186
 * parameter will be interpreted to match any value. */
 
187
static GnomeRROutput *
 
188
find_output_by_edid (GnomeRRScreen *rr_screen,
 
189
                     const gchar   *edid[3])
 
190
{
 
191
        GnomeRROutput **outputs;
 
192
        GnomeRROutput *retval = NULL;
 
193
        guint i;
 
194
 
 
195
        outputs = gnome_rr_screen_list_outputs (rr_screen);
 
196
 
 
197
        for (i = 0; outputs[i] != NULL; i++) {
 
198
                gchar *vendor, *product, *serial;
 
199
                gboolean match;
 
200
 
 
201
                gnome_rr_output_get_ids_from_edid (outputs[i], &vendor,
 
202
                                                   &product, &serial);
 
203
 
 
204
                g_debug ("Checking for match between ['%s','%s','%s'] and ['%s','%s','%s']", \
 
205
                         edid[0], edid[1], edid[2], vendor, product, serial);
 
206
 
 
207
                match = (edid[0] == NULL || g_strcmp0 (edid[0], vendor)  == 0) && \
 
208
                        (edid[1] == NULL || g_strcmp0 (edid[1], product) == 0) && \
 
209
                        (edid[2] == NULL || g_strcmp0 (edid[2], serial)  == 0);
 
210
 
 
211
                g_free (vendor);
 
212
                g_free (product);
 
213
                g_free (serial);
 
214
 
 
215
                if (match) {
 
216
                        retval = outputs[i];
 
217
                        break;
 
218
                }
 
219
        }
 
220
 
 
221
        if (retval == NULL)
 
222
                g_debug ("Did not find a matching output for EDID '%s,%s,%s'",
 
223
                         edid[0], edid[1], edid[2]);
 
224
        return retval;
 
225
}
 
226
 
 
227
static GnomeRROutput *
 
228
find_builtin_output (GnomeRRScreen *rr_screen)
 
229
{
 
230
        GnomeRROutput **outputs;
 
231
        guint i;
 
232
 
 
233
        outputs = gnome_rr_screen_list_outputs (rr_screen);
 
234
 
 
235
        for (i = 0; outputs[i] != NULL; i++) {
 
236
                if (!gnome_rr_output_is_builtin_display (outputs[i]))
 
237
                        continue;
 
238
 
 
239
                return outputs[i];
 
240
        }
 
241
 
 
242
        g_debug ("Did not find a built-in monitor");
 
243
        return NULL;
 
244
}
 
245
 
 
246
static GnomeRROutput *
 
247
monitor_to_output (GsdDeviceMapper *mapper,
 
248
                   gint             monitor_num)
 
249
{
 
250
        GnomeRROutput **outputs;
 
251
        guint i;
 
252
 
 
253
        outputs = gnome_rr_screen_list_outputs (mapper->rr_screen);
 
254
 
 
255
        for (i = 0; outputs[i] != NULL; i++) {
 
256
                GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (outputs[i]);
 
257
                gint x, y;
 
258
 
 
259
                if (!crtc)
 
260
                        continue;
 
261
 
 
262
                gnome_rr_crtc_get_position (crtc, &x, &y);
 
263
 
 
264
                if (monitor_num == gdk_screen_get_monitor_at_point (mapper->screen, x, y))
 
265
                        return outputs[i];
 
266
        }
 
267
 
 
268
        return NULL;
 
269
}
 
270
 
 
271
static MappingHelper *
 
272
mapping_helper_new (void)
 
273
{
 
274
        MappingHelper *helper;
 
275
 
 
276
        helper = g_new0 (MappingHelper, 1);
 
277
        helper->device_maps = g_array_new (FALSE, FALSE, sizeof (DeviceMapHelper));
 
278
 
 
279
        return helper;
 
280
}
 
281
 
 
282
static void
 
283
mapping_helper_free (MappingHelper *helper)
 
284
{
 
285
        g_array_unref (helper->device_maps);
 
286
        g_free (helper);
 
287
}
 
288
 
 
289
static void
 
290
mapping_helper_add (MappingHelper *helper,
 
291
                    GsdInputInfo  *input,
 
292
                    GnomeRROutput *outputs[N_OUTPUT_PRIORITIES])
 
293
{
 
294
        guint i, pos, highest = N_OUTPUT_PRIORITIES;
 
295
        DeviceMapHelper info = { 0 }, *prev;
 
296
 
 
297
        info.input = input;
 
298
 
 
299
        for (i = 0; i < N_OUTPUT_PRIORITIES; i++) {
 
300
                if (outputs[i] == NULL)
 
301
                        continue;
 
302
 
 
303
                if (highest > i)
 
304
                        highest = i;
 
305
 
 
306
                info.candidates[i] = outputs[i];
 
307
                info.n_candidates++;
 
308
        }
 
309
 
 
310
        info.highest_prio = highest;
 
311
        pos = helper->device_maps->len;
 
312
 
 
313
        for (i = 0; i < helper->device_maps->len; i++) {
 
314
                prev = &g_array_index (helper->device_maps, DeviceMapHelper, i);
 
315
 
 
316
                if (prev->highest_prio < info.highest_prio)
 
317
                        pos = i;
 
318
        }
 
319
 
 
320
        if (pos >= helper->device_maps->len)
 
321
                g_array_append_val (helper->device_maps, info);
 
322
        else
 
323
                g_array_insert_val (helper->device_maps, pos, info);
 
324
}
 
325
 
 
326
/* This function gets a map of outputs, sorted by confidence, for a given device,
 
327
 * the array can actually contain NULLs if no output matched a priority. */
 
328
static void
 
329
input_info_guess_candidates (GsdInputInfo  *input,
 
330
                             GnomeRROutput *outputs[N_OUTPUT_PRIORITIES])
 
331
{
 
332
        gboolean found = FALSE;
 
333
        const gchar *name;
 
334
        gchar **split;
 
335
 
 
336
        name = gdk_device_get_name (input->device);
 
337
        split = g_strsplit (name, " ", -1);
 
338
 
 
339
        /* On Wacom devices that are integrated on a not-in-system screen (eg. Cintiqs),
 
340
         * there is usually a minimal relation between the input device name and the EDID
 
341
         * vendor/model fields. Attempt to find matching outputs and fill in the map
 
342
         * from GSD_PRIO_EDID_MATCH_FULL to GSD_PRIO_EDID_MATCH_VENDOR.
 
343
         */
 
344
        if (input->capabilities & GSD_INPUT_IS_SCREEN_INTEGRATED &&
 
345
            g_str_has_prefix (name, "Wacom ")) {
 
346
                gchar *product = g_strdup_printf ("%s %s", split[1], split[2]);
 
347
                const gchar *edids[][3] = {
 
348
                        { "WAC", product, NULL },
 
349
                        { "WAC", split[1], NULL },
 
350
                        { "WAC", NULL, NULL }
 
351
                };
 
352
                gint i;
 
353
 
 
354
                for (i = 0; i < G_N_ELEMENTS (edids); i++) {
 
355
                        /* i + 1 matches the desired priority, we skip GSD_PRIO_BUILTIN here */
 
356
                        outputs[i + 1] =
 
357
                                find_output_by_edid (input->mapper->rr_screen,
 
358
                                                     edids[i]);
 
359
                        found |= outputs[i + 1] != NULL;
 
360
                }
 
361
 
 
362
                g_free (product);
 
363
        }
 
364
 
 
365
        /* For input devices that we certainly know that are system-integrated, or
 
366
         * for screen-integrated devices we weren't able to find an output for,
 
367
         * find the builtin screen.
 
368
         */
 
369
        if ((input->capabilities & GSD_INPUT_IS_SYSTEM_INTEGRATED) ||
 
370
            (!found && input->capabilities & GSD_INPUT_IS_SCREEN_INTEGRATED)) {
 
371
                outputs[GSD_PRIO_BUILTIN] =
 
372
                        find_builtin_output (input->mapper->rr_screen);
 
373
        }
 
374
 
 
375
        g_strfreev (split);
 
376
}
 
377
 
 
378
static gboolean
 
379
output_has_input_type (GsdOutputInfo *info,
 
380
                       guint          capabilities)
 
381
{
 
382
        GList *devices;
 
383
 
 
384
        for (devices = info->input_devices; devices; devices = devices->next) {
 
385
                GsdInputInfo *input = devices->data;
 
386
 
 
387
                if (input->capabilities == capabilities)
 
388
                        return TRUE;
 
389
        }
 
390
 
 
391
        return FALSE;
 
392
}
 
393
 
 
394
static GnomeRROutput *
 
395
settings_get_display (GSettings       *settings,
 
396
                      GsdDeviceMapper *mapper)
 
397
{
 
398
        GnomeRROutput *output = NULL;
 
399
        gchar **edid;
 
400
        guint nvalues;
 
401
 
 
402
        edid = g_settings_get_strv (settings, KEY_DISPLAY);
 
403
        nvalues = g_strv_length (edid);
 
404
 
 
405
        if (nvalues == 3) {
 
406
                output = find_output_by_edid (mapper->rr_screen, (const gchar **) edid);
 
407
        } else {
 
408
                g_warning ("Unable to get display property. Got %d items, "
 
409
                           "expected %d items.\n", nvalues, 3);
 
410
        }
 
411
 
 
412
        g_strfreev (edid);
 
413
 
 
414
        return output;
 
415
}
 
416
 
 
417
static void
 
418
settings_set_display (GSettings     *settings,
 
419
                      GnomeRROutput *output)
 
420
{
 
421
        gchar **prev, *edid[4] = { NULL, NULL, NULL, NULL };
 
422
        GVariant *value;
 
423
        gsize nvalues;
 
424
 
 
425
        prev = g_settings_get_strv (settings, KEY_DISPLAY);
 
426
        nvalues = g_strv_length (prev);
 
427
 
 
428
        if (output)
 
429
                gnome_rr_output_get_ids_from_edid (output, &edid[0],
 
430
                                                   &edid[1], &edid[2]);
 
431
 
 
432
        if (nvalues != 3 ||
 
433
            g_strcmp0 (prev[0], edid[0]) != 0 ||
 
434
            g_strcmp0 (prev[1], edid[1]) != 0 ||
 
435
            g_strcmp0 (prev[2], edid[2]) != 0) {
 
436
                value = g_variant_new_strv ((const gchar * const *) &edid, 3);
 
437
                g_settings_set_value (settings, KEY_DISPLAY, value);
 
438
        }
 
439
 
 
440
        g_free (edid[0]);
 
441
        g_free (edid[1]);
 
442
        g_free (edid[2]);
 
443
        g_strfreev (prev);
 
444
}
 
445
 
 
446
static void
 
447
input_info_set_output (GsdInputInfo  *input,
 
448
                       GsdOutputInfo *output,
 
449
                       gboolean       guessed,
 
450
                       gboolean       save)
 
451
{
 
452
        GnomeRROutput *rr_output = NULL;
 
453
        GsdOutputInfo **ptr;
 
454
 
 
455
        if (guessed) {
 
456
                /* If there is already a non-guessed input, go for it */
 
457
                if (input->output)
 
458
                        return;
 
459
 
 
460
                ptr = &input->guessed_output;
 
461
        } else {
 
462
                /* Unset guessed output */
 
463
                if (input->guessed_output)
 
464
                        input_info_set_output (input, NULL, TRUE, FALSE);
 
465
                ptr = &input->output;
 
466
        }
 
467
 
 
468
        if (*ptr == output)
 
469
                return;
 
470
 
 
471
        if (*ptr) {
 
472
                (*ptr)->input_devices = g_list_remove ((*ptr)->input_devices,
 
473
                                                       input);
 
474
        }
 
475
 
 
476
        if (output) {
 
477
                output->input_devices = g_list_prepend (output->input_devices,
 
478
                                                        input);
 
479
                rr_output = output->output;
 
480
        }
 
481
 
 
482
        if (input->settings && !guessed && save)
 
483
                settings_set_display (input->settings, rr_output);
 
484
 
 
485
        *ptr = output;
 
486
}
 
487
 
 
488
static GsdOutputInfo *
 
489
input_info_get_output (GsdInputInfo *input)
 
490
{
 
491
        if (!input)
 
492
                return NULL;
 
493
 
 
494
        if (input->output)
 
495
                return input->output;
 
496
 
 
497
        if (input->guessed_output)
 
498
                return input->guessed_output;
 
499
 
 
500
        if (g_hash_table_size (input->mapper->output_devices) == 1) {
 
501
                GsdOutputInfo *output;
 
502
                GHashTableIter iter;
 
503
 
 
504
                g_hash_table_iter_init (&iter, input->mapper->output_devices);
 
505
                g_hash_table_iter_next (&iter, NULL, (gpointer *) &output);
 
506
 
 
507
                return output;
 
508
        }
 
509
 
 
510
        return NULL;
 
511
}
 
512
 
 
513
static void
 
514
init_device_rotation_matrix (GsdWacomRotation rotation,
 
515
                             float            matrix[NUM_ELEMS_MATRIX])
 
516
{
 
517
        memcpy (matrix, rotation_matrices[rotation].matrix,
 
518
                sizeof (rotation_matrices[rotation].matrix));
 
519
}
 
520
 
 
521
static void
 
522
init_output_rotation_matrix (GnomeRRRotation rotation,
 
523
                             float           matrix[NUM_ELEMS_MATRIX])
 
524
{
 
525
        guint i;
 
526
 
 
527
        for (i = 0; i < G_N_ELEMENTS (rotation_matrices); i++) {
 
528
                if (rotation_matrices[i].rotation != rotation)
 
529
                        continue;
 
530
 
 
531
                memcpy (matrix, rotation_matrices[i].matrix, sizeof (rotation_matrices[i].matrix));
 
532
                return;
 
533
        }
 
534
 
 
535
        /* We know nothing about this rotation */
 
536
        init_device_rotation_matrix (GSD_WACOM_ROTATION_NONE, matrix);
 
537
}
 
538
 
 
539
static void
 
540
multiply_matrix (float a[NUM_ELEMS_MATRIX],
 
541
                 float b[NUM_ELEMS_MATRIX],
 
542
                 float res[NUM_ELEMS_MATRIX])
 
543
{
 
544
        float result[NUM_ELEMS_MATRIX];
 
545
 
 
546
        result[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
 
547
        result[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
 
548
        result[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
 
549
        result[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6];
 
550
        result[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7];
 
551
        result[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8];
 
552
        result[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6];
 
553
        result[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7];
 
554
        result[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
 
555
 
 
556
        memcpy (res, result, sizeof (result));
 
557
}
 
558
 
 
559
static void
 
560
calculate_viewport_matrix (const GdkRectangle mapped,
 
561
                           const GdkRectangle desktop,
 
562
                           float              viewport[NUM_ELEMS_MATRIX])
 
563
{
 
564
        float x_scale = (float) mapped.x / desktop.width;
 
565
        float y_scale = (float) mapped.y / desktop.height;
 
566
        float width_scale  = (float) mapped.width / desktop.width;
 
567
        float height_scale = (float) mapped.height / desktop.height;
 
568
 
 
569
        viewport[0] = width_scale;
 
570
        viewport[1] = 0.0f;
 
571
        viewport[2] = x_scale;
 
572
 
 
573
        viewport[3] = 0.0f;
 
574
        viewport[4] = height_scale;
 
575
        viewport[5] = y_scale;
 
576
 
 
577
        viewport[6] = 0.0f;
 
578
        viewport[7] = 0.0f;
 
579
        viewport[8] = 1.0f;
 
580
}
 
581
 
 
582
static gint
 
583
monitor_for_output (GnomeRROutput *output)
 
584
{
 
585
        GdkScreen *screen = gdk_screen_get_default ();
 
586
        GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (output);
 
587
        gint x, y;
 
588
 
 
589
        if (!crtc)
 
590
                return -1;
 
591
 
 
592
        gnome_rr_crtc_get_position (crtc, &x, &y);
 
593
 
 
594
        return gdk_screen_get_monitor_at_point (screen, x, y);
 
595
}
 
596
 
 
597
static void
 
598
input_info_get_matrix (GsdInputInfo *input,
 
599
                       float         matrix[NUM_ELEMS_MATRIX])
 
600
{
 
601
        GsdOutputInfo *output;
 
602
 
 
603
        output = input_info_get_output (input);
 
604
 
 
605
        if (!output) {
 
606
                init_output_rotation_matrix (GNOME_RR_ROTATION_0, matrix);
 
607
        } else {
 
608
                GdkScreen *screen = gdk_screen_get_default ();
 
609
                float viewport[NUM_ELEMS_MATRIX];
 
610
                float output_rot[NUM_ELEMS_MATRIX];
 
611
                GdkRectangle display, desktop = { 0 };
 
612
                GnomeRRRotation rotation;
 
613
                GnomeRRCrtc *crtc;
 
614
                int monitor;
 
615
 
 
616
                g_debug ("Mapping '%s' to output '%s'",
 
617
                         gdk_device_get_name (input->device),
 
618
                         gnome_rr_output_get_name (output->output));
 
619
 
 
620
                crtc = gnome_rr_output_get_crtc (output->output);
 
621
                rotation = gnome_rr_crtc_get_current_rotation (crtc);
 
622
                init_output_rotation_matrix (rotation, output_rot);
 
623
 
 
624
                desktop.width = gdk_screen_get_width (screen);
 
625
                desktop.height = gdk_screen_get_height (screen);
 
626
 
 
627
                monitor = monitor_for_output (output->output);
 
628
                gdk_screen_get_monitor_geometry (screen, monitor, &display);
 
629
                calculate_viewport_matrix (display, desktop, viewport);
 
630
 
 
631
                multiply_matrix (viewport, output_rot, matrix);
 
632
        }
 
633
 
 
634
        /* Apply device rotation after output rotation */
 
635
        if (input->settings &&
 
636
            (input->capabilities &
 
637
             (GSD_INPUT_IS_SYSTEM_INTEGRATED | GSD_INPUT_IS_SCREEN_INTEGRATED)) == 0) {
 
638
                gint rotation;
 
639
 
 
640
                rotation = g_settings_get_enum (input->settings, KEY_ROTATION);
 
641
 
 
642
                if (rotation > 0) {
 
643
                        float device_rot[NUM_ELEMS_MATRIX];
 
644
 
 
645
                        g_debug ("Applying device rotation %d to '%s'",
 
646
                                 rotation, gdk_device_get_name (input->device));
 
647
 
 
648
                        init_device_rotation_matrix (rotation, device_rot);
 
649
                        multiply_matrix (matrix, device_rot, matrix);
 
650
                }
 
651
        }
 
652
}
 
653
 
 
654
static void
 
655
input_info_remap (GsdInputInfo *input)
 
656
{
 
657
        float matrix[NUM_ELEMS_MATRIX] = { 0 };
 
658
 
 
659
        if (input->capabilities & GSD_INPUT_IS_PAD)
 
660
                return;
 
661
 
 
662
        input_info_get_matrix (input, matrix);
 
663
 
 
664
        g_debug ("About to remap device '%s'",
 
665
                 gdk_device_get_name (input->device));
 
666
 
 
667
        if (!device_set_matrix (input->device, matrix)) {
 
668
                g_warning ("Failed to map device '%s'",
 
669
                           gdk_device_get_name (input->device));
 
670
        }
 
671
 
 
672
        g_signal_emit (input->mapper, signals[DEVICE_CHANGED], 0, input->device);
 
673
}
 
674
 
 
675
static void
 
676
mapper_apply_helper_info (GsdDeviceMapper *mapper,
 
677
                          MappingHelper   *helper)
 
678
{
 
679
        guint i, j;
 
680
 
 
681
        /* Now, decide which input claims which output */
 
682
        for (i = 0; i < helper->device_maps->len; i++) {
 
683
                GsdOutputInfo *last = NULL, *output = NULL;
 
684
                DeviceMapHelper *info;
 
685
 
 
686
                info = &g_array_index (helper->device_maps, DeviceMapHelper, i);
 
687
 
 
688
                for (j = 0; j < N_OUTPUT_PRIORITIES; j++) {
 
689
                        if (!info->candidates[j])
 
690
                                continue;
 
691
 
 
692
                        output = g_hash_table_lookup (mapper->output_devices,
 
693
                                                      info->candidates[j]);
 
694
 
 
695
                        if (!output)
 
696
                                continue;
 
697
 
 
698
                        last = output;
 
699
 
 
700
                        if ((info->input->capabilities &
 
701
                             (GSD_INPUT_IS_SYSTEM_INTEGRATED | GSD_INPUT_IS_SCREEN_INTEGRATED))) {
 
702
                                /* A single output is hardly going to have multiple integrated input
 
703
                                 * devices with the same capabilities, so punt to any next output.
 
704
                                 */
 
705
                                if (output_has_input_type (output, info->input->capabilities))
 
706
                                        continue;
 
707
                        }
 
708
 
 
709
                        input_info_set_output (info->input, output, TRUE, FALSE);
 
710
                        break;
 
711
                }
 
712
 
 
713
                /* Assign the last candidate if we came up empty */
 
714
                if (!info->input->guessed_output && last)
 
715
                        input_info_set_output (info->input, last, TRUE, FALSE);
 
716
 
 
717
                input_info_remap (info->input);
 
718
        }
 
719
}
 
720
 
 
721
static void
 
722
mapper_recalculate_candidates (GsdDeviceMapper *mapper)
 
723
{
 
724
        MappingHelper *helper;
 
725
        GHashTableIter iter;
 
726
        GsdInputInfo *input;
 
727
 
 
728
        helper = mapping_helper_new ();
 
729
        g_hash_table_iter_init (&iter, mapper->input_devices);
 
730
 
 
731
        while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &input)) {
 
732
                GnomeRROutput *outputs[N_OUTPUT_PRIORITIES] = { 0 };
 
733
 
 
734
                /* Device has an output from settings */
 
735
                if (input->output)
 
736
                        continue;
 
737
 
 
738
                input_info_guess_candidates (input, outputs);
 
739
                mapping_helper_add (helper, input, outputs);
 
740
        }
 
741
 
 
742
        mapper_apply_helper_info (mapper, helper);
 
743
        mapping_helper_free (helper);
 
744
}
 
745
 
 
746
static void
 
747
mapper_recalculate_input (GsdDeviceMapper *mapper,
 
748
                          GsdInputInfo    *input)
 
749
{
 
750
        GnomeRROutput *outputs[N_OUTPUT_PRIORITIES] = { 0 };
 
751
        MappingHelper *helper;
 
752
 
 
753
        /* Device has an output from settings */
 
754
        if (input->output)
 
755
                return;
 
756
 
 
757
        helper = mapping_helper_new ();
 
758
        input_info_guess_candidates (input, outputs);
 
759
        mapping_helper_add (helper, input, outputs);
 
760
 
 
761
        mapper_apply_helper_info (mapper, helper);
 
762
        mapping_helper_free (helper);
 
763
}
 
764
 
 
765
static gboolean
 
766
input_info_update_capabilities_from_tool_type (GsdInputInfo *info)
 
767
{
 
768
        const char *tool_type;
 
769
        int deviceid;
 
770
 
 
771
        deviceid = gdk_x11_device_get_id (info->device);
 
772
        tool_type = xdevice_get_wacom_tool_type (deviceid);
 
773
 
 
774
        if (!tool_type)
 
775
                return FALSE;
 
776
 
 
777
        if (g_str_equal (tool_type, "STYLUS"))
 
778
                info->capabilities |= GSD_INPUT_IS_PEN;
 
779
        else if (g_str_equal (tool_type, "ERASER"))
 
780
                info->capabilities |= GSD_INPUT_IS_ERASER;
 
781
        else if (g_str_equal (tool_type, "PAD"))
 
782
                info->capabilities |= GSD_INPUT_IS_PAD;
 
783
 
 
784
        return TRUE;
 
785
}
 
786
 
 
787
static void
 
788
input_info_update_capabilities (GsdInputInfo *info)
 
789
{
 
790
#if HAVE_WACOM
 
791
        WacomDevice *wacom_device;
 
792
        gchar *devpath;
 
793
 
 
794
        info->capabilities = 0;
 
795
        devpath = xdevice_get_device_node (gdk_x11_device_get_id (info->device));
 
796
        wacom_device = libwacom_new_from_path (info->mapper->wacom_db, devpath,
 
797
                                               WFALLBACK_GENERIC, NULL);
 
798
 
 
799
        if (wacom_device) {
 
800
                WacomIntegrationFlags integration_flags;
 
801
 
 
802
                integration_flags = libwacom_get_integration_flags (wacom_device);
 
803
 
 
804
                if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY)
 
805
                        info->capabilities |= GSD_INPUT_IS_SCREEN_INTEGRATED;
 
806
 
 
807
                if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM)
 
808
                        info->capabilities |= GSD_INPUT_IS_SYSTEM_INTEGRATED;
 
809
 
 
810
                libwacom_destroy (wacom_device);
 
811
        }
 
812
 
 
813
        g_free (devpath);
 
814
#else
 
815
        info->capabilities = 0;
 
816
#endif /* HAVE_WACOM */
 
817
 
 
818
        if (!input_info_update_capabilities_from_tool_type (info)) {
 
819
                GdkInputSource source;
 
820
 
 
821
                /* Fallback to GdkInputSource */
 
822
                source = gdk_device_get_source (info->device);
 
823
 
 
824
                if (source == GDK_SOURCE_TOUCHSCREEN)
 
825
                        info->capabilities |= GSD_INPUT_IS_TOUCH | GSD_INPUT_IS_SCREEN_INTEGRATED;
 
826
                else if (source == GDK_SOURCE_PEN)
 
827
                        info->capabilities |= GSD_INPUT_IS_PEN;
 
828
                else if (source == GDK_SOURCE_ERASER)
 
829
                        info->capabilities |= GSD_INPUT_IS_ERASER;
 
830
        }
 
831
}
 
832
 
 
833
static void
 
834
device_settings_changed_cb (GSettings    *settings,
 
835
                            gchar        *key,
 
836
                            GsdInputInfo *input)
 
837
{
 
838
        if (g_str_equal (key, KEY_DISPLAY)) {
 
839
                GnomeRROutput *rr_output;
 
840
                GsdOutputInfo *output;
 
841
 
 
842
                rr_output = settings_get_display (settings, input->mapper);
 
843
 
 
844
                if (rr_output) {
 
845
                        output = g_hash_table_lookup (input->mapper->output_devices,
 
846
                                                      rr_output);
 
847
                        input_info_set_output (input, output, FALSE, FALSE);
 
848
                        input_info_remap (input);
 
849
                } else {
 
850
                        /* Guess an output for this device */
 
851
                        mapper_recalculate_input (input->mapper, input);
 
852
                }
 
853
        } else if (g_str_equal (key, KEY_ROTATION)) {
 
854
                /* Remap the device so the new rotation is applied */
 
855
                input_info_remap (input);
 
856
        }
 
857
}
 
858
 
 
859
static GsdInputInfo *
 
860
input_info_new (GdkDevice       *device,
 
861
                GSettings       *settings,
 
862
                GsdDeviceMapper *mapper)
 
863
{
 
864
        GnomeRROutput *rr_output = NULL;
 
865
        GsdOutputInfo *output = NULL;
 
866
        GsdInputInfo *info;
 
867
 
 
868
        info = g_new0 (GsdInputInfo, 1);
 
869
        info->device = device;
 
870
        info->settings = (settings) ? g_object_ref (settings) : NULL;
 
871
        info->mapper = mapper;
 
872
 
 
873
        if (info->settings) {
 
874
                info->changed_id = g_signal_connect (info->settings, "changed",
 
875
                                                     G_CALLBACK (device_settings_changed_cb),
 
876
                                                     info);
 
877
 
 
878
                /* Assign output from config */
 
879
                rr_output = settings_get_display (settings, mapper);
 
880
        }
 
881
 
 
882
        input_info_update_capabilities (info);
 
883
 
 
884
        if (rr_output) {
 
885
                output = g_hash_table_lookup (mapper->output_devices,
 
886
                                              rr_output);
 
887
                input_info_set_output (info, output, FALSE, FALSE);
 
888
                input_info_remap (info);
 
889
        } else {
 
890
                mapper_recalculate_input (mapper, info);
 
891
        }
 
892
 
 
893
        return info;
 
894
}
 
895
 
 
896
static void
 
897
input_info_free (GsdInputInfo *info)
 
898
{
 
899
        input_info_set_output (info, NULL, FALSE, FALSE);
 
900
        input_info_set_output (info, NULL, TRUE, FALSE);
 
901
 
 
902
        if (info->settings && info->changed_id)
 
903
                g_signal_handler_disconnect (info->settings, info->changed_id);
 
904
 
 
905
        if (info->settings)
 
906
                g_object_unref (info->settings);
 
907
 
 
908
        g_free (info);
 
909
}
 
910
 
 
911
static GsdOutputInfo *
 
912
output_info_new (GnomeRROutput *output)
 
913
{
 
914
        GsdOutputInfo *info;
 
915
 
 
916
        info = g_new0 (GsdOutputInfo, 1);
 
917
        info->output = output;
 
918
 
 
919
        return info;
 
920
}
 
921
 
 
922
static void
 
923
output_info_free (GsdOutputInfo *info)
 
924
{
 
925
        while (info->input_devices) {
 
926
                GsdInputInfo *input = info->input_devices->data;
 
927
 
 
928
                if (input->output == info)
 
929
                        input_info_set_output (input, NULL, FALSE, FALSE);
 
930
                if (input->guessed_output == info)
 
931
                        input_info_set_output (input, NULL, TRUE, FALSE);
 
932
        }
 
933
 
 
934
        g_free (info);
 
935
}
 
936
 
 
937
static void
 
938
gsd_device_mapper_finalize (GObject *object)
 
939
{
 
940
        GsdDeviceMapper *mapper = GSD_DEVICE_MAPPER (object);
 
941
 
 
942
        g_hash_table_unref (mapper->input_devices);
 
943
 
 
944
        if (mapper->output_devices)
 
945
                g_hash_table_unref (mapper->output_devices);
 
946
 
 
947
#if HAVE_WACOM
 
948
        libwacom_database_destroy (mapper->wacom_db);
 
949
#endif
 
950
 
 
951
        G_OBJECT_CLASS (gsd_device_mapper_parent_class)->finalize (object);
 
952
}
 
953
 
 
954
static void
 
955
_device_mapper_update_outputs (GsdDeviceMapper *mapper)
 
956
{
 
957
        GnomeRROutput **outputs;
 
958
        GHashTable *map;
 
959
        gint i = 0;
 
960
 
 
961
        map = g_hash_table_new_full (NULL, NULL, NULL,
 
962
                                     (GDestroyNotify) output_info_free);
 
963
        outputs = gnome_rr_screen_list_outputs (mapper->rr_screen);
 
964
 
 
965
        while (outputs[i]) {
 
966
                GsdOutputInfo *info = NULL;
 
967
 
 
968
                if (mapper->output_devices) {
 
969
                        info = g_hash_table_lookup (mapper->output_devices,
 
970
                                                    outputs[i]);
 
971
 
 
972
                        if (info)
 
973
                                g_hash_table_steal (mapper->output_devices,
 
974
                                                    outputs[i]);
 
975
                }
 
976
 
 
977
                if (!info)
 
978
                        info = output_info_new (outputs[i]);
 
979
 
 
980
                g_hash_table_insert (map, outputs[i], info);
 
981
                i++;
 
982
        }
 
983
 
 
984
        if (mapper->output_devices)
 
985
                g_hash_table_unref (mapper->output_devices);
 
986
 
 
987
        mapper->output_devices = map;
 
988
        mapper_recalculate_candidates (mapper);
 
989
}
 
990
 
 
991
static void
 
992
outputs_changed_cb (GnomeRRScreen   *rr_screen,
 
993
                    GnomeRROutput   *output,
 
994
                    GsdDeviceMapper *mapper)
 
995
{
 
996
        _device_mapper_update_outputs (mapper);
 
997
}
 
998
 
 
999
static void
 
1000
screen_changed_cb (GnomeRRScreen   *rr_screen,
 
1001
                   GsdDeviceMapper *mapper)
 
1002
{
 
1003
        _device_mapper_update_outputs (mapper);
 
1004
}
 
1005
 
 
1006
static gboolean
 
1007
gsd_device_mapper_initable_init (GInitable     *initable,
 
1008
                                 GCancellable  *cancellable,
 
1009
                                 GError       **error)
 
1010
{
 
1011
        GsdDeviceMapper *mapper;
 
1012
 
 
1013
        mapper = GSD_DEVICE_MAPPER (initable);
 
1014
        mapper->rr_screen = gnome_rr_screen_new (mapper->screen, error);
 
1015
 
 
1016
        if (!mapper->rr_screen)
 
1017
                return FALSE;
 
1018
 
 
1019
        g_signal_connect (mapper->rr_screen, "changed",
 
1020
                          G_CALLBACK (screen_changed_cb), initable);
 
1021
        g_signal_connect (mapper->rr_screen, "output-connected",
 
1022
                          G_CALLBACK (outputs_changed_cb), initable);
 
1023
        g_signal_connect (mapper->rr_screen, "output-disconnected",
 
1024
                          G_CALLBACK (outputs_changed_cb), initable);
 
1025
        _device_mapper_update_outputs (GSD_DEVICE_MAPPER (initable));
 
1026
        return TRUE;
 
1027
}
 
1028
 
 
1029
static void
 
1030
gsd_device_mapper_initable_iface_init (GInitableIface *iface)
 
1031
{
 
1032
        iface->init = gsd_device_mapper_initable_init;
 
1033
}
 
1034
 
 
1035
static void
 
1036
gsd_device_mapper_set_property (GObject      *object,
 
1037
                                guint         param_id,
 
1038
                                const GValue *value,
 
1039
                                GParamSpec   *pspec)
 
1040
{
 
1041
        GsdDeviceMapper *mapper = GSD_DEVICE_MAPPER (object);
 
1042
 
 
1043
        switch (param_id) {
 
1044
        case PROP_SCREEN:
 
1045
                mapper->screen = g_value_get_object (value);
 
1046
                break;
 
1047
        default:
 
1048
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 
1049
        }
 
1050
}
 
1051
 
 
1052
static void
 
1053
gsd_device_mapper_get_property (GObject    *object,
 
1054
                                guint       param_id,
 
1055
                                GValue     *value,
 
1056
                                GParamSpec *pspec)
 
1057
{
 
1058
        GsdDeviceMapper *mapper = GSD_DEVICE_MAPPER (object);
 
1059
 
 
1060
        switch (param_id) {
 
1061
        case PROP_SCREEN:
 
1062
                g_value_set_object (value, mapper->screen);
 
1063
                break;
 
1064
        default:
 
1065
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 
1066
        }
 
1067
}
 
1068
 
 
1069
static void
 
1070
gsd_device_mapper_class_init (GsdDeviceMapperClass *klass)
 
1071
{
 
1072
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
1073
 
 
1074
        object_class->set_property = gsd_device_mapper_set_property;
 
1075
        object_class->get_property = gsd_device_mapper_get_property;
 
1076
        object_class->finalize = gsd_device_mapper_finalize;
 
1077
 
 
1078
        g_object_class_install_property (object_class,
 
1079
                                         PROP_SCREEN,
 
1080
                                         g_param_spec_object ("screen",
 
1081
                                                              "Screen",
 
1082
                                                              "Screen",
 
1083
                                                              GDK_TYPE_SCREEN,
 
1084
                                                              G_PARAM_CONSTRUCT_ONLY |
 
1085
                                                              G_PARAM_READWRITE));
 
1086
        signals[DEVICE_CHANGED] =
 
1087
                g_signal_new ("device-changed",
 
1088
                              GSD_TYPE_DEVICE_MAPPER,
 
1089
                              G_SIGNAL_RUN_LAST, 0,
 
1090
                              NULL, NULL, NULL,
 
1091
                              G_TYPE_NONE, 1, GDK_TYPE_DEVICE);
 
1092
}
 
1093
 
 
1094
static void
 
1095
gsd_device_mapper_init (GsdDeviceMapper *mapper)
 
1096
{
 
1097
        mapper->input_devices = g_hash_table_new_full (NULL, NULL, NULL,
 
1098
                                                       (GDestroyNotify) input_info_free);
 
1099
#if HAVE_WACOM
 
1100
        mapper->wacom_db = libwacom_database_new ();
 
1101
#endif
 
1102
}
 
1103
 
 
1104
GsdDeviceMapper *
 
1105
gsd_device_mapper_get (void)
 
1106
{
 
1107
        GsdDeviceMapper *mapper;
 
1108
        GdkScreen *screen;
 
1109
 
 
1110
        screen = gdk_screen_get_default ();
 
1111
        g_return_val_if_fail (screen != NULL, NULL);
 
1112
 
 
1113
        mapper = g_object_get_data (G_OBJECT (screen), "gsd-device-mapper-data");
 
1114
 
 
1115
        if (!mapper) {
 
1116
                GError *error = NULL;
 
1117
 
 
1118
                mapper = g_initable_new (GSD_TYPE_DEVICE_MAPPER, NULL, &error,
 
1119
                                         "screen", screen, NULL);
 
1120
                if (error) {
 
1121
                        g_critical ("Could not create device mapper: %s", error->message);
 
1122
                        g_error_free (error);
 
1123
                } else {
 
1124
                        g_object_set_data_full (G_OBJECT (screen), "gsd-device-mapper-data",
 
1125
                                                mapper, (GDestroyNotify) g_object_unref);
 
1126
                }
 
1127
        }
 
1128
 
 
1129
        return mapper;
 
1130
}
 
1131
 
 
1132
void
 
1133
gsd_device_mapper_add_input (GsdDeviceMapper *mapper,
 
1134
                             GdkDevice       *device,
 
1135
                             GSettings       *settings)
 
1136
{
 
1137
        GsdInputInfo *info;
 
1138
 
 
1139
        g_return_if_fail (mapper != NULL);
 
1140
        g_return_if_fail (GDK_IS_DEVICE (device));
 
1141
        g_return_if_fail (!settings || G_IS_SETTINGS (settings));
 
1142
 
 
1143
        if (g_hash_table_contains (mapper->input_devices, device))
 
1144
                return;
 
1145
 
 
1146
        info = input_info_new (device, settings, mapper);
 
1147
        g_hash_table_insert (mapper->input_devices, device, info);
 
1148
}
 
1149
 
 
1150
void
 
1151
gsd_device_mapper_remove_input (GsdDeviceMapper *mapper,
 
1152
                                GdkDevice       *device)
 
1153
{
 
1154
        g_return_if_fail (mapper != NULL);
 
1155
        g_return_if_fail (GDK_IS_DEVICE (device));
 
1156
 
 
1157
        g_hash_table_remove (mapper->input_devices, device);
 
1158
}
 
1159
 
 
1160
GnomeRROutput *
 
1161
gsd_device_mapper_get_device_output (GsdDeviceMapper *mapper,
 
1162
                                     GdkDevice       *device)
 
1163
{
 
1164
        GsdOutputInfo *output;
 
1165
        GsdInputInfo *input;
 
1166
 
 
1167
        g_return_val_if_fail (mapper != NULL, NULL);
 
1168
        g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
 
1169
 
 
1170
        input = g_hash_table_lookup (mapper->input_devices, device);
 
1171
        output = input_info_get_output (input);
 
1172
 
 
1173
        if (!output)
 
1174
                return NULL;
 
1175
 
 
1176
        return output->output;
 
1177
}
 
1178
 
 
1179
gint
 
1180
gsd_device_mapper_get_device_monitor (GsdDeviceMapper *mapper,
 
1181
                                      GdkDevice       *device)
 
1182
{
 
1183
        GsdOutputInfo *output;
 
1184
        GsdInputInfo *input;
 
1185
 
 
1186
        g_return_val_if_fail (GSD_IS_DEVICE_MAPPER (mapper), -1);
 
1187
        g_return_val_if_fail (GDK_IS_DEVICE (device), -1);
 
1188
 
 
1189
        input = g_hash_table_lookup (mapper->input_devices, device);
 
1190
 
 
1191
        if (!input)
 
1192
                return -1;
 
1193
 
 
1194
        output = input_info_get_output (input);
 
1195
 
 
1196
        if (!output)
 
1197
                return -1;
 
1198
 
 
1199
        return monitor_for_output (output->output);
 
1200
}
 
1201
 
 
1202
void
 
1203
gsd_device_mapper_set_device_output (GsdDeviceMapper *mapper,
 
1204
                                     GdkDevice       *device,
 
1205
                                     GnomeRROutput   *output)
 
1206
{
 
1207
        GsdInputInfo *input_info;
 
1208
        GsdOutputInfo *output_info;
 
1209
 
 
1210
        g_return_if_fail (mapper != NULL);
 
1211
        g_return_if_fail (GDK_IS_DEVICE (device));
 
1212
 
 
1213
        input_info = g_hash_table_lookup (mapper->input_devices, device);
 
1214
        output_info = g_hash_table_lookup (mapper->output_devices, output);
 
1215
 
 
1216
        if (!input_info || !output_info)
 
1217
                return;
 
1218
 
 
1219
        input_info_set_output (input_info, output_info, FALSE, TRUE);
 
1220
        input_info_remap (input_info);
 
1221
}
 
1222
 
 
1223
void
 
1224
gsd_device_mapper_set_device_monitor (GsdDeviceMapper *mapper,
 
1225
                                      GdkDevice       *device,
 
1226
                                      gint             monitor_num)
 
1227
{
 
1228
        GnomeRROutput *output;
 
1229
 
 
1230
        g_return_if_fail (GSD_IS_DEVICE_MAPPER (mapper));
 
1231
        g_return_if_fail (GDK_IS_DEVICE (device));
 
1232
 
 
1233
        output = monitor_to_output (mapper, monitor_num);
 
1234
        gsd_device_mapper_set_device_output (mapper, device, output);
 
1235
}