[gnome-shell] Add a confirmation dialog for display changes



commit 02224bb5fe14baaed46853587dec88a64107a1a6
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sat Aug 17 17:42:39 2013 +0200

    Add a confirmation dialog for display changes
    
    Unfortunately, display configuration can and does fail, due
    to unspecified HW constraints, drivers bugs, unsupported exotic
    configurations or just bad luck.
    So when the user makes a change in the control center, show
    a dialog asking him if it looks OK, and revert back after 20 seconds
    otherwise.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706208

 js/ui/windowManager.js   |  109 ++++++++++++++++++++++++++++++++++++++++++++++
 src/gnome-shell-plugin.c |   12 +++++
 src/shell-wm-private.h   |    2 +
 src/shell-wm.c           |   28 ++++++++++++
 src/shell-wm.h           |    3 +
 5 files changed, 154 insertions(+), 0 deletions(-)
---
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
index d6b0b7a..96270a4 100644
--- a/js/ui/windowManager.js
+++ b/js/ui/windowManager.js
@@ -6,12 +6,14 @@ const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 
 const AltTab = imports.ui.altTab;
 const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
 const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
 const Tweener = imports.ui.tweener;
 
 const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@@ -20,6 +22,107 @@ const DIM_BRIGHTNESS = -0.3;
 const DIM_TIME = 0.500;
 const UNDIM_TIME = 0.250;
 
+const DISPLAY_REVERT_TIMEOUT = 20; // in seconds - keep in sync with mutter
+const ONE_SECOND = 1000; // in ms
+
+const DisplayChangeDialog = new Lang.Class({
+    Name: 'DisplayChangeDialog',
+    Extends: ModalDialog.ModalDialog,
+
+    _init: function(wm) {
+        this.parent({ styleClass: 'prompt-dialog' });
+
+        this._wm = wm;
+
+        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
+                                                vertical: false });
+        this.contentLayout.add(mainContentBox,
+                               { x_fill: true,
+                                 y_fill: true });
+
+        let icon = new St.Icon({ icon_name: 'preferences-desktop-display-symbolic' });
+        mainContentBox.add(icon,
+                           { x_fill:  true,
+                             y_fill:  false,
+                             x_align: St.Align.END,
+                             y_align: St.Align.START });
+
+        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
+                                            vertical: true });
+        mainContentBox.add(messageBox,
+                           { expand: true, y_align: St.Align.START });
+
+        let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
+                                            text: _("Do you want to keep these display settings?") });
+        messageBox.add(subjectLabel,
+                       { y_fill:  false,
+                         y_align: St.Align.START });
+
+        this._countDown = DISPLAY_REVERT_TIMEOUT;
+        let message = this._formatCountDown();
+        this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
+                                                text: this._formatCountDown() });
+        this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
+        this._descriptionLabel.clutter_text.line_wrap = true;
+
+        messageBox.add(this._descriptionLabel,
+                       { y_fill:  true,
+                         y_align: St.Align.START });
+
+        /* Translators: this and the following message should be limited in lenght,
+           to avoid ellipsizing the labels.
+        */
+        this._cancelButton = this.addButton({ label: _("Revert Settings"),
+                                              action: Lang.bind(this, this._onFailure),
+                                              key: Clutter.Escape },
+                                            { expand: true, x_fill: false, x_align: St.Align.START });
+        this._okButton = this.addButton({ label:  _("Keep Changes"),
+                                          action: Lang.bind(this, this._onSuccess),
+                                          default: true },
+                                        { expand: false, x_fill: false, x_align: St.Align.END });
+
+        this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick));
+    },
+
+    close: function(timestamp) {
+        if (this._timeoutId > 0) {
+            Mainloop.source_remove(this._timeoutId);
+            this._timeoutId = 0;
+        }
+
+        this.parent(timestamp);
+    },
+
+    _formatCountDown: function() {
+        let fmt = ngettext("Settings changes will revert in %d second",
+                           "Settings changes will revert in %d seconds");
+        return fmt.format(this._countDown);
+    },
+
+    _tick: function() {
+        this._countDown--;
+
+        if (this._countDown == 0) {
+            /* mutter already takes care of failing at timeout */
+            this._timeoutId = 0;
+            this.close();
+            return false;
+        }
+
+        this._descriptionLabel.text = this._formatCountDown();
+        return true;
+    },
+
+    _onFailure: function() {
+        this._wm.complete_display_change(false);
+        this.close();
+    },
+
+    _onSuccess: function() {
+        this._wm.complete_display_change(true);
+        this.close();
+    },
+});
 
 const WindowDimmer = new Lang.Class({
     Name: 'WindowDimmer',
@@ -306,6 +409,7 @@ const WindowManager = new Lang.Class({
         this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
         this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
         this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
+        this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
 
         this._workspaceSwitcherPopup = null;
         this.setCustomKeybindingHandler('switch-to-workspace-left',
@@ -1056,4 +1160,9 @@ const WindowManager = new Lang.Class({
             workspace.activate_with_focus (window, global.get_current_time());
         }
     },
+
+    _confirmDisplayChange: function() {
+        let dialog = new DisplayChangeDialog(this._shellwm);
+        dialog.open();
+    },
 });
diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c
index 3470637..6571b39 100644
--- a/src/gnome-shell-plugin.c
+++ b/src/gnome-shell-plugin.c
@@ -75,6 +75,9 @@ static gboolean              gnome_shell_plugin_xevent_filter (MetaPlugin *plugi
 
 static gboolean              gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
                                                                    MetaKeyBinding *binding);
+
+static void gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin);
+
 static const MetaPluginInfo *gnome_shell_plugin_plugin_info   (MetaPlugin *plugin);
 
 
@@ -132,6 +135,9 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
 
   plugin_class->xevent_filter     = gnome_shell_plugin_xevent_filter;
   plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
+
+  plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
+
   plugin_class->plugin_info       = gnome_shell_plugin_plugin_info;
 }
 
@@ -399,6 +405,12 @@ gnome_shell_plugin_keybinding_filter (MetaPlugin     *plugin,
   return _shell_wm_filter_keybinding (get_shell_wm (), binding);
 }
 
+static void
+gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin)
+{
+  _shell_wm_confirm_display_change (get_shell_wm ());
+}
+
 static const
 MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
 {
diff --git a/src/shell-wm-private.h b/src/shell-wm-private.h
index 6fc9348..bc9d4c3 100644
--- a/src/shell-wm-private.h
+++ b/src/shell-wm-private.h
@@ -38,6 +38,8 @@ void _shell_wm_kill_switch_workspace (ShellWM             *wm);
 gboolean _shell_wm_filter_keybinding (ShellWM             *wm,
                                       MetaKeyBinding      *binding);
 
+void _shell_wm_confirm_display_change (ShellWM            *wm);
+
 G_END_DECLS
 
 #endif /* __SHELL_WM_PRIVATE_H__ */
diff --git a/src/shell-wm.c b/src/shell-wm.c
index 08aceb7..20f101e 100644
--- a/src/shell-wm.c
+++ b/src/shell-wm.c
@@ -27,6 +27,7 @@ enum
   KILL_SWITCH_WORKSPACE,
   KILL_WINDOW_EFFECTS,
   FILTER_KEYBINDING,
+  CONFIRM_DISPLAY_CHANGE,
 
   LAST_SIGNAL
 };
@@ -124,6 +125,13 @@ shell_wm_class_init (ShellWMClass *klass)
                   g_signal_accumulator_true_handled, NULL, NULL,
                   G_TYPE_BOOLEAN, 1,
                   META_TYPE_KEY_BINDING);
+  shell_wm_signals[CONFIRM_DISPLAY_CHANGE] =
+    g_signal_new ("confirm-display-change",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
 }
 
 void
@@ -219,6 +227,20 @@ shell_wm_completed_destroy (ShellWM         *wm,
   meta_plugin_destroy_completed (wm->plugin, actor);
 }
 
+/**
+ * shell_wm_complete_display_change:
+ * @wm: the ShellWM
+ * @ok: if the new configuration was OK
+ *
+ * The plugin must call this after the user responded to the confirmation dialog.
+ */
+void
+shell_wm_complete_display_change (ShellWM  *wm,
+                                  gboolean  ok)
+{
+  meta_plugin_complete_display_change (wm->plugin, ok);
+}
+
 void
 _shell_wm_kill_switch_workspace (ShellWM      *wm)
 {
@@ -287,6 +309,12 @@ _shell_wm_filter_keybinding (ShellWM             *wm,
   return rv;
 }
 
+void
+_shell_wm_confirm_display_change (ShellWM *wm)
+{
+  g_signal_emit (wm, shell_wm_signals[CONFIRM_DISPLAY_CHANGE], 0);
+}
+
 /**
  * shell_wm_new:
  * @plugin: the #MetaPlugin
diff --git a/src/shell-wm.h b/src/shell-wm.h
index 20b740a..778af52 100644
--- a/src/shell-wm.h
+++ b/src/shell-wm.h
@@ -39,6 +39,9 @@ void     shell_wm_completed_destroy          (ShellWM         *wm,
                                               MetaWindowActor *actor);
 void     shell_wm_completed_switch_workspace (ShellWM         *wm);
 
+void     shell_wm_complete_display_change    (ShellWM         *wm,
+                                              gboolean         ok);
+
 G_END_DECLS
 
 #endif /* __SHELL_WM_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]