summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Finke <jens@triq.net>2005-03-14 20:19:07 +0000
committerJens Finke <jens@src.gnome.org>2005-03-14 20:19:07 +0000
commit9a3aac945d14b5274d478a42100bc633ea81644b (patch)
treec73a9481b4f52f54cf2fd2fa6532488065323ded
parentc7dce2b73f9f55f06b0e06a76be36a1cf993c6b0 (diff)
downloadeog-experimental-job-mgr.tar.gz
New keys for saving window geometry.experimental-job-mgr
2005-03-14 Jens Finke <jens@triq.net> * eog.schemas.in: New keys for saving window geometry. * shell/eog-window.c: Save window geometry and restore it on load. * shell/main.c: Create empty windows more simple.
-rw-r--r--ChangeLog8
-rw-r--r--eog.schemas.in22
-rw-r--r--libeog/eog-config-keys.h2
-rw-r--r--shell/eog-window.c345
-rw-r--r--shell/eog-window.h1
-rw-r--r--shell/main.c33
6 files changed, 340 insertions, 71 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f574641..a90a238a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2005-03-14 Jens Finke <jens@triq.net>
+ * eog.schemas.in: New keys for saving window geometry.
+
+ * shell/eog-window.c: Save window geometry and restore it on load.
+
+ * shell/main.c: Create empty windows more simple.
+
+2005-03-14 Jens Finke <jens@triq.net>
+
* libeog/eog-image-list.c (eog_image_list_add_uris):
Joined _add_directory and _add_files functions.
diff --git a/eog.schemas.in b/eog.schemas.in
index 71074523..3225150d 100644
--- a/eog.schemas.in
+++ b/eog.schemas.in
@@ -57,6 +57,28 @@
</schema>
<schema>
+ <key>/schemas/apps/eog/window/geometry_collection</key>
+ <applyto>/apps/eog/window/geometry_collection</applyto>
+ <owner>eog</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Last collection window geometry</short>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/eog/window/geometry_singleton</key>
+ <applyto>/apps/eog/window/geometry_singleton</applyto>
+ <owner>eog</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Last singleton window geometry</short>
+ </locale>
+ </schema>
+
+ <schema>
<key>/schemas/apps/eog/full_screen/loop</key>
<applyto>/apps/eog/full_screen/loop</applyto>
<owner>eog</owner>
diff --git a/libeog/eog-config-keys.h b/libeog/eog-config-keys.h
index d636a6f7..5ff9bf50 100644
--- a/libeog/eog-config-keys.h
+++ b/libeog/eog-config-keys.h
@@ -9,6 +9,8 @@
#define EOG_CONF_VIEW_TRANS_COLOR "/apps/eog/view/trans_color"
#define EOG_CONF_WINDOW_OPEN_NEW_WINDOW "/apps/eog/window/open_new_window"
+#define EOG_CONF_WINDOW_GEOMETRY_SINGLETON "/apps/eog/window/geometry_singleton"
+#define EOG_CONF_WINDOW_GEOMETRY_COLLECTION "/apps/eog/window/geometry_collection"
#define EOG_CONF_FULLSCREEN_LOOP "/apps/eog/full_screen/loop"
#define EOG_CONF_FULLSCREEN_UPSCALE "/apps/eog/full_screen/upscale"
diff --git a/shell/eog-window.c b/shell/eog-window.c
index 995a5eca..d5ca00a4 100644
--- a/shell/eog-window.c
+++ b/shell/eog-window.c
@@ -30,6 +30,7 @@
#include <gnome.h>
#include <string.h>
#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
#include <gconf/gconf-client.h>
#include <libgnome/gnome-program.h>
#include <libgnomeui/gnome-window-icon.h>
@@ -98,6 +99,9 @@ struct _EogWindowPrivate {
GtkActionGroup *actions_image;
GtkActionGroup *actions_collection;
+ /* window geometry */
+ guint save_geometry_timeout_id;
+ char *last_geometry;
int desired_width;
int desired_height;
@@ -123,6 +127,12 @@ enum {
SIGNAL_LAST
};
+typedef enum {
+ EOG_WINDOW_MODE_UNKNOWN,
+ EOG_WINDOW_MODE_SINGLETON,
+ EOG_WINDOW_MODE_COLLECTION
+} EogWindowMode;
+
static int eog_window_signals [SIGNAL_LAST];
static void eog_window_class_init (EogWindowClass *class);
@@ -203,6 +213,158 @@ gen_role (void)
return ret;
}
+/**
+ * Copied from eel/eel-gtk-extensions.c
+ * eel_gtk_window_get_geometry_string:
+ * @window: a #GtkWindow
+ *
+ * Obtains the geometry string for this window, suitable for
+ * set_geometry_string(); assumes the window has NorthWest gravity
+ *
+ * Return value: geometry string, must be freed
+ **/
+static char*
+eog_gtk_window_get_geometry_string (GtkWindow *window)
+{
+ char *str;
+ int w, h, x, y;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
+ g_return_val_if_fail (gtk_window_get_gravity (window) ==
+ GDK_GRAVITY_NORTH_WEST, NULL);
+
+ gtk_window_get_position (window, &x, &y);
+ gtk_window_get_size (window, &w, &h);
+
+ str = g_strdup_printf ("%dx%d+%d+%d", w, h, x, y);
+
+ return str;
+}
+
+static EogWindowMode
+eog_window_get_mode (EogWindow *window)
+{
+ EogWindowMode mode = EOG_WINDOW_MODE_UNKNOWN;
+
+ g_return_val_if_fail (EOG_IS_WINDOW (window), EOG_WINDOW_MODE_UNKNOWN);
+
+ if (window->priv->image_list != NULL) {
+ int n_images = eog_image_list_length (window->priv->image_list);
+
+ if (n_images == 1)
+ mode = EOG_WINDOW_MODE_SINGLETON;
+ else if (n_images > 1)
+ mode = EOG_WINDOW_MODE_COLLECTION;
+ }
+
+ return mode;
+}
+
+static gboolean
+save_window_geometry_timeout (gpointer callback_data)
+{
+ EogWindow *window;
+
+ window = EOG_WINDOW (callback_data);
+
+ eog_window_save_geometry (window);
+
+ window->priv->save_geometry_timeout_id = 0;
+
+ return FALSE;
+}
+
+static gboolean
+eog_window_configure_event (GtkWidget *widget,
+ GdkEventConfigure *event)
+{
+ EogWindow *window;
+ char *geometry_string;
+
+ window = EOG_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->configure_event (widget, event);
+
+ /* Only save the geometry if the user hasn't resized the window
+ * for a second. Otherwise delay the callback another second.
+ */
+ if (window->priv->save_geometry_timeout_id != 0) {
+ g_source_remove (window->priv->save_geometry_timeout_id);
+ }
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (window))) {
+ geometry_string = eog_gtk_window_get_geometry_string (GTK_WINDOW (window));
+
+ /* If the last geometry is NULL the window must have just
+ * been shown. No need to save geometry to disk since it
+ * must be the same.
+ */
+ if (window->priv->last_geometry == NULL) {
+ window->priv->last_geometry = geometry_string;
+ return FALSE;
+ }
+
+ /* Don't save geometry if it's the same as before. */
+ if (!strcmp (window->priv->last_geometry,
+ geometry_string)) {
+ g_free (geometry_string);
+ return FALSE;
+ }
+
+ g_free (window->priv->last_geometry);
+ window->priv->last_geometry = geometry_string;
+
+ window->priv->save_geometry_timeout_id =
+ g_timeout_add (1000, save_window_geometry_timeout, window);
+ }
+
+ return FALSE;
+}
+
+static void
+eog_window_unrealize (GtkWidget *widget)
+{
+ EogWindow *window;
+
+ window = EOG_WINDOW (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+
+ if (window->priv->save_geometry_timeout_id != 0) {
+ g_source_remove (window->priv->save_geometry_timeout_id);
+ window->priv->save_geometry_timeout_id = 0;
+ eog_window_save_geometry (window);
+ }
+}
+
+void
+eog_window_save_geometry (EogWindow *window)
+{
+ EogWindowPrivate *priv;
+ char *geometry_string;
+ EogWindowMode mode;
+ char *key = NULL;
+
+ g_return_if_fail (EOG_IS_WINDOW (window));
+
+ priv = window->priv;
+
+ mode = eog_window_get_mode (window);
+ if (mode == EOG_WINDOW_MODE_SINGLETON)
+ key = EOG_CONF_WINDOW_GEOMETRY_SINGLETON;
+ else if (mode == EOG_WINDOW_MODE_COLLECTION)
+ key = EOG_CONF_WINDOW_GEOMETRY_COLLECTION;
+
+ if (GTK_WIDGET(window)->window && key != NULL &&
+ !(gdk_window_get_state (GTK_WIDGET(window)->window) & GDK_WINDOW_STATE_MAXIMIZED)) {
+ geometry_string = eog_gtk_window_get_geometry_string (GTK_WINDOW (window));
+
+ gconf_client_set_string (priv->client, key, geometry_string, NULL);
+
+ g_free (geometry_string);
+ }
+}
+
+
/* Brings attention to a window by raising it and giving it focus */
static void
raise_and_focus (GtkWidget *widget)
@@ -1964,6 +2126,11 @@ eog_window_destroy (GtkObject *object)
priv->recent_model = NULL;
}
+ if (priv->last_geometry != NULL) {
+ g_free (priv->last_geometry);
+ priv->last_geometry = NULL;
+ }
+
/* Clean up GConf-related stuff */
if (priv->client) {
gconf_client_notify_remove (priv->client, priv->interp_type_notify_id);
@@ -2040,6 +2207,8 @@ eog_window_class_init (EogWindowClass *class)
widget_class->delete_event = eog_window_delete;
widget_class->key_press_event = eog_window_key_press;
widget_class->drag_data_received = eog_window_drag_data_received;
+ widget_class->configure_event = eog_window_configure_event;
+ widget_class->unrealize = eog_window_unrealize;
class->open_uri_list = open_uri_list_cleanup;
}
@@ -2258,47 +2427,118 @@ update_ui_visibility (EogWindow *window)
}
}
-#if 0 /* FIXME: DEAD CODE */
-static void
-image_progress_cb (EogImage *image, float progress, gpointer data)
-{
- gnome_appbar_set_progress_percentage (GNOME_APPBAR (EOG_WINDOW (data)->priv->statusbar), progress);
-}
-
static void
-image_loading_finished_cb (EogImage *image, gpointer data)
+obtain_desired_size (EogWindow *window, int *x11_flags,
+ int *x, int *y, int *width, int *height)
{
- EogWindow *window;
- EogWindowPrivate *priv;
- int n_images = 0;
-
- window = EOG_WINDOW (data);
- priv = window->priv;
-
- if (priv->image_list != NULL) {
- n_images = eog_image_list_length (priv->image_list);
+ char *key;
+ char *geometry_string;
+ EogImageList *list;
+ EogWindowMode mode;
+ gboolean finished = FALSE;
+ EogImage *img;
+
+ list = window->priv->image_list;
+
+ if (list != NULL && eog_image_list_length (list) == 1) {
+ img = eog_image_list_get_img_by_pos (list, 0);
+ eog_image_get_size (img, width, height);
+
+ g_print ("Use image dimension: %i/%i\n", *width, *height);
+
+ if ((*width > 0) && (*height > 0)) {
+ *x11_flags = *x11_flags | WidthValue | HeightValue;
+ finished = TRUE;
+ }
+
+ g_object_unref (img);
}
-
- if (n_images == 1) {
- int width, height;
+
+ if (!finished) {
+ /* retrieve last saved geometry */
+ mode = eog_window_get_mode (window);
+ if (mode == EOG_WINDOW_MODE_COLLECTION)
+ key = EOG_CONF_WINDOW_GEOMETRY_COLLECTION;
+ else
+ key = EOG_CONF_WINDOW_GEOMETRY_SINGLETON;
- eog_image_get_size (image, &width, &height);
- adapt_window_size (window, width, height);
-
-#ifdef DEBUG
- g_print ("loading finished: %s - (%i|%i)\n", eog_image_get_caption (image), width, height);
-#endif
+ geometry_string = gconf_client_get_string (window->priv->client,
+ key, NULL);
+ /* parse resulting string */
+ if (geometry_string == NULL) {
+ *width = DEFAULT_WINDOW_WIDTH;
+ *height = DEFAULT_WINDOW_HEIGHT;
+ *x11_flags = *x11_flags | WidthValue | HeightValue;
+ }
+ else {
+ *x11_flags = XParseGeometry (geometry_string,
+ x, y,
+ width, height);
+ }
}
-
- update_status_bar (window);
}
static void
-image_loading_failed_cb (EogImage *image, const char* message, gpointer data)
+setup_initial_geometry (EogWindow *window)
{
- g_print ("loading failed: %s\n", eog_image_get_caption (image));
+ int x11_flags = 0;
+ guint width, height;
+ int x, y;
+ GdkScreen *screen;
+ int screen_width, screen_height;
+
+ g_assert (EOG_IS_WINDOW (window));
+
+ obtain_desired_size (window, &x11_flags,
+ &x, &y, &width, &height);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (window));
+ g_assert (screen != NULL);
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+
+ /* set position first */
+ if ((x11_flags & XValue) && (x11_flags & YValue)) {
+ int real_x = x;
+ int real_y = y;
+
+ /* This is sub-optimal. GDK doesn't allow us to set win_gravity
+ * to South/East types, which should be done if using negative
+ * positions (so that the right or bottom edge of the window
+ * appears at the specified position, not the left or top).
+ * However it does seem to be consistent with other GNOME apps.
+ */
+ if (x11_flags & XNegative) {
+ real_x = screen_width - real_x;
+ }
+ if (x11_flags & YNegative) {
+ real_y = screen_height - real_y;
+ }
+
+ /* sanity check */
+ real_x = CLAMP (real_x, 0, screen_width - 100);
+ real_y = CLAMP (real_y, 0, screen_height - 100);
+
+ gtk_window_move (GTK_WINDOW (window), real_x, real_y);
+ }
+
+ if ((x11_flags & WidthValue) && (x11_flags & HeightValue)) {
+ if ((width > screen_width) || (height > screen_height)) {
+ double factor;
+ if (width > height) {
+ factor = (screen_width * 0.75) / (double) width;
+ }
+ else {
+ factor = (screen_height * 0.75) / (double) height;
+ }
+ width = width * factor;
+ height = height * factor;
+ }
+ g_print ("setting window size: %i/%i\n", width, height);
+
+ gtk_window_set_default_size (GTK_WINDOW (window), width, height);
+ }
}
-#endif
static void
update_status_bar (EogWindow *window)
@@ -2695,7 +2935,7 @@ eog_window_construct_ui (EogWindow *window, GError **error)
GtkAction *action;
GtkWidget *sw;
GtkWidget *frame;
- char *filename;
+ char *filename;
guint merge_id;
g_return_val_if_fail (window != NULL, FALSE);
@@ -2725,10 +2965,10 @@ eog_window_construct_ui (EogWindow *window, GError **error)
gtk_ui_manager_insert_action_group (priv->ui_mgr, priv->actions_image, 0);
/* find and setup UI description */
- filename = gnome_program_locate_file (NULL,
- GNOME_FILE_DOMAIN_APP_DATADIR,
- "eog/eog-gtk-ui.xml",
- FALSE, NULL);
+ filename = gnome_program_locate_file (NULL,
+ GNOME_FILE_DOMAIN_APP_DATADIR,
+ "eog/eog-gtk-ui.xml",
+ FALSE, NULL);
if (filename == NULL) {
g_set_error (error, EOG_WINDOW_ERROR,
@@ -2831,13 +3071,7 @@ eog_window_construct_ui (EogWindow *window, GError **error)
set_drag_dest (window);
- /* set default geometry */
- gtk_window_set_default_size (GTK_WINDOW (window),
- DEFAULT_WINDOW_WIDTH,
- DEFAULT_WINDOW_HEIGHT);
- gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
- gtk_widget_show_all (GTK_WIDGET (window));
- gtk_widget_hide_all (GTK_WIDGET (priv->vpane));
+ gtk_widget_show_all (GTK_WIDGET (priv->box));
/* show/hide toolbar? */
visible = gconf_client_get_bool (priv->client, EOG_CONF_UI_TOOLBAR, NULL);
@@ -2853,7 +3087,6 @@ eog_window_construct_ui (EogWindow *window, GError **error)
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
g_object_set (G_OBJECT (priv->statusbar), "visible", visible, NULL);
- update_ui_visibility (window);
return TRUE;
}
@@ -3010,15 +3243,6 @@ adapt_window_size (EogWindow *window, int width, int height)
}
static void
-image_list_prepared_cb (EogImageList *list, EogWindow *window)
-{
-#ifdef DEBUG
- g_print ("EogWindow: Image list prepared: %i images\n", eog_image_list_length (EOG_IMAGE_LIST (list)));
-#endif
- update_ui_visibility (EOG_WINDOW (window));
-}
-
-static void
add_uri_to_recent_files (EogWindow *window, GnomeVFSURI *uri)
{
EggRecentItem *recent_item;
@@ -3054,7 +3278,6 @@ eog_window_open (EogWindow *window, EogImageList *model, GError **error)
{
EogWindowPrivate *priv;
- g_return_val_if_fail (EOG_IS_IMAGE_LIST (model), FALSE);
g_return_val_if_fail (EOG_IS_WINDOW (window), FALSE);
priv = window->priv;
@@ -3067,16 +3290,24 @@ eog_window_open (EogWindow *window, EogImageList *model, GError **error)
if (priv->image_list != NULL) {
g_signal_handler_disconnect (G_OBJECT (priv->image_list), priv->sig_id_list_prepared);
g_object_unref (priv->image_list);
+ priv->image_list = NULL;
+ }
+
+ if (model != NULL) {
+ g_object_ref (model);
+ priv->image_list = model;
}
- g_object_ref (model);
- priv->image_list = model;
/* update ui */
update_ui_visibility (window);
+ if (!GTK_WIDGET_MAPPED (GTK_WIDGET (window))) {
+ setup_initial_geometry (window);
+ }
+
/* attach model to view */
eog_wrap_list_set_model (EOG_WRAP_LIST (priv->wraplist), EOG_IMAGE_LIST (priv->image_list));
-
+
/* update recent files */
#if 0
add_uri_to_recent_files (window, uri);
diff --git a/shell/eog-window.h b/shell/eog-window.h
index 9361e0c6..394971bf 100644
--- a/shell/eog-window.h
+++ b/shell/eog-window.h
@@ -79,6 +79,7 @@ gboolean eog_window_open (EogWindow *win, EogImageList *model, GError *
const char* eog_window_get_uri (EogWindow *eog_window);
gboolean eog_window_has_contents (EogWindow *eog_window);
+void eog_window_save_geometry (EogWindow *eog_window);
GList* eog_get_window_list (void);
diff --git a/shell/main.c b/shell/main.c
index c24d3751..ff43111e 100644
--- a/shell/main.c
+++ b/shell/main.c
@@ -17,7 +17,7 @@
#include "eog-job-manager.h"
static void open_uri_list_cb (EogWindow *window, GSList *uri_list, gpointer data);
-static GtkWidget* create_new_window (void);
+static void new_window_cb (EogWindow *window, gpointer data);
typedef struct {
@@ -78,12 +78,6 @@ load_context_new (EogWindow *window, GList *uri_list)
return ctx;
}
-static void
-new_window_cb (EogWindow *window, gpointer data)
-{
- create_new_window ();
-}
-
static GtkWidget*
create_new_window (void)
{
@@ -125,7 +119,9 @@ assign_model_to_window (EogWindow *window, EogImageList *list)
if (window == NULL) return;
- eog_image_list_print_debug (list);
+ if (list != NULL) {
+ eog_image_list_print_debug (list);
+ }
if (!eog_window_open (window, list, &error)) {
/* FIXME: show error, free image list */
@@ -135,14 +131,23 @@ assign_model_to_window (EogWindow *window, EogImageList *list)
gtk_widget_show (GTK_WIDGET (window));
}
-static gboolean
-create_empty_window (gpointer data)
+static void
+create_empty_window (void)
{
- create_new_window ();
-
- return FALSE;
+ GtkWidget *window;
+
+ window = create_new_window ();
+ if (window != NULL) {
+ eog_window_open (EOG_WINDOW (window), NULL, NULL);
+ gtk_widget_show (window);
+ }
}
+static void
+new_window_cb (EogWindow *window, gpointer data)
+{
+ create_empty_window ();
+}
static GnomeVFSURI*
make_canonical_uri (const char *path)
@@ -447,7 +452,7 @@ open_uri_list_cb (EogWindow *window, GSList *uri_list, gpointer data)
if (uri_list == NULL) {
if (window == NULL) {
- g_idle_add (create_empty_window, NULL);
+ create_empty_window ();
}
return;