MetaPlugin: add a UI hook for confirming display changes

We want to show a dialog when a display change happens from the
control center. To do so, add a new vfunc to MetaPlugin and
call it when a configuration change is requested via DBus.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
This commit is contained in:
Giovanni Campagna 2013-07-29 10:12:24 +02:00 committed by Giovanni Campagna
parent 028fa6cd4e
commit 1a0513ea61
8 changed files with 139 additions and 7 deletions

View File

@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar *plugin_name)
g_free (path); g_free (path);
} }
static void
on_confirm_display_change (MetaMonitorManager *monitors,
MetaPluginManager *plugin_mgr)
{
meta_plugin_manager_confirm_display_change (plugin_mgr);
}
MetaPluginManager * MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen) meta_plugin_manager_new (MetaScreen *screen)
{ {
MetaPluginManager *plugin_mgr; MetaPluginManager *plugin_mgr;
MetaPluginClass *klass; MetaPluginClass *klass;
MetaPlugin *plugin; MetaPlugin *plugin;
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1); plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen; plugin_mgr->screen = screen;
@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen)
if (klass->start) if (klass->start)
klass->start (plugin); 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; return plugin_mgr;
} }
@ -320,3 +332,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
else else
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; 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);
}

View File

@ -73,4 +73,6 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr, gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
XEvent *xev); XEvent *xev);
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
#endif #endif

View File

@ -41,6 +41,7 @@
#include "compositor-private.h" #include "compositor-private.h"
#include "meta-window-actor-private.h" #include "meta-window-actor-private.h"
#include "monitor-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT); G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
@ -338,3 +339,13 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen; 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);
}

View File

@ -100,6 +100,8 @@ static void kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *actor); MetaWindowActor *actor);
static void kill_switch_workspace (MetaPlugin *plugin); static void kill_switch_workspace (MetaPlugin *plugin);
static void confirm_display_change (MetaPlugin *plugin);
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin); static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin); META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
@ -207,6 +209,7 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
plugin_class->plugin_info = plugin_info; plugin_class->plugin_info = plugin_info;
plugin_class->kill_window_effects = kill_window_effects; plugin_class->kill_window_effects = kill_window_effects;
plugin_class->kill_switch_workspace = kill_switch_workspace; 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)); g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
} }
@ -835,3 +838,33 @@ plugin_info (MetaPlugin *plugin)
return &priv->info; 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);
}

View File

@ -242,6 +242,9 @@ void meta_monitor_manager_apply_configuration (MetaMonitorManager
MetaOutputInfo **outputs, MetaOutputInfo **outputs,
unsigned int n_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_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(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)) #define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))

View File

@ -114,6 +114,7 @@ struct _MetaMonitorManagerClass
enum { enum {
MONITORS_CHANGED, MONITORS_CHANGED,
CONFIRM_DISPLAY_CHANGE,
SIGNALS_LAST SIGNALS_LAST
}; };
@ -1095,6 +1096,14 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
NULL, NULL, NULL, NULL, NULL, NULL,
G_TYPE_NONE, 0); 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"); g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
} }
@ -1562,8 +1571,9 @@ save_config_timeout (gpointer user_data)
{ {
MetaMonitorManager *manager = 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; return G_SOURCE_REMOVE;
} }
@ -1766,7 +1776,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
/* If we were in progress of making a persistent change and we see a /* 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 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) if (manager->persistent_timeout_id && persistent)
{ {
@ -1784,17 +1794,41 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
g_ptr_array_unref (output_infos); g_ptr_array_unref (output_infos);
/* Update MetaMonitorConfig data structures immediately so that we /* Update MetaMonitorConfig data structures immediately so that we
don't revert the change at the next XRandR event, then wait 20 don't revert the change at the next XRandR event, then ask the plugin
seconds and save the change to disk 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); meta_monitor_config_update_current (manager->config, manager);
if (persistent) 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); meta_dbus_display_config_complete_apply_configuration (skeleton, invocation);
return TRUE; 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 #ifdef HAVE_RANDR
static void static void
handle_change_backlight_xrandr (MetaMonitorManager *manager, handle_change_backlight_xrandr (MetaMonitorManager *manager,

View File

@ -647,8 +647,13 @@ meta_show_dialog (const char *type,
append_argument (args, "zenity"); append_argument (args, "zenity");
append_argument (args, type); 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, "--class");
append_argument (args, "mutter-dialog"); append_argument (args, "mutter-dialog");
append_argument (args, "--title"); append_argument (args, "--title");

View File

@ -205,6 +205,21 @@ struct _MetaPluginClass
gboolean (*keybinding_filter) (MetaPlugin *plugin, gboolean (*keybinding_filter) (MetaPlugin *plugin,
MetaKeyBinding *binding); 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: * MetaPluginClass::plugin_info:
* @plugin: a #MetaPlugin * @plugin: a #MetaPlugin
@ -214,6 +229,7 @@ struct _MetaPluginClass
* Returns: a #MetaPluginInfo. * Returns: a #MetaPluginInfo.
*/ */
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin); const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
}; };
/** /**
@ -360,6 +376,10 @@ void
meta_plugin_destroy_completed (MetaPlugin *plugin, meta_plugin_destroy_completed (MetaPlugin *plugin,
MetaWindowActor *actor); MetaWindowActor *actor);
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok);
/** /**
* MetaModalOptions: * MetaModalOptions:
* @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already * @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already