diff --git a/src/compositor/meta-plugin-manager.c b/src/compositor/meta-plugin-manager.c index 2ae100e84..fa9fe96e3 100644 --- a/src/compositor/meta-plugin-manager.c +++ b/src/compositor/meta-plugin-manager.c @@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar *plugin_name) g_free (path); } +static void +on_confirm_display_change (MetaMonitorManager *monitors, + MetaPluginManager *plugin_mgr) +{ + meta_plugin_manager_confirm_display_change (plugin_mgr); +} + MetaPluginManager * meta_plugin_manager_new (MetaScreen *screen) { MetaPluginManager *plugin_mgr; MetaPluginClass *klass; MetaPlugin *plugin; + MetaMonitorManager *monitors; plugin_mgr = g_new0 (MetaPluginManager, 1); plugin_mgr->screen = screen; @@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen) if (klass->start) klass->start (plugin); + monitors = meta_monitor_manager_get (); + g_signal_connect (monitors, "confirm-display-change", + G_CALLBACK (on_confirm_display_change), plugin_mgr); + return plugin_mgr; } @@ -330,3 +342,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr, return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; } + +void +meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr) +{ + MetaPlugin *plugin = plugin_mgr->plugin; + MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); + + if (klass->confirm_display_change) + return klass->confirm_display_change (plugin); + else + return meta_plugin_complete_display_change (plugin, TRUE); +} diff --git a/src/compositor/meta-plugin-manager.h b/src/compositor/meta-plugin-manager.h index 9df24c17a..215d450a5 100644 --- a/src/compositor/meta-plugin-manager.h +++ b/src/compositor/meta-plugin-manager.h @@ -73,4 +73,6 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr, gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr, XEvent *xev); +void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr); + #endif diff --git a/src/compositor/meta-plugin.c b/src/compositor/meta-plugin.c index a7ee1137b..daf582435 100644 --- a/src/compositor/meta-plugin.c +++ b/src/compositor/meta-plugin.c @@ -41,6 +41,7 @@ #include "compositor-private.h" #include "meta-window-actor-private.h" +#include "monitor-private.h" G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT); @@ -338,3 +339,13 @@ meta_plugin_get_screen (MetaPlugin *plugin) return priv->screen; } + +void +meta_plugin_complete_display_change (MetaPlugin *plugin, + gboolean ok) +{ + MetaMonitorManager *manager; + + manager = meta_monitor_manager_get (); + meta_monitor_manager_confirm_configuration (manager, ok); +} diff --git a/src/compositor/plugins/default.c b/src/compositor/plugins/default.c index b125e3ae8..6177f01da 100644 --- a/src/compositor/plugins/default.c +++ b/src/compositor/plugins/default.c @@ -101,6 +101,8 @@ static void kill_window_effects (MetaPlugin *plugin, MetaWindowActor *actor); static void kill_switch_workspace (MetaPlugin *plugin); +static void confirm_display_change (MetaPlugin *plugin); + static const MetaPluginInfo * plugin_info (MetaPlugin *plugin); META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin); @@ -208,6 +210,7 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass) plugin_class->plugin_info = plugin_info; plugin_class->kill_window_effects = kill_window_effects; plugin_class->kill_switch_workspace = kill_switch_workspace; + plugin_class->confirm_display_change = confirm_display_change; g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate)); } @@ -836,3 +839,33 @@ plugin_info (MetaPlugin *plugin) return &priv->info; } + +static void +on_dialog_closed (GPid pid, + gint status, + gpointer user_data) +{ + MetaPlugin *plugin = user_data; + gboolean ok; + + ok = g_spawn_check_exit_status (status, NULL); + meta_plugin_complete_display_change (plugin, ok); +} + +static void +confirm_display_change (MetaPlugin *plugin) +{ + GPid pid; + + pid = meta_show_dialog ("--question", + "Does the display look OK?", + "20", + NULL, + "_Keep This Configuration", + "_Restore Previous Configuration", + "preferences-desktop-display", + 0, + NULL, NULL); + + g_child_watch_add (pid, on_dialog_closed, plugin); +} diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index 03530c9f1..e25868c89 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -243,6 +243,9 @@ void meta_monitor_manager_apply_configuration (MetaMonitorManager MetaOutputInfo **outputs, unsigned int n_outputs); +void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, + gboolean ok); + #define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ()) #define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig)) #define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass)) diff --git a/src/core/monitor.c b/src/core/monitor.c index edeadae9a..01d517eef 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -116,6 +116,7 @@ struct _MetaMonitorManagerClass enum { MONITORS_CHANGED, + CONFIRM_DISPLAY_CHANGE, SIGNALS_LAST }; @@ -1108,6 +1109,14 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + signals[CONFIRM_DISPLAY_CHANGE] = + g_signal_new ("confirm-display-change", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode"); } @@ -1563,8 +1572,9 @@ save_config_timeout (gpointer user_data) { MetaMonitorManager *manager = user_data; - meta_monitor_config_make_persistent (manager->config); + meta_monitor_config_restore_previous (manager->config, manager); + manager->persistent_timeout_id = 0; return G_SOURCE_REMOVE; } @@ -1753,7 +1763,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto /* If we were in progress of making a persistent change and we see a new request, it's likely that the old one failed in some way, so - don't save it. + don't save it, but also don't queue for restoring it. */ if (manager->persistent_timeout_id && persistent) { @@ -1771,17 +1781,41 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto g_ptr_array_unref (output_infos); /* Update MetaMonitorConfig data structures immediately so that we - don't revert the change at the next XRandR event, then wait 20 - seconds and save the change to disk + don't revert the change at the next XRandR event, then ask the plugin + manager (through MetaScreen) to confirm the display change with the + appropriate UI. Then wait 20 seconds and if not confirmed, revert the + configuration. */ meta_monitor_config_update_current (manager->config, manager); if (persistent) - manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager); + { + manager->persistent_timeout_id = g_timeout_add_seconds (20, save_config_timeout, manager); + g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0); + } meta_dbus_display_config_complete_apply_configuration (skeleton, invocation); return TRUE; } +void +meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, + gboolean ok) +{ + if (!manager->persistent_timeout_id) + { + /* too late */ + return; + } + + g_source_remove (manager->persistent_timeout_id); + manager->persistent_timeout_id = 0; + + if (ok) + meta_monitor_config_make_persistent (manager->config); + else + meta_monitor_config_restore_previous (manager->config, manager); +} + #ifdef HAVE_RANDR static void handle_change_backlight_xrandr (MetaMonitorManager *manager, diff --git a/src/core/util.c b/src/core/util.c index c2af3b689..d5014607b 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -652,8 +652,13 @@ meta_show_dialog (const char *type, append_argument (args, "zenity"); append_argument (args, type); - append_argument (args, "--display"); - append_argument (args, display); + + if (display) + { + append_argument (args, "--display"); + append_argument (args, display); + } + append_argument (args, "--class"); append_argument (args, "mutter-dialog"); append_argument (args, "--title"); diff --git a/src/meta/meta-plugin.h b/src/meta/meta-plugin.h index 3ea3435b1..d2643c2a9 100644 --- a/src/meta/meta-plugin.h +++ b/src/meta/meta-plugin.h @@ -205,6 +205,21 @@ struct _MetaPluginClass gboolean (*keybinding_filter) (MetaPlugin *plugin, MetaKeyBinding *binding); + /** + * MetaPluginClass::confirm_display_config: + * @plugin: a #MetaPlugin + * + * Virtual function called when the display configuration changes. + * The common way to implement this function is to show some form + * of modal dialog that should ask the user if everything was ok. + * + * When confirmed by the user, the plugin must call meta_plugin_complete_display_change() + * to make the configuration permanent. If that function is not + * called within the timeout, the previous configuration will be + * reapplied. + */ + void (*confirm_display_change) (MetaPlugin *plugin); + /** * MetaPluginClass::plugin_info: * @plugin: a #MetaPlugin @@ -214,6 +229,7 @@ struct _MetaPluginClass * Returns: a #MetaPluginInfo. */ const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin); + }; /** @@ -360,6 +376,10 @@ void meta_plugin_destroy_completed (MetaPlugin *plugin, MetaWindowActor *actor); +void +meta_plugin_complete_display_change (MetaPlugin *plugin, + gboolean ok); + /** * MetaModalOptions: * @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already