diff --git a/js/ui/main.js b/js/ui/main.js index 2657678b7..2dc421b0b 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -195,6 +195,9 @@ function _initializeUI() { if (keybindingMode == Shell.KeyBindingMode.NONE) { keybindingMode = Shell.KeyBindingMode.NORMAL; } + if (screenShield) { + screenShield.lockIfWasLocked(); + } }); } diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 48cfaa604..185f109c7 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -30,6 +30,7 @@ const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; const LOCK_ENABLED_KEY = 'lock-enabled'; const LOCK_DELAY_KEY = 'lock-delay'; +const LOCKED_STATE_STR = 'screenShield.locked'; // fraction of screen height the arrow must reach before completing // the slide up automatically const ARROW_DRAG_THRESHOLD = 0.1; @@ -1175,6 +1176,7 @@ const ScreenShield = new Lang.Class({ this._isLocked = false; this.emit('active-changed'); this.emit('locked-changed'); + global.set_runtime_state(LOCKED_STATE_STR, null); }, activate: function(animate) { @@ -1191,6 +1193,7 @@ const ScreenShield = new Lang.Class({ } this._resetLockScreen(animate, animate); + global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true)); // We used to set isActive and emit active-changed here, // but now we do that from lockScreenShown, which means @@ -1217,5 +1220,15 @@ const ScreenShield = new Lang.Class({ this.emit('locked-changed'); }, + + // If the previous shell crashed, and gnome-session restarted us, then re-lock + lockIfWasLocked: function() { + let wasLocked = global.get_runtime_state('b', LOCKED_STATE_STR); + if (wasLocked === null) + return; + Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { + this.lock(false); + })); + } }); Signals.addSignalMethods(ScreenShield.prototype); diff --git a/src/shell-global.c b/src/shell-global.c index 9a594b7da..2f960484a 100644 --- a/src/shell-global.c +++ b/src/shell-global.c @@ -82,6 +82,8 @@ struct _ShellGlobal { const char *userdatadir; StFocusManager *focus_manager; + GFile *runtime_state_path; + guint work_count; GSList *leisure_closures; guint leisure_function_id; @@ -232,6 +234,8 @@ shell_global_init (ShellGlobal *global) const char *datadir = g_getenv ("GNOME_SHELL_DATADIR"); const char *shell_js = g_getenv("GNOME_SHELL_JS"); char *imagedir, **search_path; + char *path; + const char *byteorder_string; if (!datadir) datadir = GNOME_SHELL_DATADIR; @@ -254,6 +258,20 @@ shell_global_init (ShellGlobal *global) global->userdatadir = g_build_filename (g_get_user_data_dir (), "gnome-shell", NULL); g_mkdir_with_parents (global->userdatadir, 0700); +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + byteorder_string = "LE"; +#else + byteorder_string = "BE"; +#endif + + /* And the runtime state */ + path = g_strdup_printf ("%s/gnome-shell/runtime-state-%s.%s", + g_get_user_runtime_dir (), + byteorder_string, + XDisplayName (NULL)); + (void) g_mkdir_with_parents (path, 0700); + global->runtime_state_path = g_file_new_for_path (path); + global->settings = g_settings_new ("org.gnome.shell"); global->grab_notifier = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL)); @@ -295,6 +313,8 @@ shell_global_finalize (GObject *object) the_object = NULL; + g_clear_object (&global->runtime_state_path); + G_OBJECT_CLASS(shell_global_parent_class)->finalize (object); } @@ -1764,3 +1784,83 @@ shell_global_get_session_mode (ShellGlobal *global) return global->session_mode; } + +static GFile * +get_runtime_state_path (ShellGlobal *global, + const char *property_name) +{ + return g_file_get_child (global->runtime_state_path, property_name); +} + +/** + * shell_global_set_runtime_state: + * @global: a #ShellGlobal + * @property_name: Name of the property + * @variant: (allow-none): A #GVariant, or %NULL to unset + * + * Change the value of serialized runtime state. + */ +void +shell_global_set_runtime_state (ShellGlobal *global, + const char *property_name, + GVariant *variant) +{ + GFile *path; + + path = get_runtime_state_path (global, property_name); + + if (variant == NULL) + (void) g_file_delete (path, NULL, NULL); + else + { + gsize size = g_variant_get_size (variant); + g_file_replace_contents (path, g_variant_get_data (variant), size, + NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, + NULL, NULL, NULL); + } +} + +/** + * shell_global_get_runtime_state: + * @global: a #ShellGlobal + * @property_type: Expected data type + * @property_name: Name of the property + * + * The shell maintains "runtime" state which does not persist across + * logout or reboot. + * + * Returns: The value of a serialized property, or %NULL if none stored + */ +GVariant * +shell_global_get_runtime_state (ShellGlobal *global, + const char *property_type, + const char *property_name) +{ + GVariant *res = NULL; + GMappedFile *mfile; + GFile *path; + char *pathstr; + GError *local_error = NULL; + + path = get_runtime_state_path (global, property_name); + pathstr = g_file_get_path (path); + mfile = g_mapped_file_new (pathstr, FALSE, &local_error); + if (!mfile) + { + if (!g_error_matches (local_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + { + g_warning ("Failed to open runtime state: %s", local_error->message); + } + g_clear_error (&local_error); + } + else + { + GBytes *bytes = g_mapped_file_get_bytes (mfile); + res = g_variant_new_from_bytes ((GVariantType*)property_type, bytes, TRUE); + g_bytes_unref (bytes); + g_mapped_file_unref (mfile); + } + + out: + return res; +} diff --git a/src/shell-global.h b/src/shell-global.h index 69dff8554..38532b5ee 100644 --- a/src/shell-global.h +++ b/src/shell-global.h @@ -149,6 +149,14 @@ void shell_global_reexec_self (ShellGlobal *global); const char * shell_global_get_session_mode (ShellGlobal *global); +void shell_global_set_runtime_state (ShellGlobal *global, + const char *property_name, + GVariant *variant); +GVariant * shell_global_get_runtime_state (ShellGlobal *global, + const char *property_type, + const char *property_name); + + G_END_DECLS #endif /* __SHELL_GLOBAL_H__ */