GCC Code Coverage Report


Directory: ./
File: panels/wacom/cc-wacom-panel.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 323 0.0%
Functions: 0 33 0.0%
Branches: 0 161 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 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, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors: Peter Hutterer <peter.hutterer@redhat.com>
18 * Bastien Nocera <hadess@hadess.net>
19 *
20 */
21
22 #include <config.h>
23
24 #include <string.h>
25 #include <gtk/gtk.h>
26 #include <glib/gi18n-lib.h>
27
28 #include "shell/cc-application.h"
29 #include "shell/cc-log.h"
30 #include "cc-wacom-panel.h"
31 #include "cc-wacom-page.h"
32 #include "cc-wacom-ekr-page.h"
33 #include "cc-wacom-stylus-page.h"
34 #include "cc-wacom-resources.h"
35 #include "cc-drawing-area.h"
36 #include "cc-tablet-tool-map.h"
37 #include "gsd-device-manager.h"
38
39 #ifdef GDK_WINDOWING_WAYLAND
40 #include <gdk/wayland/gdkwayland.h>
41 #endif
42
43 #define EKR_VENDOR "056a"
44 #define EKR_PRODUCT "0331"
45 #define POLL_MS 300
46
47 struct _CcWacomPanel
48 {
49 CcPanel parent_instance;
50
51 GtkWidget *test_popover;
52 GtkWidget *test_draw_area;
53 GtkWidget *test_button;
54 GtkWidget *scrollable;
55 GtkWidget *tablets;
56 GtkWidget *styli;
57 GtkWidget *initial_state_stack;
58 GtkWidget *panel_view;
59 GtkWidget *panel_empty_state;
60 GHashTable *devices; /* key=GsdDevice, value=CcWacomDevice */
61 GHashTable *pages; /* key=CcWacomDevice, value=GtkWidget */
62 GHashTable *stylus_pages; /* key=CcWacomTool, value=CcWacomStylusPage */
63 guint mock_stylus_id;
64
65 CcTabletToolMap *tablet_tool_map;
66
67 GtkAdjustment *vadjustment;
68 GtkGesture *stylus_gesture;
69
70 GtkWidget *highlighted_widget;
71 CcWacomStylusPage *highlighted_stylus_page;
72 guint highlight_timeout_id;
73
74 /* DBus */
75 GDBusProxy *proxy;
76 GDBusProxy *input_mapping_proxy;
77 };
78
79 CC_PANEL_REGISTER (CcWacomPanel, cc_wacom_panel)
80
81 typedef struct {
82 const char *name;
83 CcWacomDevice *stylus;
84 CcWacomDevice *pad;
85 } Tablet;
86
87 enum {
88 WACOM_PAGE = -1,
89 PLUG_IN_PAGE = 0,
90 };
91
92 enum {
93 PROP_0,
94 PROP_PARAMETERS
95 };
96
97 /* Static init function */
98 static void
99 update_visibility (GsdDeviceManager *manager,
100 GsdDevice *device,
101 gpointer user_data)
102 {
103 CcApplication *application;
104 g_autoptr(GList) devices = NULL;
105 guint i;
106
107 devices = gsd_device_manager_list_devices (manager, GSD_DEVICE_TYPE_TABLET);
108 i = g_list_length (devices);
109
110 /* Set the new visibility */
111 application = CC_APPLICATION (g_application_get_default ());
112 cc_shell_model_set_panel_visibility (cc_application_get_model (application),
113 "wacom",
114 i > 0 ? CC_PANEL_VISIBLE : CC_PANEL_VISIBLE_IN_SEARCH);
115
116 g_debug ("Wacom panel visible: %s", i > 0 ? "yes" : "no");
117 }
118
119 void
120 cc_wacom_panel_static_init_func (void)
121 {
122 GsdDeviceManager *manager;
123
124 manager = gsd_device_manager_get ();
125 g_signal_connect (G_OBJECT (manager), "device-added",
126 G_CALLBACK (update_visibility), NULL);
127 g_signal_connect (G_OBJECT (manager), "device-removed",
128 G_CALLBACK (update_visibility), NULL);
129 update_visibility (manager, NULL, NULL);
130 }
131
132 static CcWacomDevice *
133 lookup_wacom_device (CcWacomPanel *self,
134 const gchar *name)
135 {
136 GHashTableIter iter;
137 CcWacomDevice *wacom_device;
138
139 g_hash_table_iter_init (&iter, self->devices);
140 while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &wacom_device)) {
141 if (g_strcmp0 (cc_wacom_device_get_name (wacom_device), name) == 0)
142 return wacom_device;
143 }
144
145 return NULL;
146 }
147
148 static void
149 highlight_widget (CcWacomPanel *self, GtkWidget *widget)
150 {
151 graphene_point_t p;
152
153 if (self->highlighted_widget == widget)
154 return;
155
156 if (!gtk_widget_compute_point (widget,
157 self->scrollable,
158 &GRAPHENE_POINT_INIT (0, 0),
159 &p))
160 return;
161
162 gtk_adjustment_set_value (self->vadjustment, p.y);
163 self->highlighted_widget = widget;
164 }
165
166 static CcWacomPage *
167 update_highlighted_device (CcWacomPanel *self, const gchar *device_name)
168 {
169 CcWacomPage *page;
170 CcWacomDevice *wacom_device;
171
172 if (device_name == NULL)
173 return NULL;
174
175 wacom_device = lookup_wacom_device (self, device_name);
176 if (!wacom_device) {
177 g_warning ("Failed to find device '%s', supplied in the command line.", device_name);
178 return NULL;
179 }
180
181 page = g_hash_table_lookup (self->pages, wacom_device);
182 highlight_widget (self, GTK_WIDGET (page));
183
184 return page;
185 }
186
187 static void
188 run_operation_from_params (CcWacomPanel *self, GVariant *parameters)
189 {
190 g_autoptr(GVariant) v = NULL;
191 g_autoptr(GVariant) v2 = NULL;
192 CcWacomPage *page;
193 const gchar *operation = NULL;
194 const gchar *device_name = NULL;
195 gint n_params;
196
197 n_params = g_variant_n_children (parameters);
198
199 g_variant_get_child (parameters, n_params - 1, "v", &v);
200 device_name = g_variant_get_string (v, NULL);
201
202 if (!g_variant_is_of_type (v, G_VARIANT_TYPE_STRING)) {
203 g_warning ("Wrong type for the second argument GVariant, expected 's' but got '%s'",
204 g_variant_get_type_string (v));
205 return;
206 }
207
208 switch (n_params) {
209 case 3:
210 page = update_highlighted_device (self, device_name);
211 if (page == NULL)
212 return;
213
214 g_variant_get_child (parameters, 1, "v", &v2);
215
216 if (!g_variant_is_of_type (v2, G_VARIANT_TYPE_STRING)) {
217 g_warning ("Wrong type for the operation name argument. A string is expected.");
218 break;
219 }
220
221 operation = g_variant_get_string (v2, NULL);
222 if (g_strcmp0 (operation, "run-calibration") == 0) {
223 if (cc_wacom_page_can_calibrate (page))
224 cc_wacom_page_calibrate (page);
225 else
226 g_warning ("The device %s cannot be calibrated.", device_name);
227 } else {
228 g_warning ("Ignoring unrecognized operation '%s'", operation);
229 }
230 case 2:
231 update_highlighted_device (self, device_name);
232 break;
233 case 1:
234 g_assert_not_reached ();
235 default:
236 g_warning ("Unexpected number of parameters found: %d. Request ignored.", n_params);
237 }
238 }
239
240 /* Boilerplate code goes below */
241
242 static void
243 cc_wacom_panel_get_property (GObject *object,
244 guint property_id,
245 GValue *value,
246 GParamSpec *pspec)
247 {
248 switch (property_id)
249 {
250 default:
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
252 }
253 }
254
255 static void
256 cc_wacom_panel_set_property (GObject *object,
257 guint property_id,
258 const GValue *value,
259 GParamSpec *pspec)
260 {
261 CcWacomPanel *self;
262 self = CC_WACOM_PANEL (object);
263
264 switch (property_id)
265 {
266 case PROP_PARAMETERS: {
267 GVariant *parameters;
268
269 parameters = g_value_get_variant (value);
270 if (parameters == NULL || g_variant_n_children (parameters) <= 1)
271 return;
272
273 run_operation_from_params (self, parameters);
274
275 break;
276 }
277 default:
278 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
279 }
280 }
281
282 static void
283 cc_wacom_panel_dispose (GObject *object)
284 {
285 CcWacomPanel *self = CC_WACOM_PANEL (object);
286 CcShell *shell;
287
288 shell = cc_panel_get_shell (CC_PANEL (self));
289 if (shell) {
290 gtk_widget_remove_controller (GTK_WIDGET (shell),
291 GTK_EVENT_CONTROLLER (self->stylus_gesture));
292 }
293
294
295 g_clear_pointer (&self->devices, g_hash_table_unref);
296 g_clear_object (&self->proxy);
297 g_clear_object (&self->input_mapping_proxy);
298 g_clear_pointer (&self->pages, g_hash_table_unref);
299 g_clear_pointer (&self->stylus_pages, g_hash_table_unref);
300 g_clear_handle_id (&self->mock_stylus_id, g_source_remove);
301 g_clear_handle_id (&self->highlight_timeout_id, g_source_remove);
302 g_clear_object (&self->highlighted_stylus_page);
303
304 G_OBJECT_CLASS (cc_wacom_panel_parent_class)->dispose (object);
305 }
306
307 static void
308 check_remove_stylus_pages (CcWacomPanel *self)
309 {
310 GHashTableIter iter;
311 CcWacomDevice *device;
312 CcWacomTool *tool;
313 CcWacomStylusPage *page;
314 GList *tools;
315 g_autoptr(GList) total = NULL;
316
317 /* First. Iterate known devices and get the tools */
318 g_hash_table_iter_init (&iter, self->devices);
319 while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &device)) {
320 tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
321 total = g_list_concat (total, tools);
322 }
323
324 /* Second. Iterate through stylus pages and remove the ones whose
325 * tool is no longer in the list.
326 */
327 g_hash_table_iter_init (&iter, self->stylus_pages);
328 while (g_hash_table_iter_next (&iter, (gpointer*) &tool, (gpointer*) &page)) {
329 if (g_list_find (total, tool))
330 continue;
331
332 if (page == self->highlighted_stylus_page) {
333 g_clear_object (&self->highlighted_stylus_page);
334 g_clear_handle_id (&self->highlight_timeout_id, g_source_remove);
335 }
336
337 gtk_box_remove (GTK_BOX (self->styli), GTK_WIDGET (page));
338 g_hash_table_iter_remove (&iter);
339 }
340
341 }
342
343 static gboolean
344 add_stylus (CcWacomPanel *self,
345 CcWacomTool *tool)
346 {
347 GtkWidget *page;
348
349 if (g_hash_table_lookup (self->stylus_pages, tool))
350 return FALSE;
351
352 page = cc_wacom_stylus_page_new (self, tool);
353 gtk_box_append (GTK_BOX (self->styli), page);
354 g_hash_table_insert (self->stylus_pages, tool, page);
355
356 return TRUE;
357 }
358
359 static void
360 update_test_button (CcWacomPanel *self)
361 {
362 if (!self->test_button)
363 return;
364
365 if (g_hash_table_size (self->devices) == 0) {
366 gtk_popover_popdown (GTK_POPOVER (self->test_popover));
367 gtk_widget_set_sensitive (self->test_button, FALSE);
368 } else {
369 gtk_widget_set_sensitive (self->test_button, TRUE);
370 }
371 }
372
373 static void
374 update_initial_state (CcWacomPanel *self)
375 {
376 gtk_stack_set_visible_child (GTK_STACK (self->initial_state_stack),
377 g_hash_table_size (self->devices) == 0 ?
378 self->panel_empty_state :
379 self->panel_view);
380 }
381
382 static void
383 on_stylus_timeout (gpointer data)
384 {
385 CcWacomPanel *panel = CC_WACOM_PANEL (data);
386
387 cc_wacom_stylus_page_set_highlight (panel->highlighted_stylus_page, FALSE);
388 g_clear_object (&panel->highlighted_stylus_page);
389 panel->highlight_timeout_id = 0;
390 }
391
392 static void
393 update_highlighted_stylus (CcWacomPanel *self,
394 CcWacomTool *stylus_to_highlight)
395 {
396 GHashTableIter iter;
397 CcWacomTool *stylus;
398 CcWacomStylusPage *page;
399
400 g_hash_table_iter_init (&iter, self->stylus_pages);
401 while (g_hash_table_iter_next (&iter, (gpointer *)&stylus, (gpointer *)&page)) {
402 gboolean highlight = stylus == stylus_to_highlight;
403 cc_wacom_stylus_page_set_highlight (page, highlight);
404 if (highlight) {
405 highlight_widget (self, GTK_WIDGET (page));
406 g_clear_object (&self->highlighted_stylus_page);
407 g_clear_handle_id (&self->highlight_timeout_id, g_source_remove);
408 self->highlight_timeout_id = g_timeout_add_once (POLL_MS, on_stylus_timeout, self);
409 self->highlighted_stylus_page = g_object_ref (page);
410 }
411 }
412
413 }
414
415 static void
416 update_current_tool (CcWacomPanel *self,
417 GdkDevice *device,
418 GdkDeviceTool *tool)
419 {
420 GsdDeviceManager *device_manager;
421 CcWacomDevice *wacom_device;
422 CcWacomTool *stylus;
423 GsdDevice *gsd_device;
424 guint64 serial, id;
425
426 if (!tool)
427 return;
428
429 /* Work our way to the CcWacomDevice */
430 device_manager = gsd_device_manager_get ();
431 gsd_device = gsd_device_manager_lookup_gdk_device (device_manager,
432 device);
433 if (!gsd_device)
434 return;
435
436 wacom_device = g_hash_table_lookup (self->devices, gsd_device);
437 if (!wacom_device)
438 return;
439
440 /* Check whether we already know this tool, nothing to do then */
441 serial = gdk_device_tool_get_serial (tool);
442
443 /* The wacom driver sends serial-less tools with a serial of
444 * 1, libinput uses 0. No device exists with serial 1, let's reset
445 * it here so everything else works as expected.
446 */
447 if (serial == 1)
448 serial = 0;
449
450 stylus = cc_tablet_tool_map_lookup_tool (self->tablet_tool_map,
451 wacom_device, serial);
452
453 if (!stylus) {
454 id = gdk_device_tool_get_hardware_id (tool);
455
456 /* The wacom driver sends a hw id of 0x2 for stylus and 0xa
457 * for eraser for devices that don't have a true HW id.
458 * Reset those to 0 so we can use the same code-paths
459 * libinput uses.
460 * The touch ID is 0x3, let's ignore that because we don't
461 * have a touch tool and it only happens when the wacom
462 * driver handles the touch device.
463 */
464 if (id == 0x2 || id == 0xa)
465 id = 0;
466 else if (id == 0x3)
467 return;
468
469 stylus = cc_wacom_tool_new (serial, id, wacom_device);
470 if (!stylus)
471 return;
472 }
473
474 add_stylus (self, stylus);
475
476 update_highlighted_stylus (self, stylus);
477
478 cc_tablet_tool_map_add_relation (self->tablet_tool_map,
479 wacom_device, stylus);
480 }
481
482 static void
483 on_stylus_proximity_cb (CcWacomPanel *self,
484 double x,
485 double y,
486 GtkGestureStylus *gesture)
487 {
488 GdkDevice *device;
489 GdkDeviceTool *tool;
490
491 device = gtk_event_controller_get_current_event_device (GTK_EVENT_CONTROLLER (gesture));
492 tool = gtk_gesture_stylus_get_device_tool (gesture);
493 update_current_tool (self, device, tool);
494 }
495
496 static gboolean
497 show_mock_stylus_cb (gpointer user_data)
498 {
499 CcWacomPanel *self = user_data;
500 GList *device_list;
501 CcWacomDevice *wacom_device;
502 CcWacomTool *stylus;
503
504 self->mock_stylus_id = 0;
505
506 device_list = g_hash_table_get_values (self->devices);
507 if (device_list == NULL) {
508 g_warning ("Could not create fake stylus event because could not find tablet device");
509 return G_SOURCE_REMOVE;
510 }
511
512 wacom_device = device_list->data;
513 g_list_free (device_list);
514
515 stylus = cc_wacom_tool_new (0, 0, wacom_device);
516 add_stylus (self, stylus);
517 update_highlighted_stylus (self, stylus);
518 cc_tablet_tool_map_add_relation (self->tablet_tool_map,
519 wacom_device, stylus);
520
521 return G_SOURCE_REMOVE;
522 }
523
524 static void
525 cc_wacom_panel_constructed (GObject *object)
526 {
527 CcWacomPanel *self = CC_WACOM_PANEL (object);
528 CcShell *shell;
529
530 G_OBJECT_CLASS (cc_wacom_panel_parent_class)->constructed (object);
531
532 /* Add test area button to shell header. */
533 shell = cc_panel_get_shell (CC_PANEL (self));
534
535 self->stylus_gesture = gtk_gesture_stylus_new ();
536 g_signal_connect_swapped (self->stylus_gesture, "proximity",
537 G_CALLBACK (on_stylus_proximity_cb), self);
538 gtk_widget_add_controller (GTK_WIDGET (shell),
539 GTK_EVENT_CONTROLLER (self->stylus_gesture));
540
541 if (g_getenv ("UMOCKDEV_DIR") != NULL)
542 self->mock_stylus_id = g_idle_add (show_mock_stylus_cb, self);
543 }
544
545 static const char *
546 cc_wacom_panel_get_help_uri (CcPanel *panel)
547 {
548 return "help:gnome-help/wacom";
549 }
550
551 static void
552 cc_wacom_panel_class_init (CcWacomPanelClass *klass)
553 {
554 GObjectClass *object_class = G_OBJECT_CLASS (klass);
555 CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
556 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
557
558 object_class->get_property = cc_wacom_panel_get_property;
559 object_class->set_property = cc_wacom_panel_set_property;
560 object_class->dispose = cc_wacom_panel_dispose;
561 object_class->constructed = cc_wacom_panel_constructed;
562
563 panel_class->get_help_uri = cc_wacom_panel_get_help_uri;
564
565 g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters");
566
567 g_type_ensure (CC_TYPE_DRAWING_AREA);
568
569 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/wacom/cc-wacom-panel.ui");
570
571 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, scrollable);
572 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_button);
573 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_popover);
574 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, test_draw_area);
575 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, tablets);
576 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, styli);
577 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, initial_state_stack);
578 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, panel_empty_state);
579 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, panel_view);
580 gtk_widget_class_bind_template_child (widget_class, CcWacomPanel, vadjustment);
581 }
582
583 static void
584 add_known_device (CcWacomPanel *self,
585 GsdDevice *gsd_device)
586 {
587 CcWacomDevice *device;
588 GsdDeviceType device_type;
589 g_autoptr(GList) tools = NULL;
590 GtkWidget *page;
591 gboolean is_ekr = FALSE;
592 GList *l;
593
594 device_type = gsd_device_get_device_type (gsd_device);
595
596 if ((device_type & GSD_DEVICE_TYPE_TABLET) == 0)
597 return;
598
599 if ((device_type &
600 (GSD_DEVICE_TYPE_TOUCHSCREEN |
601 GSD_DEVICE_TYPE_TOUCHPAD)) != 0) {
602 return;
603 }
604
605 if ((device_type & GSD_DEVICE_TYPE_PAD) != 0) {
606 const char *vendor, *product;
607
608 gsd_device_get_device_ids (gsd_device, &vendor, &product);
609 is_ekr = (g_strcmp0 (vendor, EKR_VENDOR) == 0 &&
610 g_strcmp0 (product, EKR_PRODUCT) == 0);
611
612 /* Express key remote is an special case, as it is an
613 * external pad device, we want to distinctly show it
614 * in the list. Other pads are mounted on a tablet, which
615 * get their own entries.
616 */
617 if (!is_ekr)
618 return;
619 }
620
621 device = cc_wacom_device_new (gsd_device);
622 if (!device)
623 return;
624
625 g_hash_table_insert (self->devices, gsd_device, device);
626
627 tools = cc_tablet_tool_map_list_tools (self->tablet_tool_map, device);
628
629 for (l = tools; l != NULL; l = l->next) {
630 add_stylus (self, l->data);
631 }
632
633 if (is_ekr)
634 page = cc_wacom_ekr_page_new (self, device);
635 else
636 page = cc_wacom_page_new (self, device);
637
638 gtk_box_append (GTK_BOX (self->tablets), page);
639 g_hash_table_insert (self->pages, device, page);
640 }
641
642 static void
643 device_removed_cb (CcWacomPanel *self,
644 GsdDevice *gsd_device)
645 {
646 CcWacomDevice *device;
647 GtkWidget *page;
648
649 device = g_hash_table_lookup (self->devices, gsd_device);
650 if (!device)
651 return;
652
653 page = g_hash_table_lookup (self->pages, device);
654 if (page) {
655 g_hash_table_remove (self->pages, device);
656 gtk_box_remove (GTK_BOX (self->tablets), page);
657 }
658
659 g_hash_table_remove (self->devices, gsd_device);
660 check_remove_stylus_pages (self);
661 update_test_button (self);
662 update_initial_state (self);
663 }
664
665 static void
666 device_added_cb (CcWacomPanel *self,
667 GsdDevice *device)
668 {
669 add_known_device (self, device);
670 update_test_button (self);
671 update_initial_state (self);
672 }
673
674 void
675 cc_wacom_panel_switch_to_panel (CcWacomPanel *self,
676 const char *panel)
677 {
678 CcShell *shell;
679 g_autoptr(GError) error = NULL;
680
681 g_return_if_fail (self);
682
683 shell = cc_panel_get_shell (CC_PANEL (self));
684 if (!cc_shell_set_active_panel_from_id (shell, panel, NULL, &error))
685 g_warning ("Failed to activate '%s' panel: %s", panel, error->message);
686 }
687
688 static void
689 got_osd_proxy_cb (GObject *source_object,
690 GAsyncResult *res,
691 gpointer data)
692 {
693 g_autoptr(GError) error = NULL;
694 CcWacomPanel *self;
695
696 self = CC_WACOM_PANEL (data);
697 self->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
698
699 if (self->proxy == NULL) {
700 g_printerr ("Error creating proxy: %s\n", error->message);
701 return;
702 }
703 }
704
705 static void
706 got_input_mapping_proxy_cb (GObject *source_object,
707 GAsyncResult *res,
708 gpointer data)
709 {
710 g_autoptr(GError) error = NULL;
711 CcWacomPanel *self;
712
713 self = CC_WACOM_PANEL (data);
714 self->input_mapping_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
715
716 if (self->input_mapping_proxy == NULL) {
717 g_printerr ("Error creating input mapping proxy: %s\n", error->message);
718 return;
719 }
720 }
721
722 static void
723 cc_wacom_panel_init (CcWacomPanel *self)
724 {
725 GsdDeviceManager *device_manager;
726 g_autoptr(GList) devices = NULL;
727 GList *l;
728 g_autoptr(GError) error = NULL;
729
730 g_resources_register (cc_wacom_get_resource ());
731
732 gtk_widget_init_template (GTK_WIDGET (self));
733
734 self->tablet_tool_map = cc_tablet_tool_map_new ();
735
736 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
737 G_DBUS_PROXY_FLAGS_NONE,
738 NULL,
739 "org.gnome.Shell",
740 "/org/gnome/Shell/Wacom",
741 "org.gnome.Shell.Wacom.PadOsd",
742 cc_panel_get_cancellable (CC_PANEL (self)),
743 got_osd_proxy_cb,
744 self);
745
746 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
747 G_DBUS_PROXY_FLAGS_NONE,
748 NULL,
749 "org.gnome.Shell",
750 "/org/gnome/Mutter/InputMapping",
751 "org.gnome.Mutter.InputMapping",
752 cc_panel_get_cancellable (CC_PANEL (self)),
753 got_input_mapping_proxy_cb,
754 self);
755
756 self->devices = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
757 self->pages = g_hash_table_new (NULL, NULL);
758 self->stylus_pages = g_hash_table_new (NULL, NULL);
759
760 device_manager = gsd_device_manager_get ();
761 g_signal_connect_object (device_manager, "device-added",
762 G_CALLBACK (device_added_cb), self, G_CONNECT_SWAPPED);
763 g_signal_connect_object (device_manager, "device-removed",
764 G_CALLBACK (device_removed_cb), self, G_CONNECT_SWAPPED);
765
766 devices = gsd_device_manager_list_devices (device_manager,
767 GSD_DEVICE_TYPE_TABLET);
768 for (l = devices; l ; l = l->next)
769 add_known_device (self, l->data);
770
771 update_test_button (self);
772 update_initial_state (self);
773 }
774
775 GDBusProxy *
776 cc_wacom_panel_get_gsd_wacom_bus_proxy (CcWacomPanel *self)
777 {
778 g_return_val_if_fail (CC_IS_WACOM_PANEL (self), NULL);
779
780 return self->proxy;
781 }
782
783 GDBusProxy *
784 cc_wacom_panel_get_input_mapping_bus_proxy (CcWacomPanel *self)
785 {
786 g_return_val_if_fail (CC_IS_WACOM_PANEL (self), NULL);
787
788 return self->input_mapping_proxy;
789 }
790