Line |
Branch |
Exec |
Source |
1 |
|
|
/* Copyright © 2018 Red Hat, Inc |
2 |
|
|
* |
3 |
|
|
* This program is free software; you can redistribute it and/or modify |
4 |
|
|
* it under the terms of the GNU General Public License as published by |
5 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
6 |
|
|
* (at your option) any later version. |
7 |
|
|
* |
8 |
|
|
* This program is distributed in the hope that it will be useful, |
9 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 |
|
|
* GNU General Public License for more details. |
12 |
|
|
* |
13 |
|
|
* You should have received a copy of the GNU General Public License |
14 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
15 |
|
|
* |
16 |
|
|
* Authors: Christian J. Kellner <ckellner@redhat.com> |
17 |
|
|
* |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#include <config.h> |
21 |
|
|
|
22 |
|
|
#include <glib/gi18n.h> |
23 |
|
|
#include <polkit/polkit.h> |
24 |
|
|
|
25 |
|
|
#include "shell/cc-application.h" |
26 |
|
|
#include "cc-bolt-device-dialog.h" |
27 |
|
|
#include "cc-bolt-device-entry.h" |
28 |
|
|
|
29 |
|
|
#include "bolt-client.h" |
30 |
|
|
#include "bolt-names.h" |
31 |
|
|
#include "bolt-str.h" |
32 |
|
|
|
33 |
|
|
#include "cc-bolt-page.h" |
34 |
|
|
|
35 |
|
|
struct _CcBoltPage |
36 |
|
|
{ |
37 |
|
|
AdwNavigationPage parent; |
38 |
|
|
|
39 |
|
|
BoltClient *client; |
40 |
|
|
|
41 |
|
|
/* headerbar menu */ |
42 |
|
|
GtkBox *headerbar_box; |
43 |
|
|
GtkLockButton *lock_button; |
44 |
|
|
|
45 |
|
|
/* main ui */ |
46 |
|
|
GtkStack *container; |
47 |
|
|
|
48 |
|
|
/* empty state */ |
49 |
|
|
AdwStatusPage *notb_page; |
50 |
|
|
|
51 |
|
|
/* notifications */ |
52 |
|
|
GtkLabel *notification_label; |
53 |
|
|
GtkRevealer *notification_revealer; |
54 |
|
|
|
55 |
|
|
/* authmode */ |
56 |
|
|
GtkSwitch *authmode_switch; |
57 |
|
|
GtkSpinner *authmode_spinner; |
58 |
|
|
GtkStack *direct_access_row; |
59 |
|
|
|
60 |
|
|
/* device list */ |
61 |
|
|
GHashTable *devices; |
62 |
|
|
|
63 |
|
|
GtkStack *devices_stack; |
64 |
|
|
GtkBox *devices_box; |
65 |
|
|
GtkBox *pending_box; |
66 |
|
|
|
67 |
|
|
GtkListBox *devices_list; |
68 |
|
|
GtkListBox *pending_list; |
69 |
|
|
|
70 |
|
|
/* device details dialog */ |
71 |
|
|
CcBoltDeviceDialog *device_dialog; |
72 |
|
|
|
73 |
|
|
/* polkit integration */ |
74 |
|
|
GPermission *permission; |
75 |
|
|
|
76 |
|
|
GCancellable *cancellable; |
77 |
|
|
}; |
78 |
|
|
|
79 |
|
|
/* initialization */ |
80 |
|
|
static void bolt_client_ready (GObject *source, |
81 |
|
|
GAsyncResult *res, |
82 |
|
|
gpointer user_data); |
83 |
|
|
|
84 |
|
|
/* panel functions */ |
85 |
|
|
static void cc_bolt_page_set_no_thunderbolt (CcBoltPage *self, |
86 |
|
|
const char *custom_msg); |
87 |
|
|
|
88 |
|
|
static void cc_bolt_page_name_owner_changed (CcBoltPage *self); |
89 |
|
|
|
90 |
|
|
static CcBoltDeviceEntry * cc_bolt_page_add_device (CcBoltPage *self, |
91 |
|
|
BoltDevice *dev); |
92 |
|
|
|
93 |
|
|
static void cc_bolt_page_del_device_entry (CcBoltPage *self, |
94 |
|
|
CcBoltDeviceEntry *entry); |
95 |
|
|
|
96 |
|
|
static void cc_bolt_page_authmode_sync (CcBoltPage *self); |
97 |
|
|
|
98 |
|
|
static void cc_panel_list_box_migrate (CcBoltPage *self, |
99 |
|
|
GtkListBox *from, |
100 |
|
|
GtkListBox *to, |
101 |
|
|
CcBoltDeviceEntry *entry); |
102 |
|
|
|
103 |
|
|
/* bolt client signals */ |
104 |
|
|
static void on_bolt_name_owner_changed_cb (GObject *object, |
105 |
|
|
GParamSpec *pspec, |
106 |
|
|
gpointer user_data); |
107 |
|
|
|
108 |
|
|
static void on_bolt_device_added_cb (BoltClient *cli, |
109 |
|
|
const char *path, |
110 |
|
|
CcBoltPage *self); |
111 |
|
|
|
112 |
|
|
static void on_bolt_device_removed_cb (BoltClient *cli, |
113 |
|
|
const char *opath, |
114 |
|
|
CcBoltPage *self); |
115 |
|
|
|
116 |
|
|
static void on_bolt_notify_authmode_cb (GObject *gobject, |
117 |
|
|
GParamSpec *pspec, |
118 |
|
|
gpointer user_data); |
119 |
|
|
|
120 |
|
|
/* panel signals */ |
121 |
|
|
static gboolean on_authmode_state_set_cb (CcBoltPage *self, |
122 |
|
|
gboolean state, |
123 |
|
|
GtkSwitch *toggle); |
124 |
|
|
|
125 |
|
|
static void on_device_entry_row_activated_cb (CcBoltPage *self, |
126 |
|
|
GtkListBoxRow *row); |
127 |
|
|
|
128 |
|
|
static void on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry, |
129 |
|
|
BoltStatus new_status, |
130 |
|
|
CcBoltPage *self); |
131 |
|
|
|
132 |
|
|
static void on_notification_button_clicked_cb (CcBoltPage *self); |
133 |
|
|
|
134 |
|
|
|
135 |
|
|
/* polkit */ |
136 |
|
|
static void on_permission_ready (GObject *source_object, |
137 |
|
|
GAsyncResult *res, |
138 |
|
|
gpointer user_data); |
139 |
|
|
|
140 |
|
|
static void on_permission_notify_cb (GPermission *permission, |
141 |
|
|
GParamSpec *pspec, |
142 |
|
|
CcBoltPage *self); |
143 |
|
|
|
144 |
|
✗ |
G_DEFINE_TYPE (CcBoltPage, cc_bolt_page, ADW_TYPE_NAVIGATION_PAGE) |
145 |
|
|
|
146 |
|
|
static void |
147 |
|
✗ |
update_visibility (BoltClient *client, |
148 |
|
|
const char *path, |
149 |
|
|
gpointer user_data) |
150 |
|
|
{ |
151 |
|
✗ |
g_autoptr(GPtrArray) devices = NULL; |
152 |
|
✗ |
gboolean visible = FALSE; |
153 |
|
|
CcBoltPage *self; |
154 |
|
|
|
155 |
|
✗ |
self = CC_BOLT_PAGE (user_data); |
156 |
|
|
|
157 |
|
✗ |
if (client) |
158 |
|
|
{ |
159 |
|
✗ |
devices = bolt_client_list_devices (client, self->cancellable, NULL); |
160 |
|
✗ |
if (devices) |
161 |
|
✗ |
visible = devices->len > 0; |
162 |
|
|
} |
163 |
|
|
|
164 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self), visible); |
165 |
|
✗ |
} |
166 |
|
|
|
167 |
|
|
static void |
168 |
|
✗ |
on_visibility_client_ready (GObject *source, |
169 |
|
|
GAsyncResult *res, |
170 |
|
|
gpointer user_data) |
171 |
|
|
{ |
172 |
|
|
BoltClient *client; |
173 |
|
|
CcBoltPage *self; |
174 |
|
|
|
175 |
|
✗ |
self = CC_BOLT_PAGE (user_data); |
176 |
|
|
|
177 |
|
✗ |
client = bolt_client_new_finish (res, NULL); |
178 |
|
✗ |
if (client == NULL) |
179 |
|
|
{ |
180 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self), FALSE); |
181 |
|
✗ |
return; |
182 |
|
|
} |
183 |
|
|
|
184 |
|
✗ |
g_signal_connect_object (client, |
185 |
|
|
"device-added", |
186 |
|
|
G_CALLBACK (update_visibility), |
187 |
|
|
self, |
188 |
|
|
0); |
189 |
|
✗ |
g_signal_connect_object (client, |
190 |
|
|
"device-removed", |
191 |
|
|
G_CALLBACK (update_visibility), |
192 |
|
|
self, |
193 |
|
|
0); |
194 |
|
✗ |
update_visibility (client, NULL, self); |
195 |
|
|
} |
196 |
|
|
|
197 |
|
|
static void |
198 |
|
✗ |
bolt_client_ready (GObject *source, |
199 |
|
|
GAsyncResult *res, |
200 |
|
|
gpointer user_data) |
201 |
|
|
{ |
202 |
|
✗ |
g_autoptr(GError) err = NULL; |
203 |
|
✗ |
g_autoptr(CcBoltPage) self = NULL; |
204 |
|
|
BoltClient *client; |
205 |
|
|
|
206 |
|
✗ |
self = CC_BOLT_PAGE (user_data); |
207 |
|
✗ |
client = bolt_client_new_finish (res, &err); |
208 |
|
|
|
209 |
|
✗ |
if (client == NULL) |
210 |
|
|
{ |
211 |
|
|
const char *text; |
212 |
|
|
|
213 |
|
|
/* operation got cancelled because the panel got destroyed */ |
214 |
|
✗ |
if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_CANCELLED) || |
215 |
|
✗ |
g_error_matches (err, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED)) |
216 |
|
✗ |
return; |
217 |
|
|
|
218 |
|
✗ |
g_warning ("Could not create client: %s", err->message); |
219 |
|
✗ |
text = _("The Thunderbolt subsystem (boltd) is not installed or " |
220 |
|
|
"not set up properly."); |
221 |
|
|
|
222 |
|
✗ |
adw_status_page_set_description (self->notb_page, text); |
223 |
|
✗ |
gtk_stack_set_visible_child_name (self->container, "no-thunderbolt"); |
224 |
|
|
|
225 |
|
✗ |
return; |
226 |
|
|
} |
227 |
|
|
|
228 |
|
✗ |
g_signal_connect_object (client, |
229 |
|
|
"notify::g-name-owner", |
230 |
|
|
G_CALLBACK (on_bolt_name_owner_changed_cb), |
231 |
|
|
self, |
232 |
|
|
0); |
233 |
|
|
|
234 |
|
✗ |
g_signal_connect_object (client, |
235 |
|
|
"device-added", |
236 |
|
|
G_CALLBACK (on_bolt_device_added_cb), |
237 |
|
|
self, |
238 |
|
|
0); |
239 |
|
|
|
240 |
|
✗ |
g_signal_connect_object (client, |
241 |
|
|
"device-removed", |
242 |
|
|
G_CALLBACK (on_bolt_device_removed_cb), |
243 |
|
|
self, |
244 |
|
|
0); |
245 |
|
|
|
246 |
|
✗ |
g_signal_connect_object (client, |
247 |
|
|
"notify::auth-mode", |
248 |
|
|
G_CALLBACK (on_bolt_notify_authmode_cb), |
249 |
|
|
self, |
250 |
|
|
0); |
251 |
|
|
|
252 |
|
|
/* Treat security-level changes, which should rarely happen, as |
253 |
|
|
* if the name owner changed, i.e. as if boltd got restarted */ |
254 |
|
✗ |
g_signal_connect_object (client, |
255 |
|
|
"notify::security-level", |
256 |
|
|
G_CALLBACK (on_bolt_name_owner_changed_cb), |
257 |
|
|
self, |
258 |
|
|
0); |
259 |
|
|
|
260 |
|
✗ |
self->client = client; |
261 |
|
|
|
262 |
|
✗ |
cc_bolt_device_dialog_set_client (self->device_dialog, client); |
263 |
|
|
|
264 |
|
✗ |
cc_bolt_page_authmode_sync (self); |
265 |
|
|
|
266 |
|
✗ |
g_object_bind_property (self->authmode_switch, |
267 |
|
|
"active", |
268 |
|
✗ |
self->devices_box, |
269 |
|
|
"sensitive", |
270 |
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); |
271 |
|
|
|
272 |
|
✗ |
g_object_bind_property (self->authmode_switch, |
273 |
|
|
"active", |
274 |
|
✗ |
self->pending_box, |
275 |
|
|
"sensitive", |
276 |
|
|
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); |
277 |
|
|
|
278 |
|
✗ |
gtk_stack_set_visible_child_name (self->devices_stack, "no-devices"); |
279 |
|
✗ |
cc_bolt_page_name_owner_changed (self); |
280 |
|
|
} |
281 |
|
|
|
282 |
|
|
static gboolean |
283 |
|
✗ |
devices_table_transfer_entry (GHashTable *from, |
284 |
|
|
GHashTable *to, |
285 |
|
|
gconstpointer key) |
286 |
|
|
{ |
287 |
|
|
gpointer k, v; |
288 |
|
|
gboolean found; |
289 |
|
|
|
290 |
|
✗ |
found = g_hash_table_lookup_extended (from, key, &k, &v); |
291 |
|
|
|
292 |
|
✗ |
if (found) |
293 |
|
|
{ |
294 |
|
✗ |
g_hash_table_steal (from, key); |
295 |
|
✗ |
g_hash_table_insert (to, k, v); |
296 |
|
|
} |
297 |
|
|
|
298 |
|
✗ |
return found; |
299 |
|
|
} |
300 |
|
|
|
301 |
|
|
static void |
302 |
|
✗ |
devices_table_clear_entries (GHashTable *table, |
303 |
|
|
CcBoltPage *self) |
304 |
|
|
{ |
305 |
|
|
GHashTableIter iter; |
306 |
|
|
gpointer key, value; |
307 |
|
|
|
308 |
|
✗ |
g_hash_table_iter_init (&iter, table); |
309 |
|
✗ |
while (g_hash_table_iter_next (&iter, &key, &value)) |
310 |
|
|
{ |
311 |
|
✗ |
CcBoltDeviceEntry *entry = value; |
312 |
|
|
|
313 |
|
✗ |
cc_bolt_page_del_device_entry (self, entry); |
314 |
|
✗ |
g_hash_table_iter_remove (&iter); |
315 |
|
|
} |
316 |
|
✗ |
} |
317 |
|
|
|
318 |
|
|
static void |
319 |
|
✗ |
devices_table_synchronize (CcBoltPage *self) |
320 |
|
|
{ |
321 |
|
✗ |
g_autoptr(GHashTable) old = NULL; |
322 |
|
✗ |
g_autoptr(GPtrArray) devices = NULL; |
323 |
|
✗ |
g_autoptr(GError) err = NULL; |
324 |
|
|
guint i; |
325 |
|
|
|
326 |
|
✗ |
devices = bolt_client_list_devices (self->client, self->cancellable, &err); |
327 |
|
|
|
328 |
|
✗ |
if (!devices) |
329 |
|
|
{ |
330 |
|
✗ |
g_warning ("Could not list devices: %s", err->message); |
331 |
|
✗ |
devices = g_ptr_array_new_with_free_func (g_object_unref); |
332 |
|
|
} |
333 |
|
|
|
334 |
|
✗ |
old = self->devices; |
335 |
|
✗ |
self->devices = g_hash_table_new (g_str_hash, g_str_equal); |
336 |
|
|
|
337 |
|
✗ |
for (i = 0; i < devices->len; i++) |
338 |
|
|
{ |
339 |
|
✗ |
BoltDevice *dev = g_ptr_array_index (devices, i); |
340 |
|
|
const char *path; |
341 |
|
|
gboolean found; |
342 |
|
|
|
343 |
|
✗ |
path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev)); |
344 |
|
✗ |
found = devices_table_transfer_entry (old, self->devices, path); |
345 |
|
|
|
346 |
|
✗ |
if (found) |
347 |
|
✗ |
continue; |
348 |
|
|
|
349 |
|
✗ |
cc_bolt_page_add_device (self, dev); |
350 |
|
|
} |
351 |
|
|
|
352 |
|
✗ |
devices_table_clear_entries (old, self); |
353 |
|
✗ |
gtk_stack_set_visible_child_name (self->container, "devices-listing"); |
354 |
|
✗ |
} |
355 |
|
|
|
356 |
|
|
static gboolean |
357 |
|
✗ |
list_box_sync_visible (GtkListBox *listbox) |
358 |
|
|
{ |
359 |
|
|
GtkWidget *child; |
360 |
|
|
gboolean show; |
361 |
|
|
|
362 |
|
✗ |
child = gtk_widget_get_first_child (GTK_WIDGET (listbox)); |
363 |
|
✗ |
show = child != NULL; |
364 |
|
|
|
365 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (listbox), show); |
366 |
|
|
|
367 |
|
✗ |
return show; |
368 |
|
|
} |
369 |
|
|
|
370 |
|
|
static GtkWidget * |
371 |
|
✗ |
cc_bolt_page_box_for_listbox (CcBoltPage *self, |
372 |
|
|
GtkListBox *lstbox) |
373 |
|
|
{ |
374 |
|
✗ |
if ((gpointer) lstbox == self->devices_list) |
375 |
|
✗ |
return GTK_WIDGET (self->devices_box); |
376 |
|
✗ |
else if ((gpointer) lstbox == self->pending_list) |
377 |
|
✗ |
return GTK_WIDGET (self->pending_box); |
378 |
|
|
|
379 |
|
✗ |
g_return_val_if_reached (NULL); |
380 |
|
|
} |
381 |
|
|
|
382 |
|
|
static CcBoltDeviceEntry * |
383 |
|
✗ |
cc_bolt_page_add_device (CcBoltPage *self, |
384 |
|
|
BoltDevice *dev) |
385 |
|
|
{ |
386 |
|
|
CcBoltDeviceEntry *entry; |
387 |
|
|
BoltDeviceType type; |
388 |
|
|
BoltStatus status; |
389 |
|
|
const char *path; |
390 |
|
|
|
391 |
|
✗ |
type = bolt_device_get_device_type (dev); |
392 |
|
|
|
393 |
|
✗ |
if (type != BOLT_DEVICE_PERIPHERAL) |
394 |
|
✗ |
return FALSE; |
395 |
|
|
|
396 |
|
✗ |
entry = cc_bolt_device_entry_new (dev, FALSE); |
397 |
|
✗ |
path = g_dbus_proxy_get_object_path (G_DBUS_PROXY (dev)); |
398 |
|
|
|
399 |
|
|
/* add to the list box */ |
400 |
|
✗ |
status = bolt_device_get_status (dev); |
401 |
|
|
|
402 |
|
✗ |
if (bolt_status_is_pending (status)) |
403 |
|
|
{ |
404 |
|
✗ |
gtk_list_box_append (self->pending_list, GTK_WIDGET (entry)); |
405 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->pending_list), TRUE); |
406 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->pending_box), TRUE); |
407 |
|
|
} |
408 |
|
|
else |
409 |
|
|
{ |
410 |
|
✗ |
gtk_list_box_append (self->devices_list, GTK_WIDGET (entry)); |
411 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->devices_list), TRUE); |
412 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->devices_box), TRUE); |
413 |
|
|
} |
414 |
|
|
|
415 |
|
✗ |
g_signal_connect_object (entry, |
416 |
|
|
"status-changed", |
417 |
|
|
G_CALLBACK (on_device_entry_status_changed_cb), |
418 |
|
|
self, |
419 |
|
|
0); |
420 |
|
|
|
421 |
|
✗ |
gtk_stack_set_visible_child_name (self->devices_stack, "have-devices"); |
422 |
|
✗ |
g_hash_table_insert (self->devices, (gpointer) path, entry); |
423 |
|
|
|
424 |
|
✗ |
return entry; |
425 |
|
|
} |
426 |
|
|
|
427 |
|
|
static void |
428 |
|
✗ |
cc_bolt_page_del_device_entry (CcBoltPage *self, |
429 |
|
|
CcBoltDeviceEntry *entry) |
430 |
|
|
{ |
431 |
|
|
BoltDevice *dev; |
432 |
|
|
GtkWidget *box; |
433 |
|
|
GtkWidget *p; |
434 |
|
|
gboolean show; |
435 |
|
|
|
436 |
|
✗ |
dev = cc_bolt_device_entry_get_device (entry); |
437 |
|
✗ |
if (cc_bolt_device_dialog_device_equal (self->device_dialog, dev)) |
438 |
|
|
{ |
439 |
|
✗ |
gtk_window_close (GTK_WINDOW (self->device_dialog)); |
440 |
|
✗ |
cc_bolt_device_dialog_set_device (self->device_dialog, NULL, NULL); |
441 |
|
|
} |
442 |
|
|
|
443 |
|
✗ |
p = gtk_widget_get_parent (GTK_WIDGET (entry)); |
444 |
|
✗ |
gtk_list_box_remove (GTK_LIST_BOX (p), GTK_WIDGET (entry)); |
445 |
|
|
|
446 |
|
✗ |
box = cc_bolt_page_box_for_listbox (self, GTK_LIST_BOX (p)); |
447 |
|
✗ |
show = list_box_sync_visible (GTK_LIST_BOX (p)); |
448 |
|
✗ |
gtk_widget_set_visible (box, show); |
449 |
|
|
|
450 |
|
✗ |
if (!gtk_widget_is_visible (GTK_WIDGET (self->pending_list)) && |
451 |
|
✗ |
!gtk_widget_is_visible (GTK_WIDGET (self->devices_list))) |
452 |
|
|
{ |
453 |
|
✗ |
gtk_stack_set_visible_child_name (self->devices_stack, "no-devices"); |
454 |
|
|
} |
455 |
|
✗ |
} |
456 |
|
|
|
457 |
|
|
static void |
458 |
|
✗ |
cc_bolt_page_authmode_sync (CcBoltPage *self) |
459 |
|
|
{ |
460 |
|
✗ |
BoltClient *client = self->client; |
461 |
|
|
BoltAuthMode mode; |
462 |
|
|
gboolean enabled; |
463 |
|
|
|
464 |
|
✗ |
mode = bolt_client_get_authmode (client); |
465 |
|
✗ |
enabled = (mode & BOLT_AUTH_ENABLED) != 0; |
466 |
|
|
|
467 |
|
✗ |
g_signal_handlers_block_by_func (self->authmode_switch, on_authmode_state_set_cb, self); |
468 |
|
|
|
469 |
|
✗ |
gtk_switch_set_active (self->authmode_switch, enabled); |
470 |
|
|
|
471 |
|
✗ |
g_signal_handlers_unblock_by_func (self->authmode_switch, on_authmode_state_set_cb, self); |
472 |
|
|
|
473 |
|
✗ |
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (self->direct_access_row), |
474 |
|
|
enabled ? |
475 |
|
✗ |
_("Allow direct access to devices such as docks and external GPUs.") : |
476 |
|
✗ |
_("Only USB and Display Port devices can attach.")); |
477 |
|
✗ |
} |
478 |
|
|
|
479 |
|
|
static void |
480 |
|
✗ |
cc_panel_list_box_migrate (CcBoltPage *self, |
481 |
|
|
GtkListBox *from, |
482 |
|
|
GtkListBox *to, |
483 |
|
|
CcBoltDeviceEntry *entry) |
484 |
|
|
{ |
485 |
|
|
GtkWidget *from_box; |
486 |
|
|
GtkWidget *to_box; |
487 |
|
|
gboolean show; |
488 |
|
|
GtkWidget *target; |
489 |
|
|
|
490 |
|
✗ |
target = GTK_WIDGET (entry); |
491 |
|
|
|
492 |
|
✗ |
gtk_list_box_remove (from, target); |
493 |
|
✗ |
gtk_list_box_append (to, target); |
494 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (to), TRUE); |
495 |
|
|
|
496 |
|
✗ |
from_box = cc_bolt_page_box_for_listbox (self, from); |
497 |
|
✗ |
to_box = cc_bolt_page_box_for_listbox (self, to); |
498 |
|
|
|
499 |
|
✗ |
show = list_box_sync_visible (from); |
500 |
|
✗ |
gtk_widget_set_visible (from_box, show); |
501 |
|
✗ |
gtk_widget_set_visible (to_box, TRUE); |
502 |
|
✗ |
} |
503 |
|
|
|
504 |
|
|
/* bolt client signals */ |
505 |
|
|
static void |
506 |
|
✗ |
cc_bolt_page_set_no_thunderbolt (CcBoltPage *self, |
507 |
|
|
const char *msg) |
508 |
|
|
{ |
509 |
|
✗ |
if (!msg) |
510 |
|
|
{ |
511 |
|
✗ |
msg = _("Thunderbolt could not be detected.\n" |
512 |
|
|
"Either the system lacks Thunderbolt support, " |
513 |
|
|
"it has been disabled in the BIOS or is set to " |
514 |
|
|
"an unsupported security level in the BIOS."); |
515 |
|
|
} |
516 |
|
|
|
517 |
|
✗ |
adw_status_page_set_description (self->notb_page, msg); |
518 |
|
✗ |
gtk_stack_set_visible_child_name (self->container, "no-thunderbolt"); |
519 |
|
✗ |
} |
520 |
|
|
|
521 |
|
|
static void |
522 |
|
✗ |
cc_bolt_page_name_owner_changed (CcBoltPage *self) |
523 |
|
|
{ |
524 |
|
✗ |
g_autofree char *name_owner = NULL; |
525 |
|
✗ |
BoltClient *client = self->client; |
526 |
|
|
BoltSecurity sl; |
527 |
|
✗ |
gboolean notb = TRUE; |
528 |
|
✗ |
const char *text = NULL; |
529 |
|
|
|
530 |
|
✗ |
name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (self->client)); |
531 |
|
|
|
532 |
|
✗ |
if (name_owner == NULL) |
533 |
|
|
{ |
534 |
|
✗ |
cc_bolt_page_set_no_thunderbolt (self, NULL); |
535 |
|
✗ |
devices_table_clear_entries (self->devices, self); |
536 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->headerbar_box), FALSE); |
537 |
|
✗ |
return; |
538 |
|
|
} |
539 |
|
|
|
540 |
|
✗ |
gtk_stack_set_visible_child_name (self->container, "loading"); |
541 |
|
|
|
542 |
|
✗ |
sl = bolt_client_get_security (client); |
543 |
|
|
|
544 |
|
✗ |
switch (sl) |
545 |
|
|
{ |
546 |
|
✗ |
case BOLT_SECURITY_NONE: |
547 |
|
|
case BOLT_SECURITY_SECURE: |
548 |
|
|
case BOLT_SECURITY_USER: |
549 |
|
|
/* we fetch the device list and show them here */ |
550 |
|
✗ |
notb = FALSE; |
551 |
|
✗ |
break; |
552 |
|
|
|
553 |
|
✗ |
case BOLT_SECURITY_DPONLY: |
554 |
|
|
case BOLT_SECURITY_USBONLY: |
555 |
|
✗ |
text = _("Thunderbolt support has been disabled in the BIOS."); |
556 |
|
✗ |
break; |
557 |
|
|
|
558 |
|
✗ |
case BOLT_SECURITY_UNKNOWN: |
559 |
|
✗ |
text = _("Thunderbolt security level could not be determined.");; |
560 |
|
✗ |
break; |
561 |
|
|
} |
562 |
|
|
|
563 |
|
✗ |
if (notb) |
564 |
|
|
{ |
565 |
|
|
/* security level is unknown or un-handled */ |
566 |
|
✗ |
cc_bolt_page_set_no_thunderbolt (self, text); |
567 |
|
✗ |
return; |
568 |
|
|
} |
569 |
|
|
|
570 |
|
✗ |
if (self->permission) |
571 |
|
|
{ |
572 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->headerbar_box), TRUE); |
573 |
|
|
} |
574 |
|
|
else |
575 |
|
|
{ |
576 |
|
✗ |
polkit_permission_new ("org.freedesktop.bolt.manage", |
577 |
|
|
NULL, |
578 |
|
|
self->cancellable, |
579 |
|
|
on_permission_ready, |
580 |
|
|
g_object_ref (self)); |
581 |
|
|
} |
582 |
|
|
|
583 |
|
✗ |
devices_table_synchronize (self); |
584 |
|
|
} |
585 |
|
|
|
586 |
|
|
/* bolt client signals */ |
587 |
|
|
static void |
588 |
|
✗ |
on_bolt_name_owner_changed_cb (GObject *object, |
589 |
|
|
GParamSpec *pspec, |
590 |
|
|
gpointer user_data) |
591 |
|
|
{ |
592 |
|
✗ |
cc_bolt_page_name_owner_changed (CC_BOLT_PAGE (user_data)); |
593 |
|
✗ |
} |
594 |
|
|
|
595 |
|
|
static void |
596 |
|
✗ |
on_bolt_device_added_cb (BoltClient *cli, |
597 |
|
|
const char *path, |
598 |
|
|
CcBoltPage *self) |
599 |
|
|
{ |
600 |
|
✗ |
g_autoptr(GError) err = NULL; |
601 |
|
|
GDBusConnection *bus; |
602 |
|
|
BoltDevice *dev; |
603 |
|
|
gboolean found; |
604 |
|
|
|
605 |
|
✗ |
found = g_hash_table_contains (self->devices, path); |
606 |
|
|
|
607 |
|
✗ |
if (found) |
608 |
|
✗ |
return; |
609 |
|
|
|
610 |
|
✗ |
bus = g_dbus_proxy_get_connection (G_DBUS_PROXY (self->client)); |
611 |
|
✗ |
dev = bolt_device_new_for_object_path (bus, path, self->cancellable, &err); |
612 |
|
|
|
613 |
|
✗ |
if (!dev) |
614 |
|
|
{ |
615 |
|
✗ |
g_warning ("Could not create proxy for %s", path); |
616 |
|
✗ |
return; |
617 |
|
|
} |
618 |
|
|
|
619 |
|
✗ |
cc_bolt_page_add_device (self, dev); |
620 |
|
|
} |
621 |
|
|
|
622 |
|
|
static void |
623 |
|
✗ |
on_bolt_device_removed_cb (BoltClient *cli, |
624 |
|
|
const char *path, |
625 |
|
|
CcBoltPage *self) |
626 |
|
|
{ |
627 |
|
|
CcBoltDeviceEntry *entry; |
628 |
|
|
|
629 |
|
✗ |
entry = g_hash_table_lookup (self->devices, path); |
630 |
|
|
|
631 |
|
✗ |
if (!entry) |
632 |
|
✗ |
return; |
633 |
|
|
|
634 |
|
✗ |
cc_bolt_page_del_device_entry (self, entry); |
635 |
|
✗ |
g_hash_table_remove (self->devices, path); |
636 |
|
|
} |
637 |
|
|
|
638 |
|
|
static void |
639 |
|
✗ |
on_bolt_notify_authmode_cb (GObject *gobject, |
640 |
|
|
GParamSpec *pspec, |
641 |
|
|
gpointer user_data) |
642 |
|
|
{ |
643 |
|
✗ |
cc_bolt_page_authmode_sync (CC_BOLT_PAGE (user_data)); |
644 |
|
✗ |
} |
645 |
|
|
|
646 |
|
|
/* panel signals */ |
647 |
|
|
|
648 |
|
|
static void |
649 |
|
✗ |
on_authmode_ready (GObject *source_object, |
650 |
|
|
GAsyncResult *res, |
651 |
|
|
gpointer user_data) |
652 |
|
|
{ |
653 |
|
✗ |
g_autoptr(GError) error = NULL; |
654 |
|
✗ |
BoltClient *client = BOLT_CLIENT (source_object); |
655 |
|
|
CcBoltPage *self; |
656 |
|
|
gboolean ok; |
657 |
|
|
|
658 |
|
✗ |
ok = bolt_client_set_authmode_finish (client, res, &error); |
659 |
|
✗ |
if (ok) |
660 |
|
|
{ |
661 |
|
|
BoltAuthMode mode; |
662 |
|
|
gboolean enabled; |
663 |
|
|
|
664 |
|
✗ |
self = CC_BOLT_PAGE (user_data); |
665 |
|
✗ |
mode = bolt_client_get_authmode (client); |
666 |
|
✗ |
enabled = (mode & BOLT_AUTH_ENABLED) != 0; |
667 |
|
✗ |
gtk_switch_set_state (self->authmode_switch, enabled); |
668 |
|
|
} |
669 |
|
|
else |
670 |
|
|
{ |
671 |
|
✗ |
g_autofree char *text = NULL; |
672 |
|
|
|
673 |
|
✗ |
g_warning ("Could not set authmode: %s", error->message); |
674 |
|
|
|
675 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
676 |
|
✗ |
return; |
677 |
|
|
|
678 |
|
✗ |
self = CC_BOLT_PAGE (user_data); |
679 |
|
✗ |
text = g_strdup_printf (_("Error switching direct mode: %s"), error->message); |
680 |
|
✗ |
gtk_label_set_markup (self->notification_label, text); |
681 |
|
✗ |
gtk_revealer_set_reveal_child (self->notification_revealer, TRUE); |
682 |
|
|
|
683 |
|
|
/* make sure we are reflecting the correct state */ |
684 |
|
✗ |
cc_bolt_page_authmode_sync (self); |
685 |
|
|
} |
686 |
|
|
|
687 |
|
✗ |
gtk_spinner_stop (self->authmode_spinner); |
688 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->authmode_switch), TRUE); |
689 |
|
|
} |
690 |
|
|
|
691 |
|
|
static gboolean |
692 |
|
✗ |
on_authmode_state_set_cb (CcBoltPage *self, |
693 |
|
|
gboolean enable, |
694 |
|
|
GtkSwitch *toggle) |
695 |
|
|
{ |
696 |
|
✗ |
BoltClient *client = self->client; |
697 |
|
|
BoltAuthMode mode; |
698 |
|
|
|
699 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->authmode_switch), FALSE); |
700 |
|
✗ |
gtk_spinner_start (self->authmode_spinner); |
701 |
|
|
|
702 |
|
✗ |
mode = bolt_client_get_authmode (client); |
703 |
|
|
|
704 |
|
✗ |
if (enable) |
705 |
|
✗ |
mode = mode | BOLT_AUTH_ENABLED; |
706 |
|
|
else |
707 |
|
✗ |
mode = mode & ~BOLT_AUTH_ENABLED; |
708 |
|
|
|
709 |
|
✗ |
bolt_client_set_authmode_async (client, mode, NULL, on_authmode_ready, self); |
710 |
|
|
|
711 |
|
✗ |
return TRUE; |
712 |
|
|
} |
713 |
|
|
|
714 |
|
|
static void |
715 |
|
✗ |
on_device_entry_row_activated_cb (CcBoltPage *self, |
716 |
|
|
GtkListBoxRow *row) |
717 |
|
|
{ |
718 |
|
✗ |
g_autoptr(GPtrArray) parents = NULL; |
719 |
|
|
CcBoltDeviceEntry *entry; |
720 |
|
|
BoltDevice *device; |
721 |
|
|
BoltDevice *iter; |
722 |
|
|
const char *parent; |
723 |
|
|
|
724 |
|
✗ |
if (!CC_IS_BOLT_DEVICE_ENTRY (row)) |
725 |
|
✗ |
return; |
726 |
|
|
|
727 |
|
✗ |
entry = CC_BOLT_DEVICE_ENTRY (row); |
728 |
|
✗ |
device = cc_bolt_device_entry_get_device (entry); |
729 |
|
|
|
730 |
|
|
/* walk up the chain and collect all parents */ |
731 |
|
✗ |
parents = g_ptr_array_new_with_free_func (g_object_unref); |
732 |
|
✗ |
iter = device; |
733 |
|
|
|
734 |
|
✗ |
parent = bolt_device_get_parent (iter); |
735 |
|
✗ |
while (parent != NULL) |
736 |
|
|
{ |
737 |
|
✗ |
g_autofree char *path = NULL; |
738 |
|
|
CcBoltDeviceEntry *child; |
739 |
|
|
BoltDevice *dev; |
740 |
|
|
|
741 |
|
✗ |
path = bolt_gen_object_path (BOLT_DBUS_PATH_DEVICES, parent); |
742 |
|
|
|
743 |
|
|
/* NB: the host device is not a peripheral and thus not |
744 |
|
|
* in the hash table; therefore when get a NULL back, we |
745 |
|
|
* should have reached the end of the chain */ |
746 |
|
✗ |
child = g_hash_table_lookup (self->devices, path); |
747 |
|
✗ |
if (!child) |
748 |
|
✗ |
break; |
749 |
|
|
|
750 |
|
✗ |
dev = cc_bolt_device_entry_get_device (child); |
751 |
|
✗ |
g_ptr_array_add (parents, g_object_ref (dev)); |
752 |
|
✗ |
iter = dev; |
753 |
|
|
|
754 |
|
✗ |
parent = bolt_device_get_parent (iter); |
755 |
|
|
} |
756 |
|
|
|
757 |
|
✗ |
cc_bolt_device_dialog_set_device (self->device_dialog, device, parents); |
758 |
|
|
|
759 |
|
✗ |
gtk_window_set_default_size (GTK_WINDOW (self->device_dialog), 1, 1); |
760 |
|
✗ |
gtk_window_present (GTK_WINDOW (self->device_dialog)); |
761 |
|
|
} |
762 |
|
|
|
763 |
|
|
static void |
764 |
|
✗ |
on_device_entry_status_changed_cb (CcBoltDeviceEntry *entry, |
765 |
|
|
BoltStatus new_status, |
766 |
|
|
CcBoltPage *self) |
767 |
|
|
{ |
768 |
|
✗ |
GtkListBox *from = NULL; |
769 |
|
✗ |
GtkListBox *to = NULL; |
770 |
|
|
GtkWidget *p; |
771 |
|
|
gboolean is_pending; |
772 |
|
|
gboolean parent_pending; |
773 |
|
|
|
774 |
|
|
/* if we are doing some active work, then lets not change |
775 |
|
|
* the list the entry is in; otherwise we might just hop |
776 |
|
|
* from one box to the other and back again. |
777 |
|
|
*/ |
778 |
|
✗ |
if (new_status == BOLT_STATUS_CONNECTING || new_status == BOLT_STATUS_AUTHORIZING) |
779 |
|
✗ |
return; |
780 |
|
|
|
781 |
|
✗ |
is_pending = bolt_status_is_pending (new_status); |
782 |
|
|
|
783 |
|
✗ |
p = gtk_widget_get_parent (GTK_WIDGET (entry)); |
784 |
|
✗ |
parent_pending = (gpointer) p == self->pending_list; |
785 |
|
|
|
786 |
|
|
/* */ |
787 |
|
✗ |
if (is_pending && !parent_pending) |
788 |
|
|
{ |
789 |
|
✗ |
from = self->devices_list; |
790 |
|
✗ |
to = self->pending_list; |
791 |
|
|
} |
792 |
|
✗ |
else if (!is_pending && parent_pending) |
793 |
|
|
{ |
794 |
|
✗ |
from = self->pending_list; |
795 |
|
✗ |
to = self->devices_list; |
796 |
|
|
} |
797 |
|
|
|
798 |
|
✗ |
if (from && to) |
799 |
|
✗ |
cc_panel_list_box_migrate (self, from, to, entry); |
800 |
|
|
} |
801 |
|
|
|
802 |
|
|
|
803 |
|
|
static void |
804 |
|
✗ |
on_notification_button_clicked_cb (CcBoltPage *self) |
805 |
|
|
{ |
806 |
|
✗ |
gtk_revealer_set_reveal_child (self->notification_revealer, FALSE); |
807 |
|
✗ |
} |
808 |
|
|
|
809 |
|
|
/* polkit */ |
810 |
|
|
|
811 |
|
|
static void |
812 |
|
✗ |
on_permission_ready (GObject *source_object, |
813 |
|
|
GAsyncResult *res, |
814 |
|
|
gpointer user_data) |
815 |
|
|
{ |
816 |
|
✗ |
g_autoptr(CcBoltPage) self = user_data; |
817 |
|
✗ |
g_autoptr(GError) err = NULL; |
818 |
|
|
GPermission *permission; |
819 |
|
|
gboolean is_allowed; |
820 |
|
|
const char *name; |
821 |
|
|
|
822 |
|
✗ |
permission = polkit_permission_new_finish (res, &err); |
823 |
|
✗ |
self->permission = permission; |
824 |
|
|
|
825 |
|
✗ |
if (!self->permission) |
826 |
|
|
{ |
827 |
|
✗ |
g_warning ("Could not get polkit permissions: %s", err->message); |
828 |
|
✗ |
return; |
829 |
|
|
} |
830 |
|
|
|
831 |
|
✗ |
g_signal_connect_object (permission, |
832 |
|
|
"notify", |
833 |
|
|
G_CALLBACK (on_permission_notify_cb), |
834 |
|
|
self, |
835 |
|
|
G_CONNECT_AFTER); |
836 |
|
|
|
837 |
|
✗ |
is_allowed = g_permission_get_allowed (permission); |
838 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->authmode_switch), is_allowed); |
839 |
|
✗ |
gtk_lock_button_set_permission (self->lock_button, permission); |
840 |
|
|
|
841 |
|
✗ |
name = gtk_stack_get_visible_child_name (self->container); |
842 |
|
|
|
843 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->headerbar_box), |
844 |
|
✗ |
bolt_streq (name, "devices-listing")); |
845 |
|
|
} |
846 |
|
|
|
847 |
|
|
static void |
848 |
|
✗ |
on_permission_notify_cb (GPermission *permission, |
849 |
|
|
GParamSpec *pspec, |
850 |
|
|
CcBoltPage *self) |
851 |
|
|
{ |
852 |
|
✗ |
gboolean is_allowed = g_permission_get_allowed (permission); |
853 |
|
|
|
854 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->authmode_switch), is_allowed); |
855 |
|
✗ |
} |
856 |
|
|
|
857 |
|
|
static gint |
858 |
|
✗ |
device_entries_sort_by_recency_cb (GtkListBoxRow *a_row, |
859 |
|
|
GtkListBoxRow *b_row, |
860 |
|
|
gpointer user_data) |
861 |
|
|
{ |
862 |
|
✗ |
CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row); |
863 |
|
✗ |
CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row); |
864 |
|
✗ |
BoltDevice *a = cc_bolt_device_entry_get_device (a_entry); |
865 |
|
✗ |
BoltDevice *b = cc_bolt_device_entry_get_device (b_entry); |
866 |
|
|
BoltStatus status; |
867 |
|
|
gint64 a_ts, b_ts; |
868 |
|
|
gint64 score; |
869 |
|
|
|
870 |
|
✗ |
a_ts = (gint64) bolt_device_get_timestamp (a); |
871 |
|
✗ |
b_ts = (gint64) bolt_device_get_timestamp (b); |
872 |
|
|
|
873 |
|
✗ |
score = b_ts - a_ts; |
874 |
|
|
|
875 |
|
✗ |
if (score != 0) |
876 |
|
✗ |
return score; |
877 |
|
|
|
878 |
|
✗ |
status = bolt_device_get_status (a); |
879 |
|
|
|
880 |
|
✗ |
if (bolt_status_is_connected (status)) |
881 |
|
|
{ |
882 |
|
|
const char *a_path; |
883 |
|
|
const char *b_path; |
884 |
|
|
|
885 |
|
✗ |
a_path = bolt_device_get_syspath (a); |
886 |
|
✗ |
b_path = bolt_device_get_syspath (b); |
887 |
|
|
|
888 |
|
✗ |
return g_strcmp0 (a_path, b_path); |
889 |
|
|
} |
890 |
|
|
else |
891 |
|
|
{ |
892 |
|
|
const char *a_name; |
893 |
|
|
const char *b_name; |
894 |
|
|
|
895 |
|
✗ |
a_name = bolt_device_get_name (a); |
896 |
|
✗ |
b_name = bolt_device_get_name (b); |
897 |
|
|
|
898 |
|
✗ |
return g_strcmp0 (a_name, b_name); |
899 |
|
|
} |
900 |
|
|
|
901 |
|
|
return 0; |
902 |
|
|
} |
903 |
|
|
|
904 |
|
|
static gint |
905 |
|
✗ |
device_entries_sort_by_syspath_cb (GtkListBoxRow *a_row, |
906 |
|
|
GtkListBoxRow *b_row, |
907 |
|
|
gpointer user_data) |
908 |
|
|
{ |
909 |
|
✗ |
CcBoltDeviceEntry *a_entry = CC_BOLT_DEVICE_ENTRY (a_row); |
910 |
|
✗ |
CcBoltDeviceEntry *b_entry = CC_BOLT_DEVICE_ENTRY (b_row); |
911 |
|
✗ |
BoltDevice *a = cc_bolt_device_entry_get_device (a_entry); |
912 |
|
✗ |
BoltDevice *b = cc_bolt_device_entry_get_device (b_entry); |
913 |
|
|
|
914 |
|
|
const char *a_path; |
915 |
|
|
const char *b_path; |
916 |
|
|
|
917 |
|
✗ |
a_path = bolt_device_get_syspath (a); |
918 |
|
✗ |
b_path = bolt_device_get_syspath (b); |
919 |
|
|
|
920 |
|
✗ |
return g_strcmp0 (a_path, b_path); |
921 |
|
|
} |
922 |
|
|
|
923 |
|
|
/* GObject overrides */ |
924 |
|
|
|
925 |
|
|
static void |
926 |
|
✗ |
cc_bolt_page_finalize (GObject *object) |
927 |
|
|
{ |
928 |
|
✗ |
CcBoltPage *self = CC_BOLT_PAGE (object); |
929 |
|
|
|
930 |
|
✗ |
g_clear_object (&self->client); |
931 |
|
✗ |
g_clear_pointer (&self->devices, g_hash_table_unref); |
932 |
|
✗ |
g_clear_object (&self->permission); |
933 |
|
|
|
934 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
935 |
|
✗ |
g_clear_object (&self->cancellable); |
936 |
|
|
|
937 |
|
✗ |
G_OBJECT_CLASS (cc_bolt_page_parent_class)->finalize (object); |
938 |
|
✗ |
} |
939 |
|
|
|
940 |
|
|
static void |
941 |
|
✗ |
cc_bolt_page_dispose (GObject *object) |
942 |
|
|
{ |
943 |
|
✗ |
CcBoltPage *self = CC_BOLT_PAGE (object); |
944 |
|
|
|
945 |
|
|
/* Must be destroyed in dispose, not finalize. */ |
946 |
|
✗ |
cc_bolt_device_dialog_set_device (self->device_dialog, NULL, NULL); |
947 |
|
✗ |
g_clear_pointer ((GtkWindow **) &self->device_dialog, gtk_window_destroy); |
948 |
|
|
|
949 |
|
✗ |
G_OBJECT_CLASS (cc_bolt_page_parent_class)->dispose (object); |
950 |
|
✗ |
} |
951 |
|
|
|
952 |
|
|
static void |
953 |
|
✗ |
cc_bolt_page_constructed (GObject *object) |
954 |
|
|
{ |
955 |
|
✗ |
CcBoltPage *self = CC_BOLT_PAGE (object); |
956 |
|
|
GtkWindow *parent; |
957 |
|
|
|
958 |
|
✗ |
G_OBJECT_CLASS (cc_bolt_page_parent_class)->constructed (object); |
959 |
|
|
|
960 |
|
✗ |
parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))); |
961 |
|
✗ |
gtk_window_set_transient_for (GTK_WINDOW (self->device_dialog), parent); |
962 |
|
✗ |
} |
963 |
|
|
|
964 |
|
|
static void |
965 |
|
✗ |
cc_bolt_page_class_init (CcBoltPageClass *klass) |
966 |
|
|
{ |
967 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
968 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
969 |
|
|
|
970 |
|
✗ |
object_class->constructed = cc_bolt_page_constructed; |
971 |
|
✗ |
object_class->dispose = cc_bolt_page_dispose; |
972 |
|
✗ |
object_class->finalize = cc_bolt_page_finalize; |
973 |
|
|
|
974 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/privacy/bolt/cc-bolt-page.ui"); |
975 |
|
|
|
976 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, authmode_spinner); |
977 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, authmode_switch); |
978 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, container); |
979 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, devices_list); |
980 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, devices_box); |
981 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, devices_stack); |
982 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, direct_access_row); |
983 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, headerbar_box); |
984 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, lock_button); |
985 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, notb_page); |
986 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, notification_label); |
987 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, notification_revealer); |
988 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, pending_box); |
989 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcBoltPage, pending_list); |
990 |
|
|
|
991 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_notification_button_clicked_cb); |
992 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_authmode_state_set_cb); |
993 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_device_entry_row_activated_cb); |
994 |
|
✗ |
} |
995 |
|
|
|
996 |
|
|
static void |
997 |
|
✗ |
cc_bolt_page_init (CcBoltPage *self) |
998 |
|
|
{ |
999 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
1000 |
|
|
|
1001 |
|
✗ |
self->cancellable = g_cancellable_new (); |
1002 |
|
✗ |
bolt_client_new_async (self->cancellable, on_visibility_client_ready, self); |
1003 |
|
|
|
1004 |
|
✗ |
gtk_stack_set_visible_child_name (self->container, "loading"); |
1005 |
|
|
|
1006 |
|
✗ |
gtk_list_box_set_sort_func (self->devices_list, |
1007 |
|
|
device_entries_sort_by_recency_cb, |
1008 |
|
|
self, |
1009 |
|
|
NULL); |
1010 |
|
|
|
1011 |
|
✗ |
gtk_list_box_set_sort_func (self->pending_list, |
1012 |
|
|
device_entries_sort_by_syspath_cb, |
1013 |
|
|
self, |
1014 |
|
|
NULL); |
1015 |
|
|
|
1016 |
|
✗ |
self->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); |
1017 |
|
|
|
1018 |
|
✗ |
self->device_dialog = cc_bolt_device_dialog_new (); |
1019 |
|
|
|
1020 |
|
✗ |
bolt_client_new_async (self->cancellable, bolt_client_ready, g_object_ref (self)); |
1021 |
|
✗ |
} |
1022 |
|
|
|
1023 |
|
|
CcBoltPage * |
1024 |
|
✗ |
cc_bolt_page_new (void) |
1025 |
|
|
{ |
1026 |
|
✗ |
return g_object_new (CC_TYPE_BOLT_PAGE, NULL); |
1027 |
|
|
} |
1028 |
|
|
|