aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ephy-initial-state.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ephy-initial-state.c')
-rw-r--r--lib/ephy-initial-state.c462
1 files changed, 462 insertions, 0 deletions
diff --git a/lib/ephy-initial-state.c b/lib/ephy-initial-state.c
new file mode 100644
index 000000000..fb625ac45
--- /dev/null
+++ b/lib/ephy-initial-state.c
@@ -0,0 +1,462 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2001 Matthew Mueller
+ * Copyright © 2002 Jorn Baayen <jorn@nl.linux.org>
+ * Copyright © 2003 Marco Pesenti Gritti <mpeseng@tin.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ephy-initial-state.h"
+
+#include "ephy-file-helpers.h"
+#include "ephy-lib-type-builtins.h"
+#include "ephy-node-common.h"
+#include "ephy-node-db.h"
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define EPHY_STATES_XML_FILE "states.xml"
+#define EPHY_STATES_XML_ROOT (const xmlChar *)"ephy_states"
+#define EPHY_STATES_XML_VERSION (const xmlChar *)"1.0"
+
+enum
+{
+ EPHY_NODE_INITIAL_STATE_PROP_NAME = 2,
+ EPHY_NODE_INITIAL_STATE_PROP_WIDTH = 3,
+ EPHY_NODE_INITIAL_STATE_PROP_HEIGHT = 4,
+ EPHY_NODE_INITIAL_STATE_PROP_MAXIMIZE = 5,
+ EPHY_NODE_INITIAL_STATE_PROP_POSITION_X = 6,
+ EPHY_NODE_INITIAL_STATE_PROP_POSITION_Y = 7,
+ EPHY_NODE_INITIAL_STATE_PROP_SIZE = 8,
+ EPHY_NODE_INITIAL_STATE_PROP_POSITION = 9,
+ EPHY_NODE_INITIAL_STATE_PROP_ACTIVE = 10
+};
+
+static EphyNode *states = NULL;
+static EphyNodeDb *states_db = NULL;
+
+static void
+ephy_states_save (void)
+{
+ char *xml_file;
+
+ xml_file = g_build_filename (ephy_dot_dir (),
+ EPHY_STATES_XML_FILE,
+ NULL);
+
+ ephy_node_db_write_to_xml_safe (states_db,
+ (const xmlChar *)xml_file,
+ EPHY_STATES_XML_ROOT,
+ EPHY_STATES_XML_VERSION,
+ NULL, /* comment */
+ states, NULL, NULL,
+ NULL);
+
+ g_free (xml_file);
+}
+
+static EphyNode *
+find_by_name (const char *name)
+{
+ EphyNode *result = NULL;
+ GPtrArray *children;
+ int i;
+
+ children = ephy_node_get_children (states);
+ for (i = 0; i < children->len; i++) {
+ EphyNode *kid;
+ const char *node_name;
+
+ kid = g_ptr_array_index (children, i);
+
+ node_name = ephy_node_get_property_string
+ (kid, EPHY_NODE_INITIAL_STATE_PROP_NAME);
+
+ if (strcmp (node_name, name) == 0)
+ result = kid;
+ }
+
+ return result;
+}
+
+static void
+ensure_states (void)
+{
+ if (states == NULL) {
+ char *xml_file;
+
+ xml_file = g_build_filename (ephy_dot_dir (),
+ EPHY_STATES_XML_FILE,
+ NULL);
+
+ states_db = ephy_node_db_new (EPHY_NODE_DB_STATES);
+ states = ephy_node_new_with_id (states_db, STATES_NODE_ID);
+ ephy_node_db_load_from_file (states_db, xml_file,
+ EPHY_STATES_XML_ROOT,
+ EPHY_STATES_XML_VERSION);
+
+ g_free (xml_file);
+ }
+}
+
+static void
+ephy_state_window_set_size (GtkWidget *window, EphyNode *node)
+{
+ int width, height, w = -1, h = -1;
+ gboolean maximize, size;
+
+ width = ephy_node_get_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_WIDTH);
+ height = ephy_node_get_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_HEIGHT);
+ maximize = ephy_node_get_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_MAXIMIZE);
+ size = ephy_node_get_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_SIZE);
+
+ gtk_window_get_default_size (GTK_WINDOW (window), &w, &h);
+
+ if (size && w == -1 && h == -1) {
+ GdkScreen *screen;
+ int screen_width, screen_height;
+
+ screen = gdk_screen_get_default ();
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+
+ gtk_window_set_default_size (GTK_WINDOW (window),
+ MIN (width, screen_width),
+ MIN (height, screen_height));
+ }
+
+ if (maximize)
+ gtk_window_maximize (GTK_WINDOW (window));
+}
+
+static void
+ephy_state_window_set_position (GtkWidget *window, EphyNode *node)
+{
+ GdkScreen *screen;
+ int x, y;
+ int screen_width, screen_height;
+ gboolean maximize, size;
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+
+ /* Setting the default size doesn't work when the window is already showing. */
+ g_return_if_fail (!gtk_widget_get_visible (window));
+
+ maximize = ephy_node_get_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_MAXIMIZE);
+ size = ephy_node_get_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION);
+
+ /* Don't set the position of the window if it is maximized */
+ if ((!maximize) && size) {
+ x = ephy_node_get_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION_X);
+ y = ephy_node_get_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION_Y);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (window));
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+
+ if ((x <= screen_width) && (y <= screen_height) &&
+ (x >= 0) && (y >= 0))
+ gtk_window_move (GTK_WINDOW (window), x, y);
+ }
+}
+
+static void
+ephy_state_save_unmaximized_size (EphyNode *node, int width, int height)
+{
+ ephy_node_set_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_WIDTH,
+ width);
+ ephy_node_set_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_HEIGHT,
+ height);
+ ephy_node_set_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_SIZE,
+ TRUE);
+}
+
+static void
+ephy_state_save_position (EphyNode *node, int x, int y)
+{
+ ephy_node_set_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION_X,
+ x);
+ ephy_node_set_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION_Y,
+ y);
+ ephy_node_set_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_POSITION,
+ TRUE);
+}
+
+
+static void
+ephy_state_window_save_size (GtkWidget *window, EphyNode *node)
+{
+ int width, height;
+ gboolean maximize;
+ GdkWindowState state;
+
+ state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
+ maximize = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
+
+ gtk_window_get_size (GTK_WINDOW(window),
+ &width, &height);
+
+ if (!maximize)
+ ephy_state_save_unmaximized_size (node, width, height);
+
+ ephy_node_set_property_boolean (node,
+ EPHY_NODE_INITIAL_STATE_PROP_MAXIMIZE,
+ maximize);
+}
+
+static void
+ephy_state_window_save_position (GtkWidget *window, EphyNode *node)
+{
+ int x,y;
+ gboolean maximize;
+ GdkWindowState state;
+
+ state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
+ maximize = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
+
+ /* Don't save the position if maximized. */
+ if (!maximize) {
+ gtk_window_get_position (GTK_WINDOW (window), &x, &y);
+ ephy_state_save_position (node, x, y);
+ }
+}
+
+static void
+ephy_state_window_save (GtkWidget *widget, EphyNode *node)
+{
+ EphyInitialStateWindowFlags flags;
+
+ flags = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "state_flags"));
+
+ if (flags & EPHY_INITIAL_STATE_WINDOW_SAVE_SIZE)
+ ephy_state_window_save_size (widget, node);
+
+ if (flags & EPHY_INITIAL_STATE_WINDOW_SAVE_POSITION)
+ ephy_state_window_save_position (widget, node);
+}
+
+static gboolean
+window_configure_event_cb (GtkWidget *widget,
+ GdkEventConfigure *event,
+ EphyNode *node)
+{
+ GdkWindowState state;
+
+ state = gdk_window_get_state (gtk_widget_get_window (widget));
+
+ if (!(state & GDK_WINDOW_STATE_FULLSCREEN))
+ ephy_state_window_save (widget, node);
+
+ return FALSE;
+}
+
+static gboolean
+window_state_event_cb (GtkWidget *widget,
+ GdkEventWindowState *event,
+ EphyNode *node)
+{
+ if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN))
+ ephy_state_window_save (widget, node);
+
+ return FALSE;
+}
+
+static EphyNode *
+create_window_node (const char *name,
+ int default_width,
+ int default_height,
+ gboolean maximize,
+ EphyInitialStateWindowFlags flags)
+{
+ EphyNode *node;
+
+ node = ephy_node_new (states_db);
+ ephy_node_add_child (states, node);
+
+ ephy_node_set_property_string (node, EPHY_NODE_INITIAL_STATE_PROP_NAME,
+ name);
+ ephy_node_set_property_boolean (node, EPHY_NODE_INITIAL_STATE_PROP_MAXIMIZE,
+ maximize);
+
+ if (flags & EPHY_INITIAL_STATE_WINDOW_SAVE_SIZE) {
+ ephy_state_save_unmaximized_size (node,
+ default_width,
+ default_height);
+ }
+
+ if (flags & EPHY_INITIAL_STATE_WINDOW_SAVE_POSITION) {
+ /* Constants for now, these should be default_wi dth
+ and default_height. */
+ ephy_state_save_position (node, 0, 0);
+ }
+
+ return node;
+}
+
+void
+ephy_initial_state_add_window (GtkWidget *window,
+ const char *name,
+ int default_width,
+ int default_height,
+ gboolean maximize,
+ EphyInitialStateWindowFlags flags)
+{
+ EphyNode *node;
+
+ g_return_if_fail (GTK_IS_WIDGET (window));
+ g_return_if_fail (name != NULL);
+
+ ensure_states ();
+
+ node = find_by_name (name);
+
+ if (node == NULL)
+ node = create_window_node (name, default_width, default_height,
+ maximize, flags);
+
+ ephy_state_window_set_size (window, node);
+ ephy_state_window_set_position (window, node);
+
+ g_object_set_data (G_OBJECT (window), "state_flags", GINT_TO_POINTER (flags));
+
+ g_signal_connect (window, "configure_event",
+ G_CALLBACK (window_configure_event_cb), node);
+ g_signal_connect (window, "window_state_event",
+ G_CALLBACK (window_state_event_cb), node);
+}
+
+static gboolean
+paned_sync_position_cb (GtkWidget *paned,
+ GParamSpec *pspec,
+ EphyNode *node)
+{
+ int width;
+
+ width = gtk_paned_get_position (GTK_PANED (paned));
+ ephy_node_set_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_WIDTH,
+ width);
+ return FALSE;
+}
+
+void
+ephy_initial_state_add_paned (GtkWidget *paned,
+ const char *name,
+ int default_width)
+{
+ EphyNode *node;
+ int width;
+
+ ensure_states ();
+
+ node = find_by_name (name);
+
+ if (node == NULL) {
+ node = ephy_node_new (states_db);
+ ephy_node_add_child (states, node);
+
+ ephy_node_set_property_string (node,
+ EPHY_NODE_INITIAL_STATE_PROP_NAME,
+ name);
+ ephy_node_set_property_int (node,
+ EPHY_NODE_INITIAL_STATE_PROP_WIDTH,
+ default_width);
+ }
+
+ width = ephy_node_get_property_int (node, EPHY_NODE_INITIAL_STATE_PROP_WIDTH);
+ gtk_paned_set_position (GTK_PANED (paned), width);
+
+ g_signal_connect (paned, "notify::position",
+ G_CALLBACK (paned_sync_position_cb), node);
+}
+
+static void
+sync_expander_cb (GtkExpander *expander,
+ GParamSpec *pspec,
+ EphyNode *node)
+{
+ gboolean is_expanded;
+
+ is_expanded = gtk_expander_get_expanded (expander);
+ ephy_node_set_property_boolean (node,
+ EPHY_NODE_INITIAL_STATE_PROP_ACTIVE,
+ is_expanded);
+}
+
+static void
+sync_toggle_cb (GtkToggleButton *toggle,
+ GParamSpec *pspec,
+ EphyNode *node)
+{
+ gboolean is_active;
+
+ is_active = gtk_toggle_button_get_active (toggle);
+ ephy_node_set_property_boolean (node,
+ EPHY_NODE_INITIAL_STATE_PROP_ACTIVE,
+ is_active);
+}
+
+void
+ephy_initial_state_add_expander (GtkWidget *widget,
+ const char *name,
+ gboolean default_state)
+{
+ EphyNode *node;
+ gboolean active;
+
+ ensure_states ();
+
+ node = find_by_name (name);
+
+ if (node == NULL) {
+ node = ephy_node_new (states_db);
+ ephy_node_add_child (states, node);
+
+ ephy_node_set_property_string (node,
+ EPHY_NODE_INITIAL_STATE_PROP_NAME,
+ name);
+ ephy_node_set_property_boolean (node,
+ EPHY_NODE_INITIAL_STATE_PROP_ACTIVE,
+ default_state);
+ }
+
+ active = ephy_node_get_property_boolean
+ (node, EPHY_NODE_INITIAL_STATE_PROP_ACTIVE);
+
+ if (GTK_IS_TOGGLE_BUTTON (widget)) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), active);
+ g_signal_connect (widget, "notify::active",
+ G_CALLBACK (sync_toggle_cb), node);
+ } else if (GTK_IS_EXPANDER (widget)) {
+ gtk_expander_set_expanded (GTK_EXPANDER (widget), active);
+ g_signal_connect (widget, "notify::expanded",
+ G_CALLBACK (sync_expander_cb), node);
+ }
+}
+
+void
+ephy_initial_state_save (void)
+{
+ if (states) {
+ ephy_states_save ();
+ ephy_node_unref (states);
+ g_object_unref (states_db);
+ states = NULL;
+ states_db = NULL;
+ }
+}