GCC Code Coverage Report


Directory: ./
File: panels/wacom/cc-wacom-device.c
Date: 2024-05-03 09:46:52
Exec Total Coverage
Lines: 0 182 0.0%
Functions: 0 27 0.0%
Branches: 0 107 0.0%

Line Branch Exec Source
1 /*
2 * Copyright © 2016 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: Carlos Garnacho <carlosg@gnome.org>
18 *
19 */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include "cc-wacom-device.h"
25
26 #include <glib/gi18n.h>
27
28 enum {
29 PROP_0,
30 PROP_DEVICE,
31 N_PROPS
32 };
33
34 GParamSpec *props[N_PROPS] = { 0 };
35
36 typedef struct _CcWacomDevice CcWacomDevice;
37
38 struct _CcWacomDevice {
39 GObject parent_instance;
40
41 GsdDevice *device;
42 WacomDevice *wdevice;
43 };
44
45 static void cc_wacom_device_initable_iface_init (GInitableIface *iface);
46
47 G_DEFINE_TYPE_WITH_CODE (CcWacomDevice, cc_wacom_device, G_TYPE_OBJECT,
48 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
49 cc_wacom_device_initable_iface_init))
50
51 WacomDeviceDatabase *
52 cc_wacom_device_database_get (void)
53 {
54 static WacomDeviceDatabase *db = NULL;
55
56 if (g_once_init_enter (&db)) {
57 gpointer p = libwacom_database_new ();
58 g_once_init_leave (&db, p);
59 }
60
61 return db;
62 }
63
64 static void
65 cc_wacom_device_init (CcWacomDevice *device)
66 {
67 }
68
69 static void
70 cc_wacom_device_set_property (GObject *object,
71 guint prop_id,
72 const GValue *value,
73 GParamSpec *pspec)
74 {
75 CcWacomDevice *device = CC_WACOM_DEVICE (object);
76
77 switch (prop_id) {
78 case PROP_DEVICE:
79 device->device = g_value_get_object (value);
80 break;
81 default:
82 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
83 break;
84 }
85 }
86
87 static void
88 cc_wacom_device_get_property (GObject *object,
89 guint prop_id,
90 GValue *value,
91 GParamSpec *pspec)
92 {
93 CcWacomDevice *device = CC_WACOM_DEVICE (object);
94
95 switch (prop_id) {
96 case PROP_DEVICE:
97 g_value_set_object (value, device->device);
98 break;
99 default:
100 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101 break;
102 }
103 }
104
105 static void
106 cc_wacom_device_finalize (GObject *object)
107 {
108 CcWacomDevice *device = CC_WACOM_DEVICE (object);
109
110 g_clear_pointer (&device->wdevice, libwacom_destroy);
111
112 G_OBJECT_CLASS (cc_wacom_device_parent_class)->finalize (object);
113 }
114
115 static void
116 cc_wacom_device_class_init (CcWacomDeviceClass *klass)
117 {
118 GObjectClass *object_class = G_OBJECT_CLASS (klass);
119
120 object_class->set_property = cc_wacom_device_set_property;
121 object_class->get_property = cc_wacom_device_get_property;
122 object_class->finalize = cc_wacom_device_finalize;
123
124 props[PROP_DEVICE] =
125 g_param_spec_object ("device",
126 "device",
127 "device",
128 GSD_TYPE_DEVICE,
129 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
130
131 g_object_class_install_properties (object_class, N_PROPS, props);
132 }
133
134 static gboolean
135 cc_wacom_device_initable_init (GInitable *initable,
136 GCancellable *cancellable,
137 GError **error)
138 {
139 CcWacomDevice *device = CC_WACOM_DEVICE (initable);
140 WacomDeviceDatabase *wacom_db;
141 WacomError *wacom_error;
142 const gchar *node_path;
143
144 wacom_db = cc_wacom_device_database_get ();
145 node_path = gsd_device_get_device_file (device->device);
146 wacom_error = libwacom_error_new ();
147 device->wdevice = libwacom_new_from_path (wacom_db, node_path, WFALLBACK_NONE, wacom_error);
148
149 if (!device->wdevice) {
150 g_debug ("libwacom_new_from_path() failed: %s", libwacom_error_get_message (wacom_error));
151 libwacom_error_free (&wacom_error);
152 g_set_error (error, 0, 0, "Tablet description not found");
153 return FALSE;
154 }
155 libwacom_error_free (&wacom_error);
156
157 return TRUE;
158 }
159
160 static void
161 cc_wacom_device_initable_iface_init (GInitableIface *iface)
162 {
163 iface->init = cc_wacom_device_initable_init;
164 }
165
166 CcWacomDevice *
167 cc_wacom_device_new (GsdDevice *device)
168 {
169 return g_initable_new (CC_TYPE_WACOM_DEVICE,
170 NULL, NULL,
171 "device", device,
172 NULL);
173 }
174
175 CcWacomDevice *
176 cc_wacom_device_new_fake (const gchar *name)
177 {
178 CcWacomDevice *device;
179 WacomDevice *wacom_device;
180 WacomError *wacom_error;
181
182 device = g_object_new (CC_TYPE_WACOM_DEVICE,
183 NULL);
184
185 wacom_error = libwacom_error_new ();
186 wacom_device = libwacom_new_from_name (cc_wacom_device_database_get(),
187 name, wacom_error);
188 if (wacom_device == NULL) {
189 g_debug ("libwacom_new_fake() failed: %s", libwacom_error_get_message (wacom_error));
190 g_clear_object (&device);
191 } else {
192 device->wdevice = wacom_device;
193 }
194 libwacom_error_free (&wacom_error);
195
196 return device;
197 }
198
199 const gchar *
200 cc_wacom_device_get_name (CcWacomDevice *device)
201 {
202 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
203
204 return libwacom_get_name (device->wdevice);
205 }
206
207 const gchar *
208 cc_wacom_device_get_icon_name (CcWacomDevice *device)
209 {
210 WacomIntegrationFlags integration_flags;
211
212 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
213
214 integration_flags = libwacom_get_integration_flags (device->wdevice);
215
216 if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
217 return "wacom-tablet-pc";
218 } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
219 return "wacom-tablet-cintiq";
220 } else {
221 return "wacom-tablet";
222 }
223 }
224
225 gboolean
226 cc_wacom_device_is_reversible (CcWacomDevice *device)
227 {
228 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), FALSE);
229
230 return libwacom_is_reversible (device->wdevice);
231 }
232
233 WacomIntegrationFlags
234 cc_wacom_device_get_integration_flags (CcWacomDevice *device)
235 {
236 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
237
238 return libwacom_get_integration_flags (device->wdevice);
239 }
240
241 GsdDevice *
242 cc_wacom_device_get_device (CcWacomDevice *device)
243 {
244 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
245
246 return device->device;
247 }
248
249 GSettings *
250 cc_wacom_device_get_settings (CcWacomDevice *device)
251 {
252 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
253
254 return gsd_device_get_settings (device->device);
255 }
256
257 const gint *
258 cc_wacom_device_get_supported_tools (CcWacomDevice *device,
259 gint *n_tools)
260 {
261 *n_tools = 0;
262
263 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
264
265 return libwacom_get_supported_styli (device->wdevice, n_tools);
266 }
267
268 static GnomeRROutput *
269 find_output_by_edid (GnomeRRScreen *rr_screen,
270 const gchar *vendor,
271 const gchar *product,
272 const gchar *serial,
273 const gchar *name)
274 {
275 GnomeRROutput **rr_outputs;
276 GnomeRROutput *retval = NULL;
277 guint i;
278
279 rr_outputs = gnome_rr_screen_list_outputs (rr_screen);
280
281 for (i = 0; rr_outputs[i] != NULL; i++) {
282 g_autofree gchar *o_vendor = NULL;
283 g_autofree gchar *o_product = NULL;
284 g_autofree gchar *o_serial = NULL;
285 const gchar *o_name;
286 gboolean match;
287
288 o_name = gnome_rr_output_get_name (rr_outputs[i]);
289 gnome_rr_output_get_ids_from_edid (rr_outputs[i],
290 &o_vendor,
291 &o_product,
292 &o_serial);
293
294 g_debug ("Checking for match between '%s','%s','%s', '%s' and '%s','%s','%s', '%s'", \
295 vendor, product, serial, name, o_vendor, o_product, o_serial, o_name);
296
297 match = (g_strcmp0 (vendor, o_vendor) == 0) && \
298 (g_strcmp0 (product, o_product) == 0) && \
299 (g_strcmp0 (serial, o_serial) == 0) && \
300 (g_strcmp0 (name, o_name) == 0);
301
302 if (match) {
303 retval = rr_outputs[i];
304 break;
305 }
306 }
307
308 if (retval == NULL)
309 g_debug ("Did not find a matching output for EDID '%s,%s,%s'",
310 vendor, product, serial);
311
312 return retval;
313 }
314
315 static GnomeRROutput *
316 find_output (GnomeRRScreen *rr_screen,
317 CcWacomDevice *device)
318 {
319 g_autoptr(GSettings) settings = NULL;
320 g_autoptr(GVariant) variant = NULL;
321 g_autofree const gchar **edid = NULL;
322 const gchar *connector_name = NULL;
323 gsize n;
324
325 settings = cc_wacom_device_get_settings (device);
326 variant = g_settings_get_value (settings, "output");
327 edid = g_variant_get_strv (variant, &n);
328
329 if (n < 3) {
330 g_critical ("Expected 'output' key to store at least %d values; got %"G_GSIZE_FORMAT".", 3, n);
331 return NULL;
332 }
333 if (n >= 4)
334 connector_name = edid[3];
335
336 if (strlen (edid[0]) == 0 || strlen (edid[1]) == 0 || strlen (edid[2]) == 0)
337 return NULL;
338
339 return find_output_by_edid (rr_screen, edid[0], edid[1], edid[2], connector_name);
340 }
341
342 GnomeRROutput *
343 cc_wacom_device_get_output (CcWacomDevice *device,
344 GnomeRRScreen *rr_screen)
345 {
346 GnomeRROutput *rr_output;
347 GnomeRRCrtc *crtc;
348
349 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
350 g_return_val_if_fail (GNOME_RR_IS_SCREEN (rr_screen), NULL);
351
352 rr_output = find_output (rr_screen, device);
353 if (rr_output == NULL) {
354 return NULL;
355 }
356
357 crtc = gnome_rr_output_get_crtc (rr_output);
358
359 if (!crtc || gnome_rr_crtc_get_current_mode (crtc) == NULL) {
360 g_debug ("Output is not active.");
361 return NULL;
362 }
363
364 return rr_output;
365 }
366
367 void
368 cc_wacom_device_set_output (CcWacomDevice *device,
369 GnomeRROutput *output)
370 {
371 g_autoptr(GSettings) settings = NULL;
372 g_autofree gchar *vendor = NULL;
373 g_autofree gchar *product = NULL;
374 g_autofree gchar *serial = NULL;
375 const gchar *values[] = { "", "", "", NULL };
376
377 g_return_if_fail (CC_IS_WACOM_DEVICE (device));
378
379 vendor = product = serial = NULL;
380 settings = cc_wacom_device_get_settings (device);
381
382 if (output != NULL) {
383 gnome_rr_output_get_ids_from_edid (output,
384 &vendor,
385 &product,
386 &serial);
387 values[0] = vendor;
388 values[1] = product;
389 values[2] = serial;
390 }
391
392 g_settings_set_strv (settings, "output", values);
393 }
394
395 guint
396 cc_wacom_device_get_num_buttons (CcWacomDevice *device)
397 {
398 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), 0);
399
400 return libwacom_get_num_buttons (device->wdevice);
401 }
402
403 GSettings *
404 cc_wacom_device_get_button_settings (CcWacomDevice *device,
405 guint button)
406 {
407 g_autoptr(GSettings) tablet_settings = NULL;
408 GSettings *settings;
409 g_autofree gchar *path = NULL;
410 g_autofree gchar *button_path = NULL;
411
412 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
413
414 if (button > cc_wacom_device_get_num_buttons (device))
415 return NULL;
416
417 tablet_settings = cc_wacom_device_get_settings (device);
418 g_object_get (tablet_settings, "path", &path, NULL);
419
420 button_path = g_strdup_printf ("%sbutton%c/", path, 'A' + button);
421 settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
422 button_path);
423
424 return settings;
425 }
426
427 const gchar *
428 cc_wacom_device_get_description (CcWacomDevice *device)
429 {
430 WacomIntegrationFlags integration_flags;
431
432 g_return_val_if_fail (CC_IS_WACOM_DEVICE (device), NULL);
433
434 integration_flags = libwacom_get_integration_flags (device->wdevice);
435
436 if (integration_flags & WACOM_DEVICE_INTEGRATED_SYSTEM) {
437 return _("Tablet mounted on laptop panel");
438 } else if (integration_flags & WACOM_DEVICE_INTEGRATED_DISPLAY) {
439 return _("Tablet mounted on external display");
440 } else {
441 return _("External tablet device");
442 }
443 }
444