Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2020 Canonical Ltd. |
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, see <http://www.gnu.org/licenses/>. |
17 |
|
|
* |
18 |
|
|
* SPDX-License-Identifier: GPL-3.0-or-later |
19 |
|
|
* |
20 |
|
|
* Authors: Marco Trevisan <marco.trevisan@canonical.com> |
21 |
|
|
*/ |
22 |
|
|
|
23 |
|
|
#include <glib/gi18n.h> |
24 |
|
|
#include <cairo/cairo.h> |
25 |
|
|
|
26 |
|
|
#include "cc-fingerprint-dialog.h" |
27 |
|
|
|
28 |
|
|
#include "cc-fingerprint-manager.h" |
29 |
|
|
#include "cc-fprintd-generated.h" |
30 |
|
|
#include "cc-list-row.h" |
31 |
|
|
|
32 |
|
|
#include "config.h" |
33 |
|
|
|
34 |
|
|
#define CC_FPRINTD_NAME "net.reactivated.Fprint" |
35 |
|
|
|
36 |
|
|
/* Translate fprintd strings */ |
37 |
|
|
#define TR(s) dgettext ("fprintd", s) |
38 |
|
|
#include "fingerprint-strings.h" |
39 |
|
|
|
40 |
|
|
typedef enum { |
41 |
|
|
DIALOG_STATE_NONE = 0, |
42 |
|
|
DIALOG_STATE_DEVICES_LISTING = (1 << 0), |
43 |
|
|
DIALOG_STATE_DEVICE_CLAIMING = (1 << 1), |
44 |
|
|
DIALOG_STATE_DEVICE_CLAIMED = (1 << 2), |
45 |
|
|
DIALOG_STATE_DEVICE_PRINTS_LISTING = (1 << 3), |
46 |
|
|
DIALOG_STATE_DEVICE_RELEASING = (1 << 4), |
47 |
|
|
DIALOG_STATE_DEVICE_ENROLL_STARTING = (1 << 5), |
48 |
|
|
DIALOG_STATE_DEVICE_ENROLLING = (1 << 6), |
49 |
|
|
DIALOG_STATE_DEVICE_ENROLL_STOPPING = (1 << 7), |
50 |
|
|
DIALOG_STATE_DEVICE_DELETING = (1 << 8), |
51 |
|
|
|
52 |
|
|
DIALOG_STATE_IDLE = DIALOG_STATE_DEVICE_CLAIMED | DIALOG_STATE_DEVICE_ENROLLING, |
53 |
|
|
} DialogState; |
54 |
|
|
|
55 |
|
|
struct _CcFingerprintDialog |
56 |
|
|
{ |
57 |
|
|
GtkWindow parent_instance; |
58 |
|
|
|
59 |
|
|
GtkButton *back_button; |
60 |
|
|
GtkButton *cancel_button; |
61 |
|
|
GtkButton *delete_prints_button; |
62 |
|
|
GtkButton *done_button; |
63 |
|
|
GtkBox *add_print_popover_box; |
64 |
|
|
GtkEntry *enroll_print_entry; |
65 |
|
|
GtkFlowBox *prints_gallery; |
66 |
|
|
GtkHeaderBar *titlebar; |
67 |
|
|
GtkImage *enroll_result_image; |
68 |
|
|
GtkLabel *enroll_message; |
69 |
|
|
GtkLabel *enroll_result_message; |
70 |
|
|
GtkLabel *infobar_error; |
71 |
|
|
GtkLabel *title; |
72 |
|
|
GtkListBox *devices_list; |
73 |
|
|
GtkPopover *add_print_popover; |
74 |
|
|
GtkSpinner *spinner; |
75 |
|
|
GtkStack *stack; |
76 |
|
|
GtkWidget *add_print_icon; |
77 |
|
|
GtkWidget *delete_confirmation_infobar; |
78 |
|
|
GtkWidget *device_selector; |
79 |
|
|
GtkWidget *enroll_print_bin; |
80 |
|
|
GtkWidget *enroll_result_icon; |
81 |
|
|
GtkWidget *enrollment_view; |
82 |
|
|
GtkWidget *error_infobar; |
83 |
|
|
GtkWidget *no_devices_found; |
84 |
|
|
GtkWidget *prints_manager; |
85 |
|
|
|
86 |
|
|
CcFingerprintManager *manager; |
87 |
|
|
DialogState dialog_state; |
88 |
|
|
CcFprintdDevice *device; |
89 |
|
|
gulong device_signal_id; |
90 |
|
|
gulong device_name_owner_id; |
91 |
|
|
GCancellable *cancellable; |
92 |
|
|
GStrv enrolled_fingers; |
93 |
|
|
guint enroll_stages_passed; |
94 |
|
|
guint enroll_stage_passed_id; |
95 |
|
|
gdouble enroll_progress; |
96 |
|
|
}; |
97 |
|
|
|
98 |
|
|
/* TODO - fprintd and API changes required: |
99 |
|
|
- Identify the finger when the enroll dialog is visible |
100 |
|
|
+ Only if device supports identification |
101 |
|
|
ยท And only in such case support enrolling more than one finger |
102 |
|
|
- Delete a single fingerprint | and remove the "Delete all" button |
103 |
|
|
- Highlight the finger when the sensor is touched during enrollment |
104 |
|
|
- Add customized labels to fingerprints |
105 |
|
|
- Devices hotplug (object manager) |
106 |
|
|
*/ |
107 |
|
|
|
108 |
|
✗ |
G_DEFINE_TYPE (CcFingerprintDialog, cc_fingerprint_dialog, GTK_TYPE_WINDOW) |
109 |
|
|
|
110 |
|
|
enum { |
111 |
|
|
PROP_0, |
112 |
|
|
PROP_MANAGER, |
113 |
|
|
N_PROPS |
114 |
|
|
}; |
115 |
|
|
|
116 |
|
|
#define N_VALID_FINGERS G_N_ELEMENTS (FINGER_IDS) - 1 |
117 |
|
|
/* The order of the fingers here will affect the UI order */ |
118 |
|
|
const char * FINGER_IDS[] = { |
119 |
|
|
"right-index-finger", |
120 |
|
|
"left-index-finger", |
121 |
|
|
"right-thumb", |
122 |
|
|
"right-middle-finger", |
123 |
|
|
"right-ring-finger", |
124 |
|
|
"right-little-finger", |
125 |
|
|
"left-thumb", |
126 |
|
|
"left-middle-finger", |
127 |
|
|
"left-ring-finger", |
128 |
|
|
"left-little-finger", |
129 |
|
|
"any", |
130 |
|
|
}; |
131 |
|
|
|
132 |
|
|
typedef enum { |
133 |
|
|
ENROLL_STATE_NORMAL, |
134 |
|
|
ENROLL_STATE_RETRY, |
135 |
|
|
ENROLL_STATE_SUCCESS, |
136 |
|
|
ENROLL_STATE_WARNING, |
137 |
|
|
ENROLL_STATE_ERROR, |
138 |
|
|
ENROLL_STATE_COMPLETED, |
139 |
|
|
N_ENROLL_STATES, |
140 |
|
|
} EnrollState; |
141 |
|
|
|
142 |
|
|
const char * ENROLL_STATE_CLASSES[N_ENROLL_STATES] = { |
143 |
|
|
"", |
144 |
|
|
"retry", |
145 |
|
|
"success", |
146 |
|
|
"warning", |
147 |
|
|
"error", |
148 |
|
|
"completed", |
149 |
|
|
}; |
150 |
|
|
|
151 |
|
|
static GParamSpec *properties[N_PROPS]; |
152 |
|
|
|
153 |
|
|
CcFingerprintDialog * |
154 |
|
✗ |
cc_fingerprint_dialog_new (CcFingerprintManager *manager) |
155 |
|
|
{ |
156 |
|
✗ |
return g_object_new (CC_TYPE_FINGERPRINT_DIALOG, |
157 |
|
|
"fingerprint-manager", manager, |
158 |
|
|
NULL); |
159 |
|
|
} |
160 |
|
|
|
161 |
|
|
static gboolean |
162 |
|
✗ |
update_dialog_state (CcFingerprintDialog *self, |
163 |
|
|
DialogState state) |
164 |
|
|
{ |
165 |
|
✗ |
if (self->dialog_state == state) |
166 |
|
✗ |
return FALSE; |
167 |
|
|
|
168 |
|
✗ |
self->dialog_state = state; |
169 |
|
|
|
170 |
|
✗ |
if (self->dialog_state == DIALOG_STATE_NONE || |
171 |
|
✗ |
self->dialog_state == (self->dialog_state & DIALOG_STATE_IDLE)) |
172 |
|
|
{ |
173 |
|
✗ |
gtk_spinner_stop (self->spinner); |
174 |
|
|
} |
175 |
|
|
else |
176 |
|
|
{ |
177 |
|
✗ |
gtk_spinner_start (self->spinner); |
178 |
|
|
} |
179 |
|
|
|
180 |
|
✗ |
return TRUE; |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
static gboolean |
184 |
|
✗ |
add_dialog_state (CcFingerprintDialog *self, |
185 |
|
|
DialogState state) |
186 |
|
|
{ |
187 |
|
✗ |
return update_dialog_state (self, (self->dialog_state | state)); |
188 |
|
|
} |
189 |
|
|
|
190 |
|
|
static gboolean |
191 |
|
✗ |
remove_dialog_state (CcFingerprintDialog *self, |
192 |
|
|
DialogState state) |
193 |
|
|
{ |
194 |
|
✗ |
return update_dialog_state (self, (self->dialog_state & ~state)); |
195 |
|
|
} |
196 |
|
|
|
197 |
|
|
typedef struct |
198 |
|
|
{ |
199 |
|
|
CcFingerprintDialog *dialog; |
200 |
|
|
DialogState state; |
201 |
|
|
} DialogStateRemover; |
202 |
|
|
|
203 |
|
|
static DialogStateRemover * |
204 |
|
✗ |
auto_state_remover (CcFingerprintDialog *self, |
205 |
|
|
DialogState state) |
206 |
|
|
{ |
207 |
|
|
DialogStateRemover *state_remover; |
208 |
|
|
|
209 |
|
✗ |
state_remover = g_new0 (DialogStateRemover, 1); |
210 |
|
✗ |
state_remover->dialog = g_object_ref (self); |
211 |
|
✗ |
state_remover->state = state; |
212 |
|
|
|
213 |
|
✗ |
return state_remover; |
214 |
|
|
} |
215 |
|
|
|
216 |
|
|
static void |
217 |
|
✗ |
auto_state_remover_cleanup (DialogStateRemover *state_remover) |
218 |
|
|
{ |
219 |
|
✗ |
remove_dialog_state (state_remover->dialog, state_remover->state); |
220 |
|
✗ |
g_clear_object (&state_remover->dialog); |
221 |
|
✗ |
g_free (state_remover); |
222 |
|
✗ |
} |
223 |
|
|
|
224 |
|
✗ |
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DialogStateRemover, auto_state_remover_cleanup); |
225 |
|
|
|
226 |
|
|
static const char * |
227 |
|
✗ |
dbus_error_to_human (CcFingerprintDialog *self, |
228 |
|
|
GError *error) |
229 |
|
|
{ |
230 |
|
✗ |
g_autofree char *dbus_error = g_dbus_error_get_remote_error (error); |
231 |
|
|
|
232 |
|
✗ |
if (dbus_error == NULL) |
233 |
|
|
{ /* Fallback to generic */ } |
234 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.ClaimDevice")) |
235 |
|
✗ |
return _("the device needs to be claimed to perform this action"); |
236 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.AlreadyInUse")) |
237 |
|
✗ |
return _("the device is already claimed by another process"); |
238 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.PermissionDenied")) |
239 |
|
✗ |
return _("you do not have permission to perform the action"); |
240 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints")) |
241 |
|
✗ |
return _("no prints have been enrolled"); |
242 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoActionInProgress")) |
243 |
|
|
{ /* Fallback to generic */ } |
244 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.InvalidFingername")) |
245 |
|
|
{ /* Fallback to generic */ } |
246 |
|
✗ |
else if (g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.Internal")) |
247 |
|
|
{ /* Fallback to generic */ } |
248 |
|
|
|
249 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING) |
250 |
|
✗ |
return _("Failed to communicate with the device during enrollment"); |
251 |
|
|
|
252 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED || |
253 |
|
✗ |
self->dialog_state & DIALOG_STATE_DEVICE_CLAIMING) |
254 |
|
✗ |
return _("Failed to communicate with the fingerprint reader"); |
255 |
|
|
|
256 |
|
✗ |
return _("Failed to communicate with the fingerprint daemon"); |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
static void |
260 |
|
✗ |
disconnect_device_signals (CcFingerprintDialog *self) |
261 |
|
|
{ |
262 |
|
✗ |
if (!self->device) |
263 |
|
✗ |
return; |
264 |
|
|
|
265 |
|
✗ |
if (self->device_signal_id) |
266 |
|
|
{ |
267 |
|
✗ |
g_signal_handler_disconnect (self->device, self->device_signal_id); |
268 |
|
✗ |
self->device_signal_id = 0; |
269 |
|
|
} |
270 |
|
|
|
271 |
|
✗ |
if (self->device_name_owner_id) |
272 |
|
|
{ |
273 |
|
✗ |
g_signal_handler_disconnect (self->device, self->device_name_owner_id); |
274 |
|
✗ |
self->device_name_owner_id = 0; |
275 |
|
|
} |
276 |
|
|
} |
277 |
|
|
|
278 |
|
|
static void |
279 |
|
✗ |
cc_fingerprint_dialog_get_property (GObject *object, |
280 |
|
|
guint prop_id, |
281 |
|
|
GValue *value, |
282 |
|
|
GParamSpec *pspec) |
283 |
|
|
{ |
284 |
|
✗ |
CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object); |
285 |
|
|
|
286 |
|
✗ |
switch (prop_id) |
287 |
|
|
{ |
288 |
|
✗ |
case PROP_MANAGER: |
289 |
|
✗ |
g_value_set_object (value, self->manager); |
290 |
|
✗ |
break; |
291 |
|
|
|
292 |
|
✗ |
default: |
293 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
294 |
|
|
} |
295 |
|
✗ |
} |
296 |
|
|
|
297 |
|
|
static void |
298 |
|
✗ |
cc_fingerprint_dialog_set_property (GObject *object, |
299 |
|
|
guint prop_id, |
300 |
|
|
const GValue *value, |
301 |
|
|
GParamSpec *pspec) |
302 |
|
|
{ |
303 |
|
✗ |
CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object); |
304 |
|
|
|
305 |
|
✗ |
switch (prop_id) |
306 |
|
|
{ |
307 |
|
✗ |
case PROP_MANAGER: |
308 |
|
✗ |
g_set_object (&self->manager, g_value_get_object (value)); |
309 |
|
✗ |
break; |
310 |
|
|
|
311 |
|
✗ |
default: |
312 |
|
✗ |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
313 |
|
|
} |
314 |
|
✗ |
} |
315 |
|
|
|
316 |
|
|
static void |
317 |
|
✗ |
notify_error (CcFingerprintDialog *self, |
318 |
|
|
const char *error_message) |
319 |
|
|
{ |
320 |
|
✗ |
if (error_message) |
321 |
|
✗ |
gtk_label_set_label (self->infobar_error, error_message); |
322 |
|
|
|
323 |
|
✗ |
gtk_widget_set_visible (self->error_infobar, error_message != NULL); |
324 |
|
✗ |
} |
325 |
|
|
|
326 |
|
|
static GtkWidget * |
327 |
|
✗ |
fingerprint_icon_new (const char *icon_name, |
328 |
|
|
const char *label_text, |
329 |
|
|
GType icon_widget_type, |
330 |
|
|
gpointer progress_data, |
331 |
|
|
GtkWidget **out_icon, |
332 |
|
|
GtkWidget **out_label) |
333 |
|
|
{ |
334 |
|
|
GtkWidget *box; |
335 |
|
|
GtkWidget *label; |
336 |
|
|
GtkWidget *image; |
337 |
|
|
GtkWidget *icon_widget; |
338 |
|
|
|
339 |
|
✗ |
g_return_val_if_fail (g_type_is_a (icon_widget_type, GTK_TYPE_WIDGET), NULL); |
340 |
|
|
|
341 |
|
✗ |
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); |
342 |
|
✗ |
gtk_widget_set_name (box, "fingerprint-box"); |
343 |
|
✗ |
gtk_widget_set_hexpand (box, TRUE); |
344 |
|
|
|
345 |
|
✗ |
image = gtk_image_new_from_icon_name (icon_name); |
346 |
|
|
|
347 |
|
✗ |
if (icon_widget_type == GTK_TYPE_IMAGE) |
348 |
|
✗ |
icon_widget = image; |
349 |
|
|
else |
350 |
|
✗ |
icon_widget = g_object_new (icon_widget_type, NULL); |
351 |
|
|
|
352 |
|
✗ |
if (g_type_is_a (icon_widget_type, GTK_TYPE_MENU_BUTTON)) |
353 |
|
|
{ |
354 |
|
✗ |
gtk_menu_button_set_child (GTK_MENU_BUTTON (icon_widget), image); |
355 |
|
✗ |
gtk_widget_set_can_focus (icon_widget, FALSE); |
356 |
|
|
} |
357 |
|
|
|
358 |
|
✗ |
gtk_widget_set_halign (icon_widget, GTK_ALIGN_CENTER); |
359 |
|
✗ |
gtk_widget_set_valign (icon_widget, GTK_ALIGN_CENTER); |
360 |
|
✗ |
gtk_widget_set_name (icon_widget, "fingerprint-image"); |
361 |
|
|
|
362 |
|
✗ |
gtk_box_append (GTK_BOX (box), icon_widget); |
363 |
|
|
|
364 |
|
✗ |
gtk_widget_add_css_class (icon_widget, "circular"); |
365 |
|
|
|
366 |
|
✗ |
label = gtk_label_new_with_mnemonic (label_text); |
367 |
|
✗ |
gtk_box_append (GTK_BOX (box), label); |
368 |
|
|
|
369 |
|
✗ |
gtk_widget_add_css_class (box, "fingerprint-icon"); |
370 |
|
|
|
371 |
|
✗ |
if (out_icon) |
372 |
|
✗ |
*out_icon = icon_widget; |
373 |
|
|
|
374 |
|
✗ |
if (out_label) |
375 |
|
✗ |
*out_label = label; |
376 |
|
|
|
377 |
|
✗ |
return box; |
378 |
|
|
} |
379 |
|
|
|
380 |
|
|
static GtkWidget * |
381 |
|
✗ |
fingerprint_menu_button (const char *icon_name, |
382 |
|
|
const char *label_text) |
383 |
|
|
{ |
384 |
|
|
GtkWidget *flowbox_child; |
385 |
|
|
GtkWidget *button; |
386 |
|
|
GtkWidget *label; |
387 |
|
|
GtkWidget *box; |
388 |
|
|
|
389 |
|
✗ |
box = fingerprint_icon_new (icon_name, label_text, GTK_TYPE_MENU_BUTTON, NULL, |
390 |
|
|
&button, &label); |
391 |
|
|
|
392 |
|
✗ |
flowbox_child = gtk_flow_box_child_new (); |
393 |
|
✗ |
gtk_widget_set_focus_on_click (flowbox_child, FALSE); |
394 |
|
✗ |
gtk_widget_set_name (flowbox_child, "fingerprint-flowbox"); |
395 |
|
|
|
396 |
|
✗ |
gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (flowbox_child), box); |
397 |
|
|
|
398 |
|
✗ |
g_object_set_data (G_OBJECT (flowbox_child), "button", button); |
399 |
|
✗ |
g_object_set_data (G_OBJECT (flowbox_child), "icon", |
400 |
|
✗ |
GTK_IMAGE (gtk_menu_button_get_child (GTK_MENU_BUTTON (button)))); |
401 |
|
✗ |
g_object_set_data (G_OBJECT (flowbox_child), "label", label); |
402 |
|
✗ |
g_object_set_data (G_OBJECT (button), "flowbox-child", flowbox_child); |
403 |
|
|
|
404 |
|
✗ |
return flowbox_child; |
405 |
|
|
} |
406 |
|
|
|
407 |
|
|
static gboolean |
408 |
|
✗ |
prints_visibility_filter (GtkFlowBoxChild *child, |
409 |
|
|
gpointer user_data) |
410 |
|
|
{ |
411 |
|
✗ |
CcFingerprintDialog *self = user_data; |
412 |
|
|
const char *finger_id; |
413 |
|
|
|
414 |
|
✗ |
if (gtk_stack_get_visible_child (self->stack) != self->prints_manager) |
415 |
|
✗ |
return FALSE; |
416 |
|
|
|
417 |
|
✗ |
finger_id = g_object_get_data (G_OBJECT (child), "finger-id"); |
418 |
|
|
|
419 |
|
✗ |
if (!finger_id) |
420 |
|
✗ |
return TRUE; |
421 |
|
|
|
422 |
|
✗ |
if (!self->enrolled_fingers) |
423 |
|
✗ |
return FALSE; |
424 |
|
|
|
425 |
|
✗ |
return g_strv_contains ((const gchar **) self->enrolled_fingers, finger_id); |
426 |
|
|
} |
427 |
|
|
|
428 |
|
|
static GList * |
429 |
|
✗ |
get_container_children (GtkWidget *container) |
430 |
|
|
{ |
431 |
|
|
GtkWidget *child; |
432 |
|
✗ |
GList *list = NULL; |
433 |
|
|
|
434 |
|
✗ |
child = gtk_widget_get_first_child (container); |
435 |
|
✗ |
while (child) { |
436 |
|
✗ |
GtkWidget *next = gtk_widget_get_next_sibling (child); |
437 |
|
|
|
438 |
|
✗ |
list = g_list_append (list, child); |
439 |
|
|
|
440 |
|
✗ |
child = next; |
441 |
|
|
} |
442 |
|
|
|
443 |
|
✗ |
return list; |
444 |
|
|
} |
445 |
|
|
|
446 |
|
|
static void |
447 |
|
✗ |
update_prints_to_add_visibility (CcFingerprintDialog *self) |
448 |
|
|
{ |
449 |
|
✗ |
g_autoptr(GList) print_buttons = NULL; |
450 |
|
|
GList *l; |
451 |
|
|
guint i; |
452 |
|
|
|
453 |
|
✗ |
print_buttons = get_container_children (GTK_WIDGET (self->add_print_popover_box)); |
454 |
|
|
|
455 |
|
✗ |
for (i = 0, l = print_buttons; i < N_VALID_FINGERS && l; ++i, l = l->next) |
456 |
|
|
{ |
457 |
|
✗ |
GtkWidget *button = l->data; |
458 |
|
|
gboolean enrolled; |
459 |
|
|
|
460 |
|
✗ |
enrolled = self->enrolled_fingers && |
461 |
|
✗ |
g_strv_contains ((const gchar **) self->enrolled_fingers, |
462 |
|
✗ |
FINGER_IDS[i]); |
463 |
|
|
|
464 |
|
✗ |
gtk_widget_set_visible (button, !enrolled); |
465 |
|
|
} |
466 |
|
✗ |
} |
467 |
|
|
|
468 |
|
|
static void |
469 |
|
✗ |
update_prints_visibility (CcFingerprintDialog *self) |
470 |
|
|
{ |
471 |
|
✗ |
update_prints_to_add_visibility (self); |
472 |
|
|
|
473 |
|
✗ |
gtk_flow_box_invalidate_filter (self->prints_gallery); |
474 |
|
✗ |
} |
475 |
|
|
|
476 |
|
|
static void |
477 |
|
✗ |
list_enrolled_cb (GObject *object, |
478 |
|
|
GAsyncResult *res, |
479 |
|
|
gpointer user_data) |
480 |
|
|
{ |
481 |
|
✗ |
g_auto(GStrv) enrolled_fingers = NULL; |
482 |
|
✗ |
g_autoptr(GError) error = NULL; |
483 |
|
✗ |
g_autoptr(DialogStateRemover) state_remover = NULL; |
484 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
485 |
|
✗ |
CcFingerprintDialog *self = user_data; |
486 |
|
✗ |
guint n_enrolled_fingers = 0; |
487 |
|
|
|
488 |
|
✗ |
cc_fprintd_device_call_list_enrolled_fingers_finish (fprintd_device, |
489 |
|
|
&enrolled_fingers, |
490 |
|
|
res, &error); |
491 |
|
|
|
492 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
493 |
|
✗ |
return; |
494 |
|
|
|
495 |
|
✗ |
state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_PRINTS_LISTING); |
496 |
|
|
|
497 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->add_print_icon), TRUE); |
498 |
|
|
|
499 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED) |
500 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->prints_manager), TRUE); |
501 |
|
|
|
502 |
|
✗ |
if (error) |
503 |
|
|
{ |
504 |
|
✗ |
g_autofree char *dbus_error = g_dbus_error_get_remote_error (error); |
505 |
|
|
|
506 |
|
✗ |
if (!dbus_error || !g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.NoEnrolledPrints")) |
507 |
|
|
{ |
508 |
|
✗ |
g_autofree char *error_message = NULL; |
509 |
|
|
|
510 |
|
✗ |
error_message = g_strdup_printf (_("Failed to list fingerprints: %s"), |
511 |
|
|
dbus_error_to_human (self, error)); |
512 |
|
✗ |
g_warning ("Listing of fingerprints on device %s failed: %s", |
513 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
514 |
|
✗ |
notify_error (self, error_message); |
515 |
|
✗ |
return; |
516 |
|
|
} |
517 |
|
|
} |
518 |
|
|
else |
519 |
|
|
{ |
520 |
|
✗ |
n_enrolled_fingers = g_strv_length (enrolled_fingers); |
521 |
|
|
} |
522 |
|
|
|
523 |
|
✗ |
self->enrolled_fingers = g_steal_pointer (&enrolled_fingers); |
524 |
|
✗ |
gtk_flow_box_set_max_children_per_line (self->prints_gallery, |
525 |
|
✗ |
MIN (3, n_enrolled_fingers + 1)); |
526 |
|
|
|
527 |
|
✗ |
update_prints_visibility (self); |
528 |
|
|
|
529 |
|
✗ |
if (n_enrolled_fingers == N_VALID_FINGERS) |
530 |
|
✗ |
gtk_widget_set_sensitive (self->add_print_icon, FALSE); |
531 |
|
|
|
532 |
|
✗ |
if (n_enrolled_fingers > 0) |
533 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->delete_prints_button), TRUE); |
534 |
|
|
} |
535 |
|
|
|
536 |
|
|
static void |
537 |
|
✗ |
update_prints_store (CcFingerprintDialog *self) |
538 |
|
|
{ |
539 |
|
|
ActUser *user; |
540 |
|
|
|
541 |
|
✗ |
g_assert_true (CC_FPRINTD_IS_DEVICE (self->device)); |
542 |
|
|
|
543 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_PRINTS_LISTING)) |
544 |
|
✗ |
return; |
545 |
|
|
|
546 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->add_print_icon), FALSE); |
547 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->delete_prints_button), FALSE); |
548 |
|
|
|
549 |
|
✗ |
g_clear_pointer (&self->enrolled_fingers, g_strfreev); |
550 |
|
|
|
551 |
|
✗ |
user = cc_fingerprint_manager_get_user (self->manager); |
552 |
|
✗ |
cc_fprintd_device_call_list_enrolled_fingers (self->device, |
553 |
|
✗ |
act_user_get_user_name (user), |
554 |
|
|
self->cancellable, |
555 |
|
|
list_enrolled_cb, |
556 |
|
|
self); |
557 |
|
|
} |
558 |
|
|
|
559 |
|
|
static void |
560 |
|
✗ |
delete_prints_cb (GObject *object, |
561 |
|
|
GAsyncResult *res, |
562 |
|
|
gpointer user_data) |
563 |
|
|
{ |
564 |
|
✗ |
g_autoptr(GError) error = NULL; |
565 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
566 |
|
✗ |
CcFingerprintDialog *self = user_data; |
567 |
|
|
|
568 |
|
✗ |
cc_fprintd_device_call_delete_enrolled_fingers2_finish (fprintd_device, res, &error); |
569 |
|
|
|
570 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
571 |
|
✗ |
return; |
572 |
|
|
|
573 |
|
✗ |
if (error) |
574 |
|
|
{ |
575 |
|
✗ |
g_autofree char *error_message = NULL; |
576 |
|
|
|
577 |
|
✗ |
error_message = g_strdup_printf (_("Failed to delete saved fingerprints: %s"), |
578 |
|
|
dbus_error_to_human (self, error)); |
579 |
|
✗ |
g_warning ("Deletion of fingerprints on device %s failed: %s", |
580 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
581 |
|
✗ |
notify_error (self, error_message); |
582 |
|
|
} |
583 |
|
|
|
584 |
|
✗ |
update_prints_store (self); |
585 |
|
✗ |
cc_fingerprint_manager_update_state (self->manager, NULL, NULL); |
586 |
|
|
} |
587 |
|
|
|
588 |
|
|
static void |
589 |
|
✗ |
delete_enrolled_prints (CcFingerprintDialog *self) |
590 |
|
|
{ |
591 |
|
✗ |
g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED); |
592 |
|
|
|
593 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_DELETING)) |
594 |
|
✗ |
return; |
595 |
|
|
|
596 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->prints_manager), FALSE); |
597 |
|
|
|
598 |
|
✗ |
cc_fprintd_device_call_delete_enrolled_fingers2 (self->device, |
599 |
|
|
self->cancellable, |
600 |
|
|
delete_prints_cb, |
601 |
|
|
self); |
602 |
|
|
} |
603 |
|
|
|
604 |
|
|
static const char * |
605 |
|
✗ |
get_finger_name (const char *finger_id) |
606 |
|
|
{ |
607 |
|
✗ |
if (g_str_equal (finger_id, "left-thumb")) |
608 |
|
✗ |
return _("Left thumb"); |
609 |
|
✗ |
if (g_str_equal (finger_id, "left-middle-finger")) |
610 |
|
✗ |
return _("Left middle finger"); |
611 |
|
✗ |
if (g_str_equal (finger_id, "left-index-finger")) |
612 |
|
✗ |
return _("_Left index finger"); |
613 |
|
✗ |
if (g_str_equal (finger_id, "left-ring-finger")) |
614 |
|
✗ |
return _("Left ring finger"); |
615 |
|
✗ |
if (g_str_equal (finger_id, "left-little-finger")) |
616 |
|
✗ |
return _("Left little finger"); |
617 |
|
✗ |
if (g_str_equal (finger_id, "right-thumb")) |
618 |
|
✗ |
return _("Right thumb"); |
619 |
|
✗ |
if (g_str_equal (finger_id, "right-middle-finger")) |
620 |
|
✗ |
return _("Right middle finger"); |
621 |
|
✗ |
if (g_str_equal (finger_id, "right-index-finger")) |
622 |
|
✗ |
return _("_Right index finger"); |
623 |
|
✗ |
if (g_str_equal (finger_id, "right-ring-finger")) |
624 |
|
✗ |
return _("Right ring finger"); |
625 |
|
✗ |
if (g_str_equal (finger_id, "right-little-finger")) |
626 |
|
✗ |
return _("Right little finger"); |
627 |
|
|
|
628 |
|
✗ |
g_return_val_if_reached (_("Unknown Finger")); |
629 |
|
|
} |
630 |
|
|
|
631 |
|
|
static gboolean |
632 |
|
✗ |
have_multiple_devices (CcFingerprintDialog *self) |
633 |
|
|
{ |
634 |
|
✗ |
g_autoptr(GList) devices_rows = NULL; |
635 |
|
|
|
636 |
|
✗ |
devices_rows = get_container_children (GTK_WIDGET (self->devices_list)); |
637 |
|
|
|
638 |
|
✗ |
return devices_rows && devices_rows->next; |
639 |
|
|
} |
640 |
|
|
|
641 |
|
|
static void |
642 |
|
✗ |
set_enroll_result_message (CcFingerprintDialog *self, |
643 |
|
|
EnrollState enroll_state, |
644 |
|
|
const char *message) |
645 |
|
|
{ |
646 |
|
|
const char *icon_name; |
647 |
|
|
guint i; |
648 |
|
|
|
649 |
|
✗ |
g_return_if_fail (enroll_state >= 0 && enroll_state < N_ENROLL_STATES); |
650 |
|
|
|
651 |
|
✗ |
switch (enroll_state) |
652 |
|
|
{ |
653 |
|
✗ |
case ENROLL_STATE_WARNING: |
654 |
|
|
case ENROLL_STATE_ERROR: |
655 |
|
✗ |
icon_name = "fingerprint-detection-warning-symbolic"; |
656 |
|
✗ |
break; |
657 |
|
✗ |
case ENROLL_STATE_COMPLETED: |
658 |
|
✗ |
icon_name = "fingerprint-detection-complete-symbolic"; |
659 |
|
✗ |
break; |
660 |
|
✗ |
default: |
661 |
|
✗ |
icon_name = "fingerprint-detection-symbolic"; |
662 |
|
|
} |
663 |
|
|
|
664 |
|
✗ |
for (i = 0; i < N_ENROLL_STATES; ++i) |
665 |
|
✗ |
gtk_widget_remove_css_class (self->enroll_result_icon, ENROLL_STATE_CLASSES[i]); |
666 |
|
|
|
667 |
|
✗ |
gtk_widget_add_css_class (self->enroll_result_icon, ENROLL_STATE_CLASSES[enroll_state]); |
668 |
|
|
|
669 |
|
✗ |
gtk_image_set_from_icon_name (self->enroll_result_image, icon_name); |
670 |
|
✗ |
gtk_label_set_label (self->enroll_result_message, message); |
671 |
|
|
} |
672 |
|
|
|
673 |
|
|
static gboolean |
674 |
|
✗ |
stage_passed_timeout_cb (gpointer user_data) |
675 |
|
|
{ |
676 |
|
✗ |
CcFingerprintDialog *self = user_data; |
677 |
|
|
const char *current_message; |
678 |
|
|
|
679 |
|
✗ |
current_message = gtk_label_get_label (self->enroll_result_message); |
680 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_NORMAL, current_message); |
681 |
|
✗ |
self->enroll_stage_passed_id = 0; |
682 |
|
|
|
683 |
|
✗ |
return FALSE; |
684 |
|
|
} |
685 |
|
|
|
686 |
|
|
static void |
687 |
|
✗ |
handle_enroll_signal (CcFingerprintDialog *self, |
688 |
|
|
const char *result, |
689 |
|
|
gboolean done) |
690 |
|
|
{ |
691 |
|
|
gboolean completed; |
692 |
|
|
|
693 |
|
✗ |
g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING); |
694 |
|
|
|
695 |
|
✗ |
g_debug ("Device enroll result message: %s, done: %d", result, done); |
696 |
|
|
|
697 |
|
✗ |
completed = g_str_equal (result, "enroll-completed"); |
698 |
|
✗ |
g_clear_handle_id (&self->enroll_stage_passed_id, g_source_remove); |
699 |
|
|
|
700 |
|
✗ |
if (g_str_equal (result, "enroll-stage-passed") || completed) |
701 |
|
✗ |
{ |
702 |
|
|
guint enroll_stages; |
703 |
|
|
|
704 |
|
✗ |
enroll_stages = cc_fprintd_device_get_num_enroll_stages (self->device); |
705 |
|
|
|
706 |
|
✗ |
self->enroll_stages_passed++; |
707 |
|
|
|
708 |
|
✗ |
if (enroll_stages > 0) |
709 |
|
✗ |
self->enroll_progress = |
710 |
|
✗ |
MIN (1.0f, self->enroll_stages_passed / (double) enroll_stages); |
711 |
|
|
else |
712 |
|
✗ |
g_warning ("The device %s requires an invalid number of enroll stages (%u)", |
713 |
|
|
cc_fprintd_device_get_name (self->device), enroll_stages); |
714 |
|
|
|
715 |
|
✗ |
g_debug ("Enroll state passed, %u/%u (%.2f%%)", |
716 |
|
|
self->enroll_stages_passed, (guint) enroll_stages, |
717 |
|
|
self->enroll_progress); |
718 |
|
|
|
719 |
|
✗ |
if (!completed) |
720 |
|
|
{ |
721 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_SUCCESS, NULL); |
722 |
|
|
|
723 |
|
✗ |
self->enroll_stage_passed_id = |
724 |
|
✗ |
g_timeout_add (750, stage_passed_timeout_cb, self); |
725 |
|
|
} |
726 |
|
|
else |
727 |
|
|
{ |
728 |
|
✗ |
if (!G_APPROX_VALUE (self->enroll_progress, 1.0f, FLT_EPSILON)) |
729 |
|
|
{ |
730 |
|
✗ |
g_warning ("Device marked enroll as completed, but progress is at %.2f", |
731 |
|
|
self->enroll_progress); |
732 |
|
✗ |
self->enroll_progress = 1.0f; |
733 |
|
|
} |
734 |
|
|
} |
735 |
|
|
} |
736 |
|
✗ |
else if (!done) |
737 |
|
|
{ |
738 |
|
|
const char *scan_type; |
739 |
|
|
const char *message; |
740 |
|
|
gboolean is_swipe; |
741 |
|
|
|
742 |
|
✗ |
scan_type = cc_fprintd_device_get_scan_type (self->device); |
743 |
|
✗ |
is_swipe = g_str_equal (scan_type, "swipe"); |
744 |
|
|
|
745 |
|
✗ |
message = enroll_result_str_to_msg (result, is_swipe); |
746 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_RETRY, message); |
747 |
|
|
|
748 |
|
✗ |
self->enroll_stage_passed_id = |
749 |
|
✗ |
g_timeout_add (850, stage_passed_timeout_cb, self); |
750 |
|
|
} |
751 |
|
|
|
752 |
|
✗ |
if (done) |
753 |
|
|
{ |
754 |
|
✗ |
if (completed) |
755 |
|
|
{ |
756 |
|
|
/* TRANSLATORS: This is the message shown when the fingerprint |
757 |
|
|
* enrollment has been completed successfully */ |
758 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_COMPLETED, |
759 |
|
✗ |
C_("Fingerprint enroll state", "Complete")); |
760 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->cancel_button), FALSE); |
761 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->done_button), TRUE); |
762 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->done_button)); |
763 |
|
|
} |
764 |
|
|
else |
765 |
|
|
{ |
766 |
|
|
const char *message; |
767 |
|
|
|
768 |
|
✗ |
if (g_str_equal (result, "enroll-disconnected")) |
769 |
|
|
{ |
770 |
|
✗ |
message = _("Fingerprint device disconnected"); |
771 |
|
✗ |
remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED | |
772 |
|
|
DIALOG_STATE_DEVICE_ENROLLING); |
773 |
|
|
} |
774 |
|
✗ |
else if (g_str_equal (result, "enroll-data-full")) |
775 |
|
|
{ |
776 |
|
✗ |
message = _("Fingerprint device storage is full"); |
777 |
|
|
} |
778 |
|
✗ |
else if (g_str_equal (result, "enroll-duplicate")) |
779 |
|
|
{ |
780 |
|
✗ |
message = _("Fingerprint is duplicate"); |
781 |
|
|
} |
782 |
|
|
else |
783 |
|
|
{ |
784 |
|
✗ |
message = _("Failed to enroll new fingerprint"); |
785 |
|
|
} |
786 |
|
|
|
787 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_WARNING, message); |
788 |
|
|
} |
789 |
|
|
} |
790 |
|
|
} |
791 |
|
|
|
792 |
|
|
static void |
793 |
|
✗ |
enroll_start_cb (GObject *object, |
794 |
|
|
GAsyncResult *res, |
795 |
|
|
gpointer user_data) |
796 |
|
|
{ |
797 |
|
✗ |
g_autoptr(GError) error = NULL; |
798 |
|
✗ |
g_autoptr(DialogStateRemover) state_remover = NULL; |
799 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
800 |
|
✗ |
CcFingerprintDialog *self = user_data; |
801 |
|
|
|
802 |
|
✗ |
cc_fprintd_device_call_enroll_start_finish (fprintd_device, res, &error); |
803 |
|
|
|
804 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
805 |
|
✗ |
return; |
806 |
|
|
|
807 |
|
✗ |
state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_ENROLL_STARTING); |
808 |
|
|
|
809 |
|
✗ |
if (error) |
810 |
|
|
{ |
811 |
|
✗ |
g_autofree char *error_message = NULL; |
812 |
|
|
|
813 |
|
✗ |
remove_dialog_state (self, DIALOG_STATE_DEVICE_ENROLLING); |
814 |
|
|
|
815 |
|
✗ |
error_message = g_strdup_printf (_("Failed to start enrollment: %s"), |
816 |
|
|
dbus_error_to_human (self, error)); |
817 |
|
✗ |
g_warning ("Enrollment on device %s failed: %s", |
818 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
819 |
|
✗ |
notify_error (self, error_message); |
820 |
|
|
|
821 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_ERROR, |
822 |
|
✗ |
C_("Fingerprint enroll state", |
823 |
|
|
"Failed to enroll new fingerprint")); |
824 |
|
✗ |
gtk_widget_set_sensitive (self->enrollment_view, FALSE); |
825 |
|
|
|
826 |
|
✗ |
return; |
827 |
|
|
} |
828 |
|
|
} |
829 |
|
|
|
830 |
|
|
static void |
831 |
|
✗ |
enroll_stop_cb (GObject *object, |
832 |
|
|
GAsyncResult *res, |
833 |
|
|
gpointer user_data) |
834 |
|
|
{ |
835 |
|
✗ |
g_autoptr(GError) error = NULL; |
836 |
|
✗ |
g_autoptr(DialogStateRemover) state_remover = NULL; |
837 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
838 |
|
✗ |
CcFingerprintDialog *self = user_data; |
839 |
|
|
|
840 |
|
✗ |
cc_fprintd_device_call_enroll_stop_finish (fprintd_device, res, &error); |
841 |
|
|
|
842 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
843 |
|
✗ |
return; |
844 |
|
|
|
845 |
|
✗ |
state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_ENROLLING | |
846 |
|
|
DIALOG_STATE_DEVICE_ENROLL_STOPPING); |
847 |
|
✗ |
gtk_widget_set_sensitive (self->enrollment_view, TRUE); |
848 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->prints_manager); |
849 |
|
|
|
850 |
|
✗ |
if (error) |
851 |
|
|
{ |
852 |
|
✗ |
g_autofree char *error_message = NULL; |
853 |
|
|
|
854 |
|
✗ |
error_message = g_strdup_printf (_("Failed to stop enrollment: %s"), |
855 |
|
|
dbus_error_to_human (self, error)); |
856 |
|
✗ |
g_warning ("Stopping enrollment on device %s failed: %s", |
857 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
858 |
|
✗ |
notify_error (self, error_message); |
859 |
|
|
|
860 |
|
✗ |
return; |
861 |
|
|
} |
862 |
|
|
|
863 |
|
✗ |
cc_fingerprint_manager_update_state (self->manager, NULL, NULL); |
864 |
|
|
} |
865 |
|
|
|
866 |
|
|
static void |
867 |
|
✗ |
enroll_stop (CcFingerprintDialog *self) |
868 |
|
|
{ |
869 |
|
✗ |
g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING); |
870 |
|
|
|
871 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_ENROLL_STOPPING)) |
872 |
|
✗ |
return; |
873 |
|
|
|
874 |
|
✗ |
gtk_widget_set_sensitive (self->enrollment_view, FALSE); |
875 |
|
✗ |
cc_fprintd_device_call_enroll_stop (self->device, self->cancellable, |
876 |
|
|
enroll_stop_cb, self); |
877 |
|
|
} |
878 |
|
|
|
879 |
|
|
static char * |
880 |
|
✗ |
get_enrollment_string (CcFingerprintDialog *self, |
881 |
|
|
const char *finger_id) |
882 |
|
|
{ |
883 |
|
|
char *ret; |
884 |
|
|
const char *scan_type; |
885 |
|
|
const char *device_name; |
886 |
|
|
gboolean is_swipe; |
887 |
|
|
|
888 |
|
✗ |
device_name = NULL; |
889 |
|
✗ |
scan_type = cc_fprintd_device_get_scan_type (self->device); |
890 |
|
✗ |
is_swipe = g_str_equal (scan_type, "swipe"); |
891 |
|
|
|
892 |
|
✗ |
if (have_multiple_devices (self)) |
893 |
|
✗ |
device_name = cc_fprintd_device_get_name (self->device); |
894 |
|
|
|
895 |
|
✗ |
ret = finger_str_to_msg (finger_id, device_name, is_swipe); |
896 |
|
|
|
897 |
|
✗ |
if (ret) |
898 |
|
✗ |
return ret; |
899 |
|
|
|
900 |
|
✗ |
return g_strdup (_("Repeatedly lift and place your finger on the reader to enroll your fingerprint")); |
901 |
|
|
} |
902 |
|
|
|
903 |
|
|
static void |
904 |
|
✗ |
enroll_finger (CcFingerprintDialog *self, |
905 |
|
|
const char *finger_id) |
906 |
|
|
{ |
907 |
|
✗ |
g_auto(GStrv) tmp_finger_name = NULL; |
908 |
|
✗ |
g_autofree char *finger_name = NULL; |
909 |
|
✗ |
g_autofree char *enroll_message = NULL; |
910 |
|
|
|
911 |
|
✗ |
g_return_if_fail (finger_id); |
912 |
|
|
|
913 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_ENROLLING | |
914 |
|
|
DIALOG_STATE_DEVICE_ENROLL_STARTING)) |
915 |
|
✗ |
return; |
916 |
|
|
|
917 |
|
✗ |
self->enroll_progress = 0; |
918 |
|
✗ |
self->enroll_stages_passed = 0; |
919 |
|
|
|
920 |
|
✗ |
g_debug ("Enrolling finger %s", finger_id); |
921 |
|
|
|
922 |
|
✗ |
enroll_message = get_enrollment_string (self, finger_id); |
923 |
|
✗ |
tmp_finger_name = g_strsplit (get_finger_name (finger_id), "_", -1); |
924 |
|
✗ |
finger_name = g_strjoinv ("", tmp_finger_name); |
925 |
|
|
|
926 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_NORMAL, NULL); |
927 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->enrollment_view); |
928 |
|
✗ |
gtk_label_set_label (self->enroll_message, enroll_message); |
929 |
|
✗ |
gtk_editable_set_text (GTK_EDITABLE (self->enroll_print_entry), finger_name); |
930 |
|
|
|
931 |
|
✗ |
cc_fprintd_device_call_enroll_start (self->device, finger_id, self->cancellable, |
932 |
|
|
enroll_start_cb, self); |
933 |
|
|
} |
934 |
|
|
|
935 |
|
|
static void |
936 |
|
✗ |
populate_enrollment_view (CcFingerprintDialog *self) |
937 |
|
|
{ |
938 |
|
✗ |
self->enroll_result_icon = |
939 |
|
✗ |
fingerprint_icon_new ("fingerprint-detection-symbolic", |
940 |
|
|
NULL, |
941 |
|
|
GTK_TYPE_IMAGE, |
942 |
|
✗ |
&self->enroll_progress, |
943 |
|
✗ |
(GtkWidget **) &self->enroll_result_image, |
944 |
|
✗ |
(GtkWidget **) &self->enroll_result_message); |
945 |
|
|
|
946 |
|
✗ |
gtk_box_prepend (GTK_BOX (self->enroll_print_bin), self->enroll_result_icon); |
947 |
|
|
|
948 |
|
✗ |
gtk_widget_add_css_class (self->enroll_result_icon, "enroll-status"); |
949 |
|
✗ |
} |
950 |
|
|
|
951 |
|
|
static void |
952 |
|
✗ |
on_print_activated_cb (CcFingerprintDialog *self, |
953 |
|
|
GtkFlowBoxChild *child) |
954 |
|
|
{ |
955 |
|
|
GtkWidget *selected_button; |
956 |
|
|
|
957 |
|
✗ |
selected_button = g_object_get_data (G_OBJECT (child), "button"); |
958 |
|
✗ |
g_signal_emit_by_name (GTK_MENU_BUTTON (selected_button), "activate"); |
959 |
|
✗ |
} |
960 |
|
|
|
961 |
|
|
static void |
962 |
|
✗ |
on_enroll_cb (CcFingerprintDialog *self, |
963 |
|
|
GtkMenuButton *button) |
964 |
|
|
{ |
965 |
|
|
const char *finger_id; |
966 |
|
|
|
967 |
|
✗ |
finger_id = g_object_get_data (G_OBJECT (button), "finger-id"); |
968 |
|
✗ |
enroll_finger (self, finger_id); |
969 |
|
✗ |
} |
970 |
|
|
|
971 |
|
|
static void |
972 |
|
✗ |
populate_add_print_popover (CcFingerprintDialog *self) |
973 |
|
|
{ |
974 |
|
|
guint i; |
975 |
|
|
|
976 |
|
✗ |
for (i = 0; i < N_VALID_FINGERS; ++i) |
977 |
|
|
{ |
978 |
|
|
GtkWidget *finger_item; |
979 |
|
|
|
980 |
|
✗ |
finger_item = gtk_button_new (); |
981 |
|
✗ |
gtk_button_set_label (GTK_BUTTON (finger_item), get_finger_name (FINGER_IDS[i])); |
982 |
|
✗ |
gtk_button_set_use_underline (GTK_BUTTON (finger_item), TRUE); |
983 |
|
✗ |
g_object_set_data (G_OBJECT (finger_item), "finger-id", (gpointer) FINGER_IDS[i]); |
984 |
|
✗ |
gtk_box_prepend (GTK_BOX (self->add_print_popover_box), finger_item); |
985 |
|
|
|
986 |
|
✗ |
g_signal_connect_object (finger_item, "clicked", G_CALLBACK (on_enroll_cb), |
987 |
|
|
self, G_CONNECT_SWAPPED); |
988 |
|
|
} |
989 |
|
✗ |
} |
990 |
|
|
|
991 |
|
|
static void |
992 |
|
✗ |
populate_prints_gallery (CcFingerprintDialog *self) |
993 |
|
|
{ |
994 |
|
|
const char *add_print_label; |
995 |
|
|
GtkWidget *button; |
996 |
|
|
guint i; |
997 |
|
|
|
998 |
|
✗ |
g_return_if_fail (!GTK_IS_WIDGET (self->add_print_icon)); |
999 |
|
|
|
1000 |
|
✗ |
for (i = 0; i < N_VALID_FINGERS; ++i) |
1001 |
|
|
{ |
1002 |
|
|
GtkWidget *flowbox_child; |
1003 |
|
|
GtkWidget *popover; |
1004 |
|
|
GtkWidget *reenroll_button; |
1005 |
|
|
|
1006 |
|
✗ |
flowbox_child = fingerprint_menu_button ("fingerprint-detection-symbolic", |
1007 |
|
|
get_finger_name (FINGER_IDS[i])); |
1008 |
|
|
|
1009 |
|
✗ |
button = g_object_get_data (G_OBJECT (flowbox_child), "button"); |
1010 |
|
|
|
1011 |
|
✗ |
popover = gtk_popover_new (); |
1012 |
|
✗ |
reenroll_button = gtk_button_new (); |
1013 |
|
✗ |
gtk_button_set_use_underline (GTK_BUTTON (reenroll_button), TRUE); |
1014 |
|
✗ |
gtk_button_set_label (GTK_BUTTON (reenroll_button), _("_Re-enroll this fingerโฆ")); |
1015 |
|
✗ |
g_object_set_data (G_OBJECT (reenroll_button), "finger-id", |
1016 |
|
✗ |
(gpointer) FINGER_IDS[i]); |
1017 |
|
✗ |
g_signal_connect_object (reenroll_button, "clicked", G_CALLBACK (on_enroll_cb), self, G_CONNECT_SWAPPED); |
1018 |
|
✗ |
gtk_popover_set_child (GTK_POPOVER (popover), reenroll_button); |
1019 |
|
|
|
1020 |
|
✗ |
gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), |
1021 |
|
|
popover); |
1022 |
|
✗ |
g_object_set_data (G_OBJECT (flowbox_child), "finger-id", |
1023 |
|
✗ |
(gpointer) FINGER_IDS[i]); |
1024 |
|
|
|
1025 |
|
✗ |
gtk_flow_box_insert (self->prints_gallery, flowbox_child, i); |
1026 |
|
|
} |
1027 |
|
|
|
1028 |
|
|
/* TRANSLATORS: This is the label for the button to enroll a new finger */ |
1029 |
|
✗ |
add_print_label = _("Scan new fingerprint"); |
1030 |
|
✗ |
self->add_print_icon = fingerprint_menu_button ("list-add-symbolic", |
1031 |
|
|
add_print_label); |
1032 |
|
✗ |
gtk_widget_add_css_class (self->add_print_icon, "fingerprint-print-add"); |
1033 |
|
|
|
1034 |
|
✗ |
populate_add_print_popover (self); |
1035 |
|
✗ |
button = g_object_get_data (G_OBJECT (self->add_print_icon), "button"); |
1036 |
|
✗ |
gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), |
1037 |
|
✗ |
GTK_WIDGET (self->add_print_popover)); |
1038 |
|
|
|
1039 |
|
✗ |
gtk_flow_box_insert (self->prints_gallery, self->add_print_icon, -1); |
1040 |
|
✗ |
gtk_flow_box_set_max_children_per_line (self->prints_gallery, 1); |
1041 |
|
|
|
1042 |
|
✗ |
gtk_flow_box_set_filter_func (self->prints_gallery, prints_visibility_filter, |
1043 |
|
|
self, NULL); |
1044 |
|
|
|
1045 |
|
✗ |
update_prints_visibility (self); |
1046 |
|
|
} |
1047 |
|
|
|
1048 |
|
|
static void |
1049 |
|
✗ |
release_device_cb (GObject *object, |
1050 |
|
|
GAsyncResult *res, |
1051 |
|
|
gpointer user_data) |
1052 |
|
|
{ |
1053 |
|
✗ |
g_autoptr(GError) error = NULL; |
1054 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
1055 |
|
✗ |
CcFingerprintDialog *self = user_data; |
1056 |
|
|
|
1057 |
|
✗ |
cc_fprintd_device_call_release_finish (fprintd_device, res, &error); |
1058 |
|
|
|
1059 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1060 |
|
✗ |
return; |
1061 |
|
|
|
1062 |
|
✗ |
if (error) |
1063 |
|
|
{ |
1064 |
|
✗ |
g_autofree char *error_message = NULL; |
1065 |
|
|
|
1066 |
|
✗ |
error_message = g_strdup_printf (_("Failed to release fingerprint device %s: %s"), |
1067 |
|
|
cc_fprintd_device_get_name (fprintd_device), |
1068 |
|
|
dbus_error_to_human (self, error)); |
1069 |
|
✗ |
g_warning ("Releasing device %s failed: %s", |
1070 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
1071 |
|
|
|
1072 |
|
✗ |
notify_error (self, error_message); |
1073 |
|
✗ |
return; |
1074 |
|
|
} |
1075 |
|
|
|
1076 |
|
✗ |
remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED); |
1077 |
|
|
} |
1078 |
|
|
|
1079 |
|
|
static void |
1080 |
|
✗ |
release_device (CcFingerprintDialog *self) |
1081 |
|
|
{ |
1082 |
|
✗ |
if (!self->device || !(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)) |
1083 |
|
✗ |
return; |
1084 |
|
|
|
1085 |
|
✗ |
disconnect_device_signals (self); |
1086 |
|
|
|
1087 |
|
✗ |
cc_fprintd_device_call_release (self->device, |
1088 |
|
|
self->cancellable, |
1089 |
|
|
release_device_cb, |
1090 |
|
|
self); |
1091 |
|
|
} |
1092 |
|
|
|
1093 |
|
|
static void |
1094 |
|
✗ |
on_device_signal (CcFingerprintDialog *self, |
1095 |
|
|
gchar *sender_name, |
1096 |
|
|
gchar *signal_name, |
1097 |
|
|
GVariant *parameters, |
1098 |
|
|
gpointer user_data) |
1099 |
|
|
{ |
1100 |
|
✗ |
if (g_str_equal (signal_name, "EnrollStatus")) |
1101 |
|
|
{ |
1102 |
|
|
const char *result; |
1103 |
|
|
gboolean done; |
1104 |
|
|
|
1105 |
|
✗ |
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sb)"))) |
1106 |
|
|
{ |
1107 |
|
✗ |
g_warning ("Unexpected enroll parameters type %s", |
1108 |
|
|
g_variant_get_type_string (parameters)); |
1109 |
|
✗ |
return; |
1110 |
|
|
} |
1111 |
|
|
|
1112 |
|
✗ |
g_variant_get (parameters, "(&sb)", &result, &done); |
1113 |
|
✗ |
handle_enroll_signal (self, result, done); |
1114 |
|
|
} |
1115 |
|
|
} |
1116 |
|
|
|
1117 |
|
|
static void claim_device (CcFingerprintDialog *self); |
1118 |
|
|
|
1119 |
|
|
static void |
1120 |
|
✗ |
on_device_owner_changed (CcFprintdDevice *device, |
1121 |
|
|
GParamSpec *spec, |
1122 |
|
|
CcFingerprintDialog *self) |
1123 |
|
|
{ |
1124 |
|
✗ |
g_autofree char *name_owner = NULL; |
1125 |
|
|
|
1126 |
|
✗ |
name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (device)); |
1127 |
|
|
|
1128 |
|
✗ |
if (!name_owner) |
1129 |
|
|
{ |
1130 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED) |
1131 |
|
|
{ |
1132 |
|
✗ |
disconnect_device_signals (self); |
1133 |
|
|
|
1134 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING) |
1135 |
|
|
{ |
1136 |
|
✗ |
set_enroll_result_message (self, ENROLL_STATE_ERROR, |
1137 |
|
✗ |
C_("Fingerprint enroll state", |
1138 |
|
|
"Problem Reading Device")); |
1139 |
|
|
} |
1140 |
|
|
|
1141 |
|
✗ |
remove_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED); |
1142 |
|
✗ |
claim_device (self); |
1143 |
|
|
} |
1144 |
|
|
} |
1145 |
|
✗ |
} |
1146 |
|
|
|
1147 |
|
|
static void |
1148 |
|
✗ |
claim_device_cb (GObject *object, |
1149 |
|
|
GAsyncResult *res, |
1150 |
|
|
gpointer user_data) |
1151 |
|
|
{ |
1152 |
|
✗ |
g_autoptr(GError) error = NULL; |
1153 |
|
✗ |
g_autoptr(DialogStateRemover) state_remover = NULL; |
1154 |
|
✗ |
CcFprintdDevice *fprintd_device = CC_FPRINTD_DEVICE (object); |
1155 |
|
✗ |
CcFingerprintDialog *self = user_data; |
1156 |
|
|
|
1157 |
|
✗ |
cc_fprintd_device_call_claim_finish (fprintd_device, res, &error); |
1158 |
|
|
|
1159 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1160 |
|
✗ |
return; |
1161 |
|
|
|
1162 |
|
✗ |
state_remover = auto_state_remover (self, DIALOG_STATE_DEVICE_CLAIMING); |
1163 |
|
|
|
1164 |
|
✗ |
if (error) |
1165 |
|
|
{ |
1166 |
|
✗ |
g_autofree char *dbus_error = g_dbus_error_get_remote_error (error); |
1167 |
|
✗ |
g_autofree char *error_message = NULL; |
1168 |
|
|
|
1169 |
|
✗ |
if (dbus_error && g_str_equal (dbus_error, CC_FPRINTD_NAME ".Error.AlreadyInUse") && |
1170 |
|
✗ |
(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)) |
1171 |
|
✗ |
return; |
1172 |
|
|
|
1173 |
|
✗ |
error_message = g_strdup_printf (_("Failed to claim fingerprint device %s: %s"), |
1174 |
|
|
cc_fprintd_device_get_name (self->device), |
1175 |
|
|
dbus_error_to_human (self, error)); |
1176 |
|
✗ |
g_warning ("Claiming device %s failed: %s", |
1177 |
|
|
cc_fprintd_device_get_name (self->device), error->message); |
1178 |
|
✗ |
notify_error (self, error_message); |
1179 |
|
✗ |
return; |
1180 |
|
|
} |
1181 |
|
|
|
1182 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMED)) |
1183 |
|
✗ |
return; |
1184 |
|
|
|
1185 |
|
✗ |
gtk_widget_set_sensitive (self->prints_manager, TRUE); |
1186 |
|
✗ |
self->device_signal_id = g_signal_connect_object (self->device, "g-signal", |
1187 |
|
|
G_CALLBACK (on_device_signal), |
1188 |
|
|
self, G_CONNECT_SWAPPED); |
1189 |
|
✗ |
self->device_name_owner_id = g_signal_connect_object (self->device, "notify::g-name-owner", |
1190 |
|
|
G_CALLBACK (on_device_owner_changed), |
1191 |
|
|
self, 0); |
1192 |
|
|
} |
1193 |
|
|
|
1194 |
|
|
static void |
1195 |
|
✗ |
claim_device (CcFingerprintDialog *self) |
1196 |
|
|
{ |
1197 |
|
|
ActUser *user; |
1198 |
|
|
|
1199 |
|
✗ |
g_return_if_fail (!(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)); |
1200 |
|
|
|
1201 |
|
✗ |
if (!add_dialog_state (self, DIALOG_STATE_DEVICE_CLAIMING)) |
1202 |
|
✗ |
return; |
1203 |
|
|
|
1204 |
|
✗ |
user = cc_fingerprint_manager_get_user (self->manager); |
1205 |
|
✗ |
gtk_widget_set_sensitive (self->prints_manager, FALSE); |
1206 |
|
|
|
1207 |
|
✗ |
cc_fprintd_device_call_claim (self->device, |
1208 |
|
✗ |
act_user_get_user_name (user), |
1209 |
|
|
self->cancellable, |
1210 |
|
|
claim_device_cb, |
1211 |
|
|
self); |
1212 |
|
|
} |
1213 |
|
|
|
1214 |
|
|
static void |
1215 |
|
✗ |
on_stack_child_changed (CcFingerprintDialog *self) |
1216 |
|
|
{ |
1217 |
|
✗ |
GtkWidget *visible_child = gtk_stack_get_visible_child (self->stack); |
1218 |
|
|
|
1219 |
|
✗ |
g_debug ("Fingerprint dialog child changed: %s", |
1220 |
|
|
gtk_stack_get_visible_child_name (self->stack)); |
1221 |
|
|
|
1222 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->back_button), FALSE); |
1223 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->cancel_button), FALSE); |
1224 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->done_button), FALSE); |
1225 |
|
|
|
1226 |
|
✗ |
adw_header_bar_set_show_start_title_buttons (ADW_HEADER_BAR (self->titlebar), TRUE); |
1227 |
|
✗ |
adw_header_bar_set_show_end_title_buttons (ADW_HEADER_BAR (self->titlebar), TRUE); |
1228 |
|
✗ |
gtk_flow_box_invalidate_filter (self->prints_gallery); |
1229 |
|
|
|
1230 |
|
✗ |
if (visible_child == self->prints_manager) |
1231 |
|
|
{ |
1232 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->back_button), |
1233 |
|
|
have_multiple_devices (self)); |
1234 |
|
✗ |
notify_error (self, NULL); |
1235 |
|
✗ |
update_prints_store (self); |
1236 |
|
|
|
1237 |
|
✗ |
if (!(self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)) |
1238 |
|
✗ |
claim_device (self); |
1239 |
|
|
} |
1240 |
|
✗ |
else if (visible_child == self->enrollment_view) |
1241 |
|
|
{ |
1242 |
|
✗ |
adw_header_bar_set_show_start_title_buttons (ADW_HEADER_BAR (self->titlebar), FALSE); |
1243 |
|
✗ |
adw_header_bar_set_show_end_title_buttons (ADW_HEADER_BAR (self->titlebar), FALSE); |
1244 |
|
|
|
1245 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->cancel_button), TRUE); |
1246 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->cancel_button), TRUE); |
1247 |
|
|
|
1248 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->done_button), TRUE); |
1249 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->done_button), FALSE); |
1250 |
|
|
} |
1251 |
|
|
else |
1252 |
|
|
{ |
1253 |
|
✗ |
release_device (self); |
1254 |
|
✗ |
g_clear_object (&self->device); |
1255 |
|
|
} |
1256 |
|
✗ |
} |
1257 |
|
|
|
1258 |
|
|
static void |
1259 |
|
✗ |
cc_fingerprint_dialog_init (CcFingerprintDialog *self) |
1260 |
|
|
{ |
1261 |
|
✗ |
self->cancellable = g_cancellable_new (); |
1262 |
|
|
|
1263 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
1264 |
|
|
|
1265 |
|
✗ |
on_stack_child_changed (self); |
1266 |
|
✗ |
g_signal_connect_object (self->stack, "notify::visible-child", |
1267 |
|
|
G_CALLBACK (on_stack_child_changed), self, |
1268 |
|
|
G_CONNECT_SWAPPED); |
1269 |
|
|
|
1270 |
|
✗ |
g_object_bind_property (self->stack, "visible-child-name", |
1271 |
|
✗ |
self->title, "label", G_BINDING_SYNC_CREATE); |
1272 |
|
|
|
1273 |
|
✗ |
populate_prints_gallery (self); |
1274 |
|
✗ |
populate_enrollment_view (self); |
1275 |
|
✗ |
} |
1276 |
|
|
|
1277 |
|
|
static void |
1278 |
|
✗ |
select_device_row (CcFingerprintDialog *self, |
1279 |
|
|
GtkListBoxRow *row, |
1280 |
|
|
GtkListBox *listbox) |
1281 |
|
|
{ |
1282 |
|
✗ |
CcFprintdDevice *device = g_object_get_data (G_OBJECT (row), "device"); |
1283 |
|
|
|
1284 |
|
✗ |
g_return_if_fail (CC_FPRINTD_DEVICE (device)); |
1285 |
|
|
|
1286 |
|
✗ |
g_set_object (&self->device, device); |
1287 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->prints_manager); |
1288 |
|
|
} |
1289 |
|
|
|
1290 |
|
|
static void |
1291 |
|
✗ |
on_devices_list (GObject *object, |
1292 |
|
|
GAsyncResult *res, |
1293 |
|
|
gpointer user_data) |
1294 |
|
|
{ |
1295 |
|
✗ |
g_autolist (CcFprintdDevice) fprintd_devices = NULL; |
1296 |
|
✗ |
g_autoptr(DialogStateRemover) state_remover = NULL; |
1297 |
|
✗ |
g_autoptr(GError) error = NULL; |
1298 |
|
✗ |
CcFingerprintManager *fingerprint_manager = CC_FINGERPRINT_MANAGER (object); |
1299 |
|
✗ |
CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (user_data); |
1300 |
|
|
|
1301 |
|
✗ |
fprintd_devices = cc_fingerprint_manager_get_devices_finish (fingerprint_manager, |
1302 |
|
|
res, &error); |
1303 |
|
|
|
1304 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1305 |
|
✗ |
return; |
1306 |
|
|
|
1307 |
|
✗ |
state_remover = auto_state_remover (self, DIALOG_STATE_DEVICES_LISTING); |
1308 |
|
|
|
1309 |
|
✗ |
if (fprintd_devices == NULL) |
1310 |
|
|
{ |
1311 |
|
✗ |
if (error) |
1312 |
|
|
{ |
1313 |
|
✗ |
g_autofree char *error_message = NULL; |
1314 |
|
|
|
1315 |
|
✗ |
error_message = g_strdup_printf (_("Failed to get fingerprint devices: %s"), |
1316 |
|
|
dbus_error_to_human (self, error)); |
1317 |
|
✗ |
g_warning ("Retrieving fingerprint devices failed: %s", error->message); |
1318 |
|
✗ |
notify_error (self, error_message); |
1319 |
|
|
} |
1320 |
|
|
|
1321 |
|
✗ |
gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->no_devices_found)); |
1322 |
|
|
} |
1323 |
|
✗ |
else if (fprintd_devices->next == NULL) |
1324 |
|
|
{ |
1325 |
|
|
/* We have just one device... Skip devices selection */ |
1326 |
|
✗ |
self->device = g_object_ref (fprintd_devices->data); |
1327 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->prints_manager); |
1328 |
|
|
} |
1329 |
|
|
else |
1330 |
|
|
{ |
1331 |
|
|
GList *l; |
1332 |
|
|
|
1333 |
|
✗ |
for (l = fprintd_devices; l; l = l->next) |
1334 |
|
|
{ |
1335 |
|
✗ |
CcFprintdDevice *device = l->data; |
1336 |
|
|
CcListRow *device_row; |
1337 |
|
|
|
1338 |
|
✗ |
device_row = g_object_new (CC_TYPE_LIST_ROW, |
1339 |
|
|
"visible", TRUE, |
1340 |
|
|
"icon-name", "go-next-symbolic", |
1341 |
|
|
"title", cc_fprintd_device_get_name (device), |
1342 |
|
|
NULL); |
1343 |
|
|
|
1344 |
|
✗ |
gtk_list_box_insert (self->devices_list, GTK_WIDGET (device_row), -1); |
1345 |
|
✗ |
g_object_set_data_full (G_OBJECT (device_row), "device", |
1346 |
|
|
g_object_ref (device), g_object_unref); |
1347 |
|
|
} |
1348 |
|
|
|
1349 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->device_selector); |
1350 |
|
|
} |
1351 |
|
|
} |
1352 |
|
|
|
1353 |
|
|
static void |
1354 |
|
✗ |
cc_fingerprint_dialog_constructed (GObject *object) |
1355 |
|
|
{ |
1356 |
|
✗ |
CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (object); |
1357 |
|
|
|
1358 |
|
✗ |
bindtextdomain ("fprintd", GNOMELOCALEDIR); |
1359 |
|
✗ |
bind_textdomain_codeset ("fprintd", "UTF-8"); |
1360 |
|
|
|
1361 |
|
✗ |
add_dialog_state (self, DIALOG_STATE_DEVICES_LISTING); |
1362 |
|
✗ |
cc_fingerprint_manager_get_devices (self->manager, self->cancellable, |
1363 |
|
|
on_devices_list, self); |
1364 |
|
✗ |
} |
1365 |
|
|
|
1366 |
|
|
static void |
1367 |
|
✗ |
back_button_clicked_cb (CcFingerprintDialog *self) |
1368 |
|
|
{ |
1369 |
|
✗ |
if (gtk_stack_get_visible_child (self->stack) == self->prints_manager) |
1370 |
|
|
{ |
1371 |
|
✗ |
notify_error (self, NULL); |
1372 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->device_selector); |
1373 |
|
✗ |
return; |
1374 |
|
|
} |
1375 |
|
|
|
1376 |
|
✗ |
g_return_if_reached (); |
1377 |
|
|
} |
1378 |
|
|
|
1379 |
|
|
static void |
1380 |
|
✗ |
confirm_deletion_button_clicked_cb (CcFingerprintDialog *self) |
1381 |
|
|
{ |
1382 |
|
✗ |
gtk_widget_set_visible (self->delete_confirmation_infobar, FALSE); |
1383 |
|
✗ |
delete_enrolled_prints (self); |
1384 |
|
✗ |
} |
1385 |
|
|
|
1386 |
|
|
static void |
1387 |
|
✗ |
cancel_deletion_button_clicked_cb (CcFingerprintDialog *self) |
1388 |
|
|
{ |
1389 |
|
✗ |
gtk_widget_set_sensitive (self->prints_manager, TRUE); |
1390 |
|
✗ |
gtk_widget_set_visible (self->delete_confirmation_infobar, FALSE); |
1391 |
|
✗ |
} |
1392 |
|
|
|
1393 |
|
|
static void |
1394 |
|
✗ |
delete_prints_button_clicked_cb (CcFingerprintDialog *self) |
1395 |
|
|
{ |
1396 |
|
✗ |
gtk_widget_set_sensitive (self->prints_manager, FALSE); |
1397 |
|
✗ |
gtk_widget_set_visible (self->delete_confirmation_infobar, TRUE); |
1398 |
|
✗ |
} |
1399 |
|
|
|
1400 |
|
|
static void |
1401 |
|
✗ |
cancel_button_clicked_cb (CcFingerprintDialog *self) |
1402 |
|
|
{ |
1403 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING) |
1404 |
|
|
{ |
1405 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
1406 |
|
✗ |
g_set_object (&self->cancellable, g_cancellable_new ()); |
1407 |
|
|
|
1408 |
|
✗ |
g_debug ("Cancelling enroll operation"); |
1409 |
|
✗ |
enroll_stop (self); |
1410 |
|
|
} |
1411 |
|
|
else |
1412 |
|
|
{ |
1413 |
|
✗ |
gtk_stack_set_visible_child (self->stack, self->prints_manager); |
1414 |
|
|
} |
1415 |
|
✗ |
} |
1416 |
|
|
|
1417 |
|
|
static void |
1418 |
|
✗ |
done_button_clicked_cb (CcFingerprintDialog *self) |
1419 |
|
|
{ |
1420 |
|
✗ |
g_return_if_fail (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING); |
1421 |
|
|
|
1422 |
|
✗ |
g_debug ("Completing enroll operation"); |
1423 |
|
✗ |
enroll_stop (self); |
1424 |
|
|
} |
1425 |
|
|
|
1426 |
|
|
static gboolean |
1427 |
|
✗ |
cc_fingerprint_dialog_close_request (GtkWindow *window) |
1428 |
|
|
{ |
1429 |
|
✗ |
CcFingerprintDialog *self = CC_FINGERPRINT_DIALOG (window); |
1430 |
|
|
|
1431 |
|
✗ |
cc_fingerprint_manager_update_state (self->manager, NULL, NULL); |
1432 |
|
|
|
1433 |
|
✗ |
g_clear_handle_id (&self->enroll_stage_passed_id, g_source_remove); |
1434 |
|
|
|
1435 |
|
✗ |
if (self->device && (self->dialog_state & DIALOG_STATE_DEVICE_CLAIMED)) |
1436 |
|
|
{ |
1437 |
|
✗ |
disconnect_device_signals (self); |
1438 |
|
|
|
1439 |
|
✗ |
if (self->dialog_state & DIALOG_STATE_DEVICE_ENROLLING) |
1440 |
|
✗ |
cc_fprintd_device_call_enroll_stop_sync (self->device, NULL, NULL); |
1441 |
|
✗ |
cc_fprintd_device_call_release (self->device, NULL, NULL, NULL); |
1442 |
|
|
} |
1443 |
|
|
|
1444 |
|
✗ |
g_clear_object (&self->manager); |
1445 |
|
✗ |
g_clear_object (&self->device); |
1446 |
|
✗ |
g_clear_pointer (&self->enrolled_fingers, g_strfreev); |
1447 |
|
|
|
1448 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
1449 |
|
✗ |
g_clear_object (&self->cancellable); |
1450 |
|
|
|
1451 |
|
✗ |
return GTK_WINDOW_CLASS (cc_fingerprint_dialog_parent_class)->close_request (window); |
1452 |
|
|
} |
1453 |
|
|
|
1454 |
|
|
static void |
1455 |
|
✗ |
cc_fingerprint_dialog_class_init (CcFingerprintDialogClass *klass) |
1456 |
|
|
{ |
1457 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
1458 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
1459 |
|
✗ |
GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass); |
1460 |
|
|
|
1461 |
|
✗ |
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL); |
1462 |
|
|
|
1463 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, |
1464 |
|
|
"/org/gnome/control-center/system/users/cc-fingerprint-dialog.ui"); |
1465 |
|
|
|
1466 |
|
✗ |
object_class->constructed = cc_fingerprint_dialog_constructed; |
1467 |
|
✗ |
object_class->get_property = cc_fingerprint_dialog_get_property; |
1468 |
|
✗ |
object_class->set_property = cc_fingerprint_dialog_set_property; |
1469 |
|
|
|
1470 |
|
✗ |
window_class->close_request = cc_fingerprint_dialog_close_request; |
1471 |
|
|
|
1472 |
|
✗ |
properties[PROP_MANAGER] = |
1473 |
|
✗ |
g_param_spec_object ("fingerprint-manager", |
1474 |
|
|
"FingerprintManager", |
1475 |
|
|
"The CC fingerprint manager", |
1476 |
|
|
CC_TYPE_FINGERPRINT_MANAGER, |
1477 |
|
|
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); |
1478 |
|
|
|
1479 |
|
✗ |
g_object_class_install_properties (object_class, N_PROPS, properties); |
1480 |
|
|
|
1481 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, add_print_popover); |
1482 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, add_print_popover_box); |
1483 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, back_button); |
1484 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, cancel_button); |
1485 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, delete_confirmation_infobar); |
1486 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, delete_prints_button); |
1487 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, device_selector); |
1488 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, devices_list); |
1489 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, done_button); |
1490 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_message); |
1491 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_print_bin); |
1492 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enroll_print_entry); |
1493 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, enrollment_view); |
1494 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, error_infobar); |
1495 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, infobar_error); |
1496 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, no_devices_found); |
1497 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, prints_gallery); |
1498 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, prints_manager); |
1499 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, spinner); |
1500 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, stack); |
1501 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, title); |
1502 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcFingerprintDialog, titlebar); |
1503 |
|
|
|
1504 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, back_button_clicked_cb); |
1505 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb); |
1506 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, cancel_deletion_button_clicked_cb); |
1507 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, confirm_deletion_button_clicked_cb); |
1508 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, delete_prints_button_clicked_cb); |
1509 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, done_button_clicked_cb); |
1510 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_print_activated_cb); |
1511 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, select_device_row); |
1512 |
|
✗ |
} |
1513 |
|
|
|