1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /*
3 * Copyright (C) 2012 Red Hat
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * 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 * Written by:
19 * Jasper St. Pierre <jstpierre@mecheye.net>
20 */
21
22 #include "config.h"
23
24 #include "gnome-initial-setup.h"
25
26 #include <errno.h>
27 #include <locale.h>
28 #include <stdlib.h>
29 #include <webkit2/webkit2.h>
30
31 #include "cc-common-language.h"
32 #include "gis-assistant.h"
33
34 #define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
35
36 /* Statically include this for now. Maybe later
37 * we'll generate this from glib-mkenums. */
38 GType
gis_driver_mode_get_type(void)39 gis_driver_mode_get_type (void) {
40 static GType enum_type_id = 0;
41 if (G_UNLIKELY (!enum_type_id))
42 {
43 static const GEnumValue values[] = {
44 { GIS_DRIVER_MODE_NEW_USER, "GIS_DRIVER_MODE_NEW_USER", "new_user" },
45 { GIS_DRIVER_MODE_EXISTING_USER, "GIS_DRIVER_MODE_EXISTING_USER", "existing_user" },
46 { 0, NULL, NULL }
47 };
48 enum_type_id = g_enum_register_static("GisDriverMode", values);
49 }
50 return enum_type_id;
51 }
52
53 enum {
54 REBUILD_PAGES,
55 LOCALE_CHANGED,
56 LAST_SIGNAL,
57 };
58
59 static guint signals[LAST_SIGNAL];
60
61 typedef enum {
62 PROP_MODE = 1,
63 PROP_USERNAME,
64 PROP_SMALL_SCREEN,
65 PROP_PARENTAL_CONTROLS_ENABLED,
66 PROP_FULL_NAME,
67 PROP_AVATAR,
68 } GisDriverProperty;
69
70 static GParamSpec *obj_props[PROP_AVATAR + 1];
71
72 struct _GisDriver {
73 GtkApplication parent_instance;
74
75 GtkWindow *main_window;
76 GisAssistant *assistant;
77
78 GdmClient *client;
79 GdmGreeter *greeter;
80 GdmUserVerifier *user_verifier;
81
82 ActUser *user_account;
83 gchar *user_password;
84
85 ActUser *parent_account; /* (owned) (nullable) */
86 gchar *parent_password; /* (owned) (nullable) */
87
88 gboolean parental_controls_enabled;
89
90 gchar *lang_id;
91 gchar *username;
92 gchar *full_name; /* (owned) (nullable) */
93
94 GdkPixbuf *avatar; /* (owned) (nullable) */
95
96 GisDriverMode mode;
97 UmAccountMode account_mode;
98 gboolean small_screen;
99
100 locale_t locale;
101
102 const gchar *vendor_conf_file_path;
103 GKeyFile *vendor_conf_file;
104 };
105
G_DEFINE_TYPE(GisDriver,gis_driver,GTK_TYPE_APPLICATION)106 G_DEFINE_TYPE (GisDriver, gis_driver, GTK_TYPE_APPLICATION)
107
108 static void
109 gis_driver_dispose (GObject *object)
110 {
111 GisDriver *driver = GIS_DRIVER (object);
112
113 g_clear_object (&driver->user_verifier);
114 g_clear_object (&driver->greeter);
115 g_clear_object (&driver->client);
116
117 G_OBJECT_CLASS (gis_driver_parent_class)->dispose (object);
118 }
119
120 static void
gis_driver_finalize(GObject * object)121 gis_driver_finalize (GObject *object)
122 {
123 GisDriver *driver = GIS_DRIVER (object);
124
125 g_free (driver->lang_id);
126 g_free (driver->username);
127 g_free (driver->full_name);
128 g_free (driver->user_password);
129
130 g_clear_object (&driver->avatar);
131
132 g_clear_object (&driver->user_account);
133 g_clear_pointer (&driver->vendor_conf_file, g_key_file_free);
134
135 g_clear_object (&driver->parent_account);
136 g_free (driver->parent_password);
137
138 if (driver->locale != (locale_t) 0)
139 {
140 uselocale (LC_GLOBAL_LOCALE);
141 freelocale (driver->locale);
142 }
143
144 G_OBJECT_CLASS (gis_driver_parent_class)->finalize (object);
145 }
146
147 static void
assistant_page_changed(GtkScrolledWindow * sw)148 assistant_page_changed (GtkScrolledWindow *sw)
149 {
150 gtk_adjustment_set_value (gtk_scrolled_window_get_vadjustment (sw), 0);
151 }
152
153 static void
prepare_main_window(GisDriver * driver)154 prepare_main_window (GisDriver *driver)
155 {
156 GtkWidget *child, *sw;
157
158 child = g_object_ref (gtk_bin_get_child (GTK_BIN (driver->main_window)));
159 gtk_container_remove (GTK_CONTAINER (driver->main_window), child);
160 sw = gtk_scrolled_window_new (NULL, NULL);
161 gtk_widget_show (sw);
162 gtk_container_add (GTK_CONTAINER (driver->main_window), sw);
163 gtk_container_add (GTK_CONTAINER (sw), child);
164 g_object_unref (child);
165
166 g_signal_connect_swapped (driver->assistant,
167 "page-changed",
168 G_CALLBACK (assistant_page_changed),
169 sw);
170
171 gtk_window_set_titlebar (driver->main_window,
172 gis_assistant_get_titlebar (driver->assistant));
173 }
174
175 static void
rebuild_pages(GisDriver * driver)176 rebuild_pages (GisDriver *driver)
177 {
178 g_signal_emit (G_OBJECT (driver), signals[REBUILD_PAGES], 0);
179 }
180
181 GisAssistant *
gis_driver_get_assistant(GisDriver * driver)182 gis_driver_get_assistant (GisDriver *driver)
183 {
184 return driver->assistant;
185 }
186
187 static void
gis_driver_locale_changed(GisDriver * driver)188 gis_driver_locale_changed (GisDriver *driver)
189 {
190 GtkTextDirection direction;
191
192 direction = gtk_get_locale_direction ();
193 gtk_widget_set_default_direction (direction);
194
195 rebuild_pages (driver);
196 gis_assistant_locale_changed (driver->assistant);
197
198 g_signal_emit (G_OBJECT (driver), signals[LOCALE_CHANGED], 0);
199 }
200
201 void
gis_driver_set_user_language(GisDriver * driver,const gchar * lang_id,gboolean update_locale)202 gis_driver_set_user_language (GisDriver *driver, const gchar *lang_id, gboolean update_locale)
203 {
204 g_free (driver->lang_id);
205 driver->lang_id = g_strdup (lang_id);
206
207 cc_common_language_set_current_language (lang_id);
208
209 if (update_locale)
210 {
211 locale_t locale = newlocale (LC_MESSAGES_MASK, lang_id, (locale_t) 0);
212 if (locale == (locale_t) 0)
213 {
214 g_warning ("Failed to create locale %s: %s", lang_id, g_strerror (errno));
215 return;
216 }
217
218 uselocale (locale);
219
220 if (driver->locale != (locale_t) 0 && driver->locale != LC_GLOBAL_LOCALE)
221 freelocale (driver->locale);
222 driver->locale = locale;
223
224 gis_driver_locale_changed (driver);
225 }
226 }
227
228 const gchar *
gis_driver_get_user_language(GisDriver * driver)229 gis_driver_get_user_language (GisDriver *driver)
230 {
231 return driver->lang_id;
232 }
233
234 void
gis_driver_set_username(GisDriver * driver,const gchar * username)235 gis_driver_set_username (GisDriver *driver, const gchar *username)
236 {
237 g_free (driver->username);
238 driver->username = g_strdup (username);
239
240 g_object_notify (G_OBJECT (driver), "username");
241 }
242
243 const gchar *
gis_driver_get_username(GisDriver * driver)244 gis_driver_get_username (GisDriver *driver)
245 {
246 return driver->username;
247 }
248
249 /**
250 * gis_driver_set_full_name:
251 * @driver: a #GisDriver
252 * @full_name: (nullable): full name of the main user, or %NULL if not known
253 *
254 * Set the #GisDriver:full-name property.
255 *
256 * Since: 3.36
257 */
258 void
gis_driver_set_full_name(GisDriver * driver,const gchar * full_name)259 gis_driver_set_full_name (GisDriver *driver,
260 const gchar *full_name)
261 {
262 g_return_if_fail (GIS_IS_DRIVER (driver));
263 g_return_if_fail (full_name == NULL ||
264 g_utf8_validate (full_name, -1, NULL));
265
266 if (g_strcmp0 (driver->full_name, full_name) == 0)
267 return;
268
269 g_free (driver->full_name);
270 driver->full_name = g_strdup (full_name);
271
272 g_object_notify_by_pspec (G_OBJECT (driver), obj_props[PROP_FULL_NAME]);
273 }
274
275 /**
276 * gis_driver_get_full_name:
277 * @driver: a #GisDriver
278 *
279 * Get the #GisDriver:full-name property.
280 *
281 * Returns: (nullable): full name of the main user, or %NULL if not known
282 * Since: 3.36
283 */
284 const gchar *
gis_driver_get_full_name(GisDriver * driver)285 gis_driver_get_full_name (GisDriver *driver)
286 {
287 g_return_val_if_fail (GIS_IS_DRIVER (driver), NULL);
288
289 return driver->full_name;
290 }
291
292 /**
293 * gis_driver_set_avatar:
294 * @driver: a #GisDriver
295 * @avatar: (nullable) (transfer none): avatar of the main user, or %NULL if not known
296 *
297 * Set the #GisDriver:avatar property.
298 *
299 * Since: 3.36
300 */
301 void
gis_driver_set_avatar(GisDriver * driver,GdkPixbuf * avatar)302 gis_driver_set_avatar (GisDriver *driver,
303 GdkPixbuf *avatar)
304 {
305 g_return_if_fail (GIS_IS_DRIVER (driver));
306 g_return_if_fail (avatar == NULL || GDK_IS_PIXBUF (avatar));
307
308 if (g_set_object (&driver->avatar, avatar))
309 g_object_notify_by_pspec (G_OBJECT (driver), obj_props[PROP_AVATAR]);
310 }
311
312 /**
313 * gis_driver_get_avatar:
314 * @driver: a #GisDriver
315 *
316 * Get the #GisDriver:avatar property.
317 *
318 * Returns: (nullable) (transfer none): avatar of the main user, or %NULL if not known
319 * Since: 3.36
320 */
321 GdkPixbuf *
gis_driver_get_avatar(GisDriver * driver)322 gis_driver_get_avatar (GisDriver *driver)
323 {
324 g_return_val_if_fail (GIS_IS_DRIVER (driver), NULL);
325
326 return driver->avatar;
327 }
328
329 void
gis_driver_set_user_permissions(GisDriver * driver,ActUser * user,const gchar * password)330 gis_driver_set_user_permissions (GisDriver *driver,
331 ActUser *user,
332 const gchar *password)
333 {
334 g_set_object (&driver->user_account, user);
335 g_free (driver->user_password);
336 driver->user_password = g_strdup (password);
337 }
338
339 void
gis_driver_get_user_permissions(GisDriver * driver,ActUser ** user,const gchar ** password)340 gis_driver_get_user_permissions (GisDriver *driver,
341 ActUser **user,
342 const gchar **password)
343 {
344 if (user != NULL)
345 *user = driver->user_account;
346
347 if (password != NULL)
348 *password = driver->user_password;
349 }
350
351 /**
352 * gis_driver_set_parent_permissions:
353 * @driver: a #GisDriver
354 * @parent: (transfer none): user account for the parent
355 * @password: password for the parent
356 *
357 * Stores the parent account details for later use when saving the initial setup
358 * data.
359 *
360 * Since: 3.36
361 */
362 void
gis_driver_set_parent_permissions(GisDriver * driver,ActUser * parent,const gchar * password)363 gis_driver_set_parent_permissions (GisDriver *driver,
364 ActUser *parent,
365 const gchar *password)
366 {
367 g_set_object (&driver->parent_account, parent);
368 g_free (driver->parent_password);
369 driver->parent_password = g_strdup (password);
370 }
371
372 /**
373 * gis_driver_get_parent_permissions:
374 * @driver: a #GisDriver
375 * @parent: (out) (transfer none) (optional) (nullable): return location for the
376 * user account for the parent, which may be %NULL
377 * @password: (out) (transfer none) (optional) (nullable): return location for
378 * the password for the parent
379 *
380 * Gets the parent account details saved from an earlier step in the initial
381 * setup process. They may be %NULL if not set yet.
382 *
383 * Since: 3.36
384 */
385 void
gis_driver_get_parent_permissions(GisDriver * driver,ActUser ** parent,const gchar ** password)386 gis_driver_get_parent_permissions (GisDriver *driver,
387 ActUser **parent,
388 const gchar **password)
389 {
390 if (parent != NULL)
391 *parent = driver->parent_account;
392 if (password != NULL)
393 *password = driver->parent_password;
394 }
395
396 void
gis_driver_set_account_mode(GisDriver * driver,UmAccountMode mode)397 gis_driver_set_account_mode (GisDriver *driver,
398 UmAccountMode mode)
399 {
400 driver->account_mode = mode;
401 }
402
403 UmAccountMode
gis_driver_get_account_mode(GisDriver * driver)404 gis_driver_get_account_mode (GisDriver *driver)
405 {
406 return driver->account_mode;
407 }
408
409 /**
410 * gis_driver_set_parental_controls_enabled:
411 * @driver: a #GisDriver
412 * @parental_controls_enabled: whether parental controls are enabled for the main user
413 *
414 * Set the #GisDriver:parental-controls-enabled property.
415 *
416 * Since: 3.36
417 */
418 void
gis_driver_set_parental_controls_enabled(GisDriver * driver,gboolean parental_controls_enabled)419 gis_driver_set_parental_controls_enabled (GisDriver *driver,
420 gboolean parental_controls_enabled)
421 {
422 if (driver->parental_controls_enabled == parental_controls_enabled)
423 return;
424
425 driver->parental_controls_enabled = parental_controls_enabled;
426 rebuild_pages (driver);
427
428 g_object_notify_by_pspec (G_OBJECT (driver), obj_props[PROP_PARENTAL_CONTROLS_ENABLED]);
429 }
430
431 /**
432 * gis_driver_get_parental_controls_enabled:
433 * @driver: a #GisDriver
434 *
435 * Get the #GisDriver:parental-controls-enabled property.
436 *
437 * Returns: whether parental controls are enabled for the main user
438 * Since: 3.36
439 */
440 gboolean
gis_driver_get_parental_controls_enabled(GisDriver * driver)441 gis_driver_get_parental_controls_enabled (GisDriver *driver)
442 {
443 return driver->parental_controls_enabled;
444 }
445
446 gboolean
gis_driver_get_gdm_objects(GisDriver * driver,GdmGreeter ** greeter,GdmUserVerifier ** user_verifier)447 gis_driver_get_gdm_objects (GisDriver *driver,
448 GdmGreeter **greeter,
449 GdmUserVerifier **user_verifier)
450 {
451 if (driver->greeter == NULL || driver->user_verifier == NULL)
452 return FALSE;
453
454 *greeter = driver->greeter;
455 *user_verifier = driver->user_verifier;
456
457 return TRUE;
458 }
459
460 void
gis_driver_add_page(GisDriver * driver,GisPage * page)461 gis_driver_add_page (GisDriver *driver,
462 GisPage *page)
463 {
464 gis_assistant_add_page (driver->assistant, page);
465 }
466
467 void
gis_driver_hide_window(GisDriver * driver)468 gis_driver_hide_window (GisDriver *driver)
469 {
470 gtk_widget_hide (GTK_WIDGET (driver->main_window));
471 }
472
473 static gboolean
load_vendor_conf_file_at_path(GisDriver * driver,const char * path)474 load_vendor_conf_file_at_path (GisDriver *driver,
475 const char *path)
476 {
477 g_autoptr(GError) error = NULL;
478 g_autoptr(GKeyFile) vendor_conf_file = g_key_file_new ();
479
480 if (!g_key_file_load_from_file (vendor_conf_file, path, G_KEY_FILE_NONE, &error))
481 {
482 if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
483 g_warning ("Could not read file %s: %s:", path, error->message);
484 return FALSE;
485 }
486
487 driver->vendor_conf_file_path = path;
488 driver->vendor_conf_file = g_steal_pointer (&vendor_conf_file);
489 return TRUE;
490 }
491
492 static void
load_vendor_conf_file(GisDriver * driver)493 load_vendor_conf_file (GisDriver *driver)
494 {
495 #ifdef VENDOR_CONF_FILE
496 load_vendor_conf_file_at_path (driver, VENDOR_CONF_FILE);
497 #else
498 /* If no path was passed at build time, then we have search path:
499 *
500 * - First check $(sysconfdir)/gnome-initial-setup/vendor.conf
501 * - Then check $(datadir)/gnome-initial-setup/vendor.conf
502 *
503 * This allows distributions to provide a default packaged config in a
504 * location that might be managed by ostree, and allows OEMs to
505 * override using an unmanaged location.
506 */
507 if (!load_vendor_conf_file_at_path (driver, PKGSYSCONFDIR "/vendor.conf"))
508 load_vendor_conf_file_at_path (driver, PKGDATADIR "/vendor.conf");
509 #endif
510 }
511
512 static void
report_conf_error_if_needed(GisDriver * driver,const gchar * group,const gchar * key,const GError * error)513 report_conf_error_if_needed (GisDriver *driver,
514 const gchar *group,
515 const gchar *key,
516 const GError *error)
517 {
518 if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND) &&
519 !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
520 g_warning ("Error getting the value for key '%s' of group [%s] in %s: %s",
521 group, key, driver->vendor_conf_file_path, error->message);
522 }
523
524 gboolean
gis_driver_conf_get_boolean(GisDriver * driver,const gchar * group,const gchar * key,gboolean default_value)525 gis_driver_conf_get_boolean (GisDriver *driver,
526 const gchar *group,
527 const gchar *key,
528 gboolean default_value)
529 {
530 if (driver->vendor_conf_file) {
531 g_autoptr(GError) error = NULL;
532 gboolean new_value = g_key_file_get_boolean (driver->vendor_conf_file, group,
533 key, &error);
534 if (error == NULL)
535 return new_value;
536
537 report_conf_error_if_needed (driver, group, key, error);
538 }
539
540 return default_value;
541 }
542
543 GStrv
gis_driver_conf_get_string_list(GisDriver * driver,const gchar * group,const gchar * key,gsize * out_length)544 gis_driver_conf_get_string_list (GisDriver *driver,
545 const gchar *group,
546 const gchar *key,
547 gsize *out_length)
548 {
549 if (driver->vendor_conf_file) {
550 g_autoptr(GError) error = NULL;
551 GStrv new_value = g_key_file_get_string_list (driver->vendor_conf_file, group,
552 key, out_length, &error);
553 if (error == NULL)
554 return new_value;
555
556 report_conf_error_if_needed (driver, group, key, error);
557 }
558
559 return NULL;
560 }
561
562 gchar *
gis_driver_conf_get_string(GisDriver * driver,const gchar * group,const gchar * key)563 gis_driver_conf_get_string (GisDriver *driver,
564 const gchar *group,
565 const gchar *key)
566 {
567 if (driver->vendor_conf_file) {
568 g_autoptr(GError) error = NULL;
569 gchar *new_value = g_key_file_get_string (driver->vendor_conf_file, group,
570 key, &error);
571 if (error == NULL)
572 return new_value;
573
574 report_conf_error_if_needed (driver, group, key, error);
575 }
576
577 return NULL;
578 }
579
580 GisDriverMode
gis_driver_get_mode(GisDriver * driver)581 gis_driver_get_mode (GisDriver *driver)
582 {
583 return driver->mode;
584 }
585
586 gboolean
gis_driver_is_small_screen(GisDriver * driver)587 gis_driver_is_small_screen (GisDriver *driver)
588 {
589 return driver->small_screen;
590 }
591
592 static gboolean
monitor_is_small(GdkMonitor * monitor)593 monitor_is_small (GdkMonitor *monitor)
594 {
595 GdkRectangle geom;
596
597 if (g_getenv ("GIS_SMALL_SCREEN"))
598 return TRUE;
599
600 gdk_monitor_get_geometry (monitor, &geom);
601 return geom.height < 800;
602 }
603
604 static void
gis_driver_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)605 gis_driver_get_property (GObject *object,
606 guint prop_id,
607 GValue *value,
608 GParamSpec *pspec)
609 {
610 GisDriver *driver = GIS_DRIVER (object);
611
612 switch ((GisDriverProperty) prop_id)
613 {
614 case PROP_MODE:
615 g_value_set_enum (value, driver->mode);
616 break;
617 case PROP_USERNAME:
618 g_value_set_string (value, driver->username);
619 break;
620 case PROP_SMALL_SCREEN:
621 g_value_set_boolean (value, driver->small_screen);
622 break;
623 case PROP_PARENTAL_CONTROLS_ENABLED:
624 g_value_set_boolean (value, driver->parental_controls_enabled);
625 break;
626 case PROP_FULL_NAME:
627 g_value_set_string (value, driver->full_name);
628 break;
629 case PROP_AVATAR:
630 g_value_set_object (value, driver->avatar);
631 break;
632 default:
633 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
634 break;
635 }
636 }
637
638 static void
gis_driver_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)639 gis_driver_set_property (GObject *object,
640 guint prop_id,
641 const GValue *value,
642 GParamSpec *pspec)
643 {
644 GisDriver *driver = GIS_DRIVER (object);
645
646 switch ((GisDriverProperty) prop_id)
647 {
648 case PROP_MODE:
649 driver->mode = g_value_get_enum (value);
650 break;
651 case PROP_USERNAME:
652 g_free (driver->username);
653 driver->username = g_value_dup_string (value);
654 break;
655 case PROP_PARENTAL_CONTROLS_ENABLED:
656 gis_driver_set_parental_controls_enabled (driver, g_value_get_boolean (value));
657 break;
658 case PROP_FULL_NAME:
659 gis_driver_set_full_name (driver, g_value_get_string (value));
660 break;
661 case PROP_AVATAR:
662 gis_driver_set_avatar (driver, g_value_get_object (value));
663 break;
664 default:
665 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
666 break;
667 }
668 }
669
670 static void
gis_driver_activate(GApplication * app)671 gis_driver_activate (GApplication *app)
672 {
673 GisDriver *driver = GIS_DRIVER (app);
674
675 G_APPLICATION_CLASS (gis_driver_parent_class)->activate (app);
676
677 gtk_window_present (GTK_WINDOW (driver->main_window));
678 }
679
680 static void
set_small_screen_based_on_primary_monitor(GisDriver * driver)681 set_small_screen_based_on_primary_monitor (GisDriver *driver)
682 {
683 GdkDisplay *default_display;
684 GdkMonitor *primary_monitor;
685
686 default_display = gdk_display_get_default ();
687 if (default_display == NULL)
688 return;
689
690 primary_monitor = gdk_display_get_primary_monitor (default_display);
691 if (primary_monitor == NULL)
692 return;
693
694 driver->small_screen = monitor_is_small (primary_monitor);
695 }
696
697 /* Recompute driver->small_screen based on the monitor where the window is
698 * located, if the window is actually realized. If not, recompute it based on
699 * the primary monitor of the default display. */
700 static void
recompute_small_screen(GisDriver * driver)701 recompute_small_screen (GisDriver *driver) {
702 GdkWindow *window;
703 GdkDisplay *default_display = gdk_display_get_default ();
704 GdkMonitor *active_monitor;
705 gboolean old_value = driver->small_screen;
706
707 if (!gtk_widget_get_realized (GTK_WIDGET (driver->main_window)))
708 {
709 set_small_screen_based_on_primary_monitor (driver);
710 }
711 else
712 {
713 window = gtk_widget_get_window (GTK_WIDGET (driver->main_window));
714 active_monitor = gdk_display_get_monitor_at_window (default_display, window);
715 driver->small_screen = monitor_is_small (active_monitor);
716 }
717
718 if (driver->small_screen != old_value)
719 g_object_notify (G_OBJECT (driver), "small-screen");
720 }
721
722 static void
update_screen_size(GisDriver * driver)723 update_screen_size (GisDriver *driver)
724 {
725 GdkWindow *window;
726 GdkGeometry size_hints;
727 GtkWidget *sw;
728
729 recompute_small_screen (driver);
730
731 if (!gtk_widget_get_realized (GTK_WIDGET (driver->main_window)))
732 return;
733
734 sw = gtk_bin_get_child (GTK_BIN (driver->main_window));
735 window = gtk_widget_get_window (GTK_WIDGET (driver->main_window));
736
737 if (driver->small_screen)
738 {
739 if (window)
740 gdk_window_set_functions (window,
741 GDK_FUNC_ALL | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE);
742
743 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
744 GTK_POLICY_AUTOMATIC,
745 GTK_POLICY_AUTOMATIC);
746
747 gtk_window_set_geometry_hints (driver->main_window, NULL, NULL, 0);
748 gtk_window_set_resizable (driver->main_window, TRUE);
749 gtk_window_set_position (driver->main_window, GTK_WIN_POS_NONE);
750
751 gtk_window_maximize (driver->main_window);
752 gtk_window_present (driver->main_window);
753 }
754 else
755 {
756 if (window)
757 gdk_window_set_functions (window,
758 GDK_FUNC_ALL | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE |
759 GDK_FUNC_RESIZE | GDK_FUNC_MOVE | GDK_FUNC_MAXIMIZE);
760
761 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
762 GTK_POLICY_NEVER,
763 GTK_POLICY_NEVER);
764
765 size_hints.min_width = size_hints.max_width = 1024;
766 size_hints.min_height = size_hints.max_height = 768;
767 size_hints.win_gravity = GDK_GRAVITY_CENTER;
768
769 gtk_window_set_geometry_hints (driver->main_window,
770 NULL,
771 &size_hints,
772 GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_WIN_GRAVITY);
773 gtk_window_set_resizable (driver->main_window, FALSE);
774 gtk_window_set_position (driver->main_window, GTK_WIN_POS_CENTER_ALWAYS);
775
776 gtk_window_unmaximize (driver->main_window);
777 gtk_window_present (driver->main_window);
778 }
779 }
780
781 static void
screen_size_changed(GdkScreen * screen,GisDriver * driver)782 screen_size_changed (GdkScreen *screen, GisDriver *driver)
783 {
784 update_screen_size (driver);
785 }
786
787 static void
window_realize_cb(GtkWidget * widget,gpointer user_data)788 window_realize_cb (GtkWidget *widget, gpointer user_data)
789 {
790 update_screen_size (GIS_DRIVER (user_data));
791 }
792
793 static void
connect_to_gdm(GisDriver * driver)794 connect_to_gdm (GisDriver *driver)
795 {
796 g_autoptr(GError) error = NULL;
797
798 driver->client = gdm_client_new ();
799
800 driver->greeter = gdm_client_get_greeter_sync (driver->client, NULL, &error);
801 if (error == NULL)
802 driver->user_verifier = gdm_client_get_user_verifier_sync (driver->client, NULL, &error);
803
804 if (error != NULL) {
805 g_warning ("Failed to open connection to GDM: %s", error->message);
806 g_clear_object (&driver->user_verifier);
807 g_clear_object (&driver->greeter);
808 g_clear_object (&driver->client);
809 }
810 }
811
812 static void
gis_driver_startup(GApplication * app)813 gis_driver_startup (GApplication *app)
814 {
815 GisDriver *driver = GIS_DRIVER (app);
816 WebKitWebContext *context = webkit_web_context_get_default ();
817
818 G_APPLICATION_CLASS (gis_driver_parent_class)->startup (app);
819
820 webkit_web_context_set_sandbox_enabled (context, TRUE);
821
822 if (driver->mode == GIS_DRIVER_MODE_NEW_USER)
823 connect_to_gdm (driver);
824
825 driver->main_window = g_object_new (GTK_TYPE_APPLICATION_WINDOW,
826 "application", app,
827 "type", GTK_WINDOW_TOPLEVEL,
828 "icon-name", "preferences-system",
829 "deletable", FALSE,
830 NULL);
831
832 g_signal_connect (driver->main_window,
833 "realize",
834 G_CALLBACK (window_realize_cb),
835 (gpointer)app);
836
837 driver->assistant = g_object_new (GIS_TYPE_ASSISTANT, NULL);
838 gtk_container_add (GTK_CONTAINER (driver->main_window), GTK_WIDGET (driver->assistant));
839
840 gtk_widget_show (GTK_WIDGET (driver->assistant));
841
842 gis_driver_set_user_language (driver, setlocale (LC_MESSAGES, NULL), FALSE);
843
844 prepare_main_window (driver);
845 rebuild_pages (driver);
846 }
847
848 static void
gis_driver_init(GisDriver * driver)849 gis_driver_init (GisDriver *driver)
850 {
851 GdkScreen *screen;
852
853 screen = gdk_screen_get_default ();
854
855 set_small_screen_based_on_primary_monitor (driver);
856
857 load_vendor_conf_file (driver);
858
859 if (screen != NULL)
860 g_signal_connect (screen, "size-changed",
861 G_CALLBACK (screen_size_changed), driver);
862 }
863
864 static void
gis_driver_class_init(GisDriverClass * klass)865 gis_driver_class_init (GisDriverClass *klass)
866 {
867 GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
868 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
869
870 gobject_class->get_property = gis_driver_get_property;
871 gobject_class->set_property = gis_driver_set_property;
872 gobject_class->dispose = gis_driver_dispose;
873 gobject_class->finalize = gis_driver_finalize;
874 application_class->startup = gis_driver_startup;
875 application_class->activate = gis_driver_activate;
876
877 signals[REBUILD_PAGES] =
878 g_signal_new ("rebuild-pages",
879 G_TYPE_FROM_CLASS (klass),
880 G_SIGNAL_RUN_FIRST,
881 0,
882 NULL, NULL, NULL,
883 G_TYPE_NONE, 0);
884
885 signals[LOCALE_CHANGED] =
886 g_signal_new ("locale-changed",
887 G_TYPE_FROM_CLASS (klass),
888 G_SIGNAL_RUN_FIRST,
889 0,
890 NULL, NULL, NULL,
891 G_TYPE_NONE, 0);
892
893 obj_props[PROP_MODE] =
894 g_param_spec_enum ("mode", "", "",
895 GIS_TYPE_DRIVER_MODE,
896 GIS_DRIVER_MODE_EXISTING_USER,
897 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
898
899 obj_props[PROP_USERNAME] =
900 g_param_spec_string ("username", "", "",
901 NULL,
902 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
903
904 obj_props[PROP_SMALL_SCREEN] =
905 g_param_spec_boolean ("small-screen", "", "",
906 FALSE,
907 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
908
909 /**
910 * GisDriver:parental-controls-enabled:
911 *
912 * Whether parental controls are enabled for the main user. If this is %TRUE,
913 * two user accounts will be created when this page is saved: one for the main
914 * user (a child) which will be a standard account; and one for the parent
915 * which will be an administrative account.
916 *
917 * Since: 3.36
918 */
919 obj_props[PROP_PARENTAL_CONTROLS_ENABLED] =
920 g_param_spec_boolean ("parental-controls-enabled",
921 "Parental Controls Enabled",
922 "Whether parental controls are enabled for the main user.",
923 FALSE,
924 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
925
926 /**
927 * GisDriver:full-name: (nullable)
928 *
929 * Full name of the main user. May be %NULL if unknown or not set yet.
930 *
931 * Since: 3.36
932 */
933 obj_props[PROP_FULL_NAME] =
934 g_param_spec_string ("full-name",
935 "Full Name",
936 "Full name of the main user.",
937 NULL,
938 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
939
940 /**
941 * GisDriver:avatar: (nullable)
942 *
943 * Avatar of the main user. May be %NULL if unknown or not set yet.
944 *
945 * Since: 3.36
946 */
947 obj_props[PROP_AVATAR] =
948 g_param_spec_object ("avatar",
949 "Avatar",
950 "Avatar of the main user.",
951 GDK_TYPE_PIXBUF,
952 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
953
954 g_object_class_install_properties (gobject_class, G_N_ELEMENTS (obj_props), obj_props);
955 }
956
957 gboolean
gis_driver_save_data(GisDriver * driver,GError ** error)958 gis_driver_save_data (GisDriver *driver,
959 GError **error)
960 {
961 if (gis_get_mock_mode ())
962 {
963 g_message ("%s: Skipping saving data due to being in mock mode", G_STRFUNC);
964 return TRUE;
965 }
966
967 return gis_assistant_save_data (driver->assistant, error);
968 }
969
970 GisDriver *
gis_driver_new(GisDriverMode mode)971 gis_driver_new (GisDriverMode mode)
972 {
973 return g_object_new (GIS_TYPE_DRIVER,
974 "application-id", "org.gnome.InitialSetup",
975 "mode", mode,
976 NULL);
977 }
978