From 15da8fa99012875735ffa3a1eb54670b6d42bea4 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sun, 27 Nov 2011 12:37:54 -0600 Subject: Add e_restore_window(). Replaces gconf_bridge_bind_window(). Requires a GSettings path to a "org.gnome.evolution.window" schema. --- e-util/e-util.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ e-util/e-util.h | 8 ++ 2 files changed, 233 insertions(+) (limited to 'e-util') diff --git a/e-util/e-util.c b/e-util/e-util.c index 0db804a618..bc163377fb 100644 --- a/e-util/e-util.c +++ b/e-util/e-util.c @@ -60,6 +60,137 @@ #include "e-util.h" #include "e-util-private.h" +typedef struct _WindowData WindowData; + +struct _WindowData { + GtkWindow *window; + GSettings *settings; + ERestoreWindowFlags flags; + gint premax_width; + gint premax_height; + guint timeout_id; +}; + +static void +window_data_free (WindowData *data) +{ + if (data->window != NULL) + g_object_unref (data->window); + + if (data->settings != NULL) + g_object_unref (data->settings); + + if (data->timeout_id > 0) + g_source_remove (data->timeout_id); + + g_slice_free (WindowData, data); +} + +static gboolean +window_update_settings (WindowData *data) +{ + GSettings *settings = data->settings; + + if (data->flags & E_RESTORE_WINDOW_SIZE) { + GdkWindowState state; + GdkWindow *window; + gboolean maximized; + + window = gtk_widget_get_window (GTK_WIDGET (data->window)); + state = gdk_window_get_state (window); + maximized = ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0); + + g_settings_set_boolean (settings, "maximized", maximized); + + if (!maximized) { + gint width, height; + + gtk_window_get_size (data->window, &width, &height); + + g_settings_set_int (settings, "width", width); + g_settings_set_int (settings, "height", height); + } + } + + if (data->flags & E_RESTORE_WINDOW_POSITION) { + gint x, y; + + gtk_window_get_position (data->window, &x, &y); + + g_settings_set_int (settings, "x", x); + g_settings_set_int (settings, "y", y); + } + + data->timeout_id = 0; + + return FALSE; +} + +static gboolean +window_configure_event_cb (GtkWindow *window, + GdkEventConfigure *event, + WindowData *data) +{ + if (data->timeout_id > 0) + g_source_remove (data->timeout_id); + + data->timeout_id = gdk_threads_add_timeout_seconds ( + 1, (GSourceFunc) window_update_settings, data); + + return FALSE; +} + +static gboolean +window_state_event_cb (GtkWindow *window, + GdkEventWindowState *event, + WindowData *data) +{ + gboolean window_was_unmaximized; + + if (data->timeout_id > 0) + g_source_remove (data->timeout_id); + + window_was_unmaximized = + ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0) && + ((event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0); + + if (window_was_unmaximized) { + gint width, height; + + width = data->premax_width; + data->premax_width = 0; + + height = data->premax_height; + data->premax_height = 0; + + /* This only applies when the window is initially restored + * as maximized and is then unmaximized. GTK+ handles the + * unmaximized window size thereafter. */ + if (width > 0 && height > 0) + gtk_window_resize (window, width, height); + } + + window_update_settings (data); + + return FALSE; +} + +static gboolean +window_unmap_cb (GtkWindow *window, + WindowData *data) +{ + if (data->timeout_id > 0) + g_source_remove (data->timeout_id); + + /* It's too late to record the window position. + * gtk_window_get_position() will report (0, 0). */ + data->flags &= ~E_RESTORE_WINDOW_POSITION; + + window_update_settings (data); + + return FALSE; +} + /** * e_get_accels_filename: * @@ -175,6 +306,100 @@ exit: g_string_free (uri, TRUE); } +/** + * e_restore_window: + * @window: a #GtkWindow + * @settings_path: a #GSettings path + * @flags: flags indicating which window features to restore + * + * This function can restore one of or both a window's size and position + * using #GSettings keys at @settings_path which conform to the relocatable + * schema "org.gnome.evolution.window". + * + * If #E_RESTORE_WINDOW_SIZE is present in @flags, restore @window's + * previously recorded size and maximize state. + * + * If #E_RESTORE_WINDOW_POSITION is present in @flags, move @window to + * the previously recorded screen coordinates. + * + * The respective #GSettings values will be updated when the window is + * resized and/or moved. + **/ +void +e_restore_window (GtkWindow *window, + const gchar *settings_path, + ERestoreWindowFlags flags) +{ + WindowData *data; + GSettings *settings; + const gchar *schema; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (settings_path != NULL); + + schema = "org.gnome.evolution.window"; + settings = g_settings_new_with_path (schema, settings_path); + + data = g_slice_new0 (WindowData); + data->window = g_object_ref (window); + data->settings = g_object_ref (settings); + data->flags = flags; + + if (flags & E_RESTORE_WINDOW_SIZE) { + gint width, height; + + width = g_settings_get_int (settings, "width"); + height = g_settings_get_int (settings, "height"); + + if (width > 0 && height > 0) + gtk_window_resize (window, width, height); + + if (g_settings_get_boolean (settings, "maximized")) { + GdkScreen *screen; + + screen = gtk_window_get_screen (window); + gtk_window_get_size (window, &width, &height); + + data->premax_width = width; + data->premax_height = height; + + width = gdk_screen_get_width (screen); + height = gdk_screen_get_height (screen); + + gtk_window_resize (window, width, height); + gtk_window_maximize (window); + } + } + + if (flags & E_RESTORE_WINDOW_POSITION) { + gint x, y; + + x = g_settings_get_int (settings, "x"); + y = g_settings_get_int (settings, "y"); + + gtk_window_move (window, x, y); + } + + g_object_set_data_full ( + G_OBJECT (window), + "e-util-window-data", data, + (GDestroyNotify) window_data_free); + + g_signal_connect ( + window, "configure-event", + G_CALLBACK (window_configure_event_cb), data); + + g_signal_connect ( + window, "window-state-event", + G_CALLBACK (window_state_event_cb), data); + + g_signal_connect ( + window, "unmap", + G_CALLBACK (window_unmap_cb), data); + + g_object_unref (settings); +} + /** * e_lookup_action: * @ui_manager: a #GtkUIManager diff --git a/e-util/e-util.h b/e-util/e-util.h index de2a817171..c95ef0c4f8 100644 --- a/e-util/e-util.h +++ b/e-util/e-util.h @@ -46,11 +46,19 @@ typedef enum { E_FOCUS_END } EFocus; +typedef enum { + E_RESTORE_WINDOW_SIZE = 1 << 0, + E_RESTORE_WINDOW_POSITION = 1 << 1 +} ERestoreWindowFlags; + const gchar * e_get_accels_filename (void); void e_show_uri (GtkWindow *parent, const gchar *uri); void e_display_help (GtkWindow *parent, const gchar *link_id); +void e_restore_window (GtkWindow *window, + const gchar *settings_path, + ERestoreWindowFlags flags); GtkAction * e_lookup_action (GtkUIManager *ui_manager, const gchar *action_name); GtkActionGroup *e_lookup_action_group (GtkUIManager *ui_manager, -- cgit v1.2.3