1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright © 2001 Matthew Mueller
4 * Copyright © 2002 Jorn Baayen <jorn@nl.linux.org>
5 * Copyright © 2003 Marco Pesenti Gritti <mpeseng@tin.it>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * $Id: ephy-state.c 6952 2007-03-11 19:42:02Z chpe $
26 #include "ephy-state.h"
27 #include "ephy-lib-type-builtins.h"
28 #include "ephy-file-helpers.h"
29 #include "ephy-node-db.h"
30 #include "ephy-node-common.h"
33 #include <gtk/gtkwindow.h>
34 #include <gtk/gtkpaned.h>
35 #include <gtk/gtkexpander.h>
36 #include <gtk/gtktogglebutton.h>
38 #define EPHY_STATES_XML_FILE "states.xml"
39 #define EPHY_STATES_XML_ROOT (const xmlChar *)"ephy_states"
40 #define EPHY_STATES_XML_VERSION (const xmlChar *)"1.0"
44 EPHY_NODE_STATE_PROP_NAME
= 2,
45 EPHY_NODE_STATE_PROP_WIDTH
= 3,
46 EPHY_NODE_STATE_PROP_HEIGHT
= 4,
47 EPHY_NODE_STATE_PROP_MAXIMIZE
= 5,
48 EPHY_NODE_STATE_PROP_POSITION_X
= 6,
49 EPHY_NODE_STATE_PROP_POSITION_Y
= 7,
50 EPHY_NODE_STATE_PROP_SIZE
= 8,
51 EPHY_NODE_STATE_PROP_POSITION
= 9,
52 EPHY_NODE_STATE_PROP_ACTIVE
= 10
55 static EphyNode
*states
= NULL
;
56 static EphyNodeDb
*states_db
= NULL
;
59 ephy_states_save (void)
63 xml_file
= g_build_filename (ephy_dot_dir (),
67 ephy_node_db_write_to_xml_safe
69 (const xmlChar
*)xml_file
,
71 EPHY_STATES_XML_VERSION
,
80 find_by_name (const char *name
)
82 EphyNode
*result
= NULL
;
86 children
= ephy_node_get_children (states
);
87 for (i
= 0; i
< children
->len
; i
++)
90 const char *node_name
;
92 kid
= g_ptr_array_index (children
, i
);
94 node_name
= ephy_node_get_property_string
95 (kid
, EPHY_NODE_STATE_PROP_NAME
);
96 if (strcmp (node_name
, name
) == 0)
110 volatile GType flags_type
; /* work around gcc's optimiser */
113 /* make sure the type is known when we read the db */
114 flags_type
= EPHY_TYPE_STATE_WINDOW_FLAGS
;
116 xml_file
= g_build_filename (ephy_dot_dir (),
117 EPHY_STATES_XML_FILE
,
120 states_db
= ephy_node_db_new (EPHY_NODE_DB_STATES
);
121 states
= ephy_node_new_with_id (states_db
, STATES_NODE_ID
);
122 ephy_node_db_load_from_file (states_db
, xml_file
,
123 EPHY_STATES_XML_ROOT
,
124 EPHY_STATES_XML_VERSION
);
131 ephy_state_window_set_size (GtkWidget
*window
, EphyNode
*node
)
133 int width
, height
, w
= -1, h
= -1;
134 gboolean maximize
, size
;
136 width
= ephy_node_get_property_int (node
, EPHY_NODE_STATE_PROP_WIDTH
);
137 height
= ephy_node_get_property_int (node
, EPHY_NODE_STATE_PROP_HEIGHT
);
138 maximize
= ephy_node_get_property_boolean (node
, EPHY_NODE_STATE_PROP_MAXIMIZE
);
139 size
= ephy_node_get_property_boolean (node
, EPHY_NODE_STATE_PROP_SIZE
);
141 gtk_window_get_default_size (GTK_WINDOW (window
), &w
, &h
);
142 if (size
&& w
== -1 && h
== -1)
145 int screen_width
, screen_height
;
147 screen
= gdk_screen_get_default ();
148 screen_width
= gdk_screen_get_width (screen
);
149 screen_height
= gdk_screen_get_height (screen
);
151 gtk_window_set_default_size (GTK_WINDOW (window
),
152 MIN (width
, screen_width
),
153 MIN (height
, screen_height
));
158 gtk_window_maximize (GTK_WINDOW (window
));
163 ephy_state_window_set_position (GtkWidget
*window
, EphyNode
*node
)
167 int screen_width
, screen_height
;
168 gboolean maximize
, size
;
170 g_return_if_fail (GTK_IS_WINDOW (window
));
172 /* Setting the default size doesn't work when the window is already showing. */
173 g_return_if_fail (!GTK_WIDGET_VISIBLE (window
));
175 maximize
= ephy_node_get_property_boolean (node
, EPHY_NODE_STATE_PROP_MAXIMIZE
);
176 size
= ephy_node_get_property_boolean (node
, EPHY_NODE_STATE_PROP_POSITION
);
178 /* Don't set the position of the window if it is maximized */
179 if ((!maximize
) && size
)
181 x
= ephy_node_get_property_int (node
, EPHY_NODE_STATE_PROP_POSITION_X
);
182 y
= ephy_node_get_property_int (node
, EPHY_NODE_STATE_PROP_POSITION_Y
);
184 screen
= gtk_window_get_screen (GTK_WINDOW (window
));
185 screen_width
= gdk_screen_get_width (screen
);
186 screen_height
= gdk_screen_get_height (screen
);
188 if ((x
<= screen_width
) && (y
<= screen_height
) &&
189 (x
>= 0) && (y
>= 0))
191 gtk_window_move (GTK_WINDOW (window
), x
, y
);
197 ephy_state_save_unmaximized_size (EphyNode
*node
, int width
, int height
)
199 ephy_node_set_property_int (node
, EPHY_NODE_STATE_PROP_WIDTH
,
201 ephy_node_set_property_int (node
, EPHY_NODE_STATE_PROP_HEIGHT
,
203 ephy_node_set_property_boolean (node
, EPHY_NODE_STATE_PROP_SIZE
,
208 ephy_state_save_position (EphyNode
*node
, int x
, int y
)
210 ephy_node_set_property_int (node
, EPHY_NODE_STATE_PROP_POSITION_X
,
212 ephy_node_set_property_int (node
, EPHY_NODE_STATE_PROP_POSITION_Y
,
214 ephy_node_set_property_boolean (node
, EPHY_NODE_STATE_PROP_POSITION
,
220 ephy_state_window_save_size (GtkWidget
*window
, EphyNode
*node
)
224 GdkWindowState state
;
226 state
= gdk_window_get_state (GTK_WIDGET (window
)->window
);
227 maximize
= ((state
& GDK_WINDOW_STATE_MAXIMIZED
) > 0);
229 gtk_window_get_size (GTK_WINDOW(window
),
234 ephy_state_save_unmaximized_size (node
, width
, height
);
237 ephy_node_set_property_boolean (node
,
238 EPHY_NODE_STATE_PROP_MAXIMIZE
,
243 ephy_state_window_save_position (GtkWidget
*window
, EphyNode
*node
)
247 GdkWindowState state
;
249 state
= gdk_window_get_state (GTK_WIDGET (window
)->window
);
250 maximize
= ((state
& GDK_WINDOW_STATE_MAXIMIZED
) > 0);
252 /* Don't save the position if maximized */
255 gtk_window_get_position (GTK_WINDOW (window
), &x
, &y
);
256 ephy_state_save_position (node
, x
, y
);
261 ephy_state_window_save (GtkWidget
*widget
, EphyNode
*node
)
263 EphyStateWindowFlags flags
;
265 flags
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget
), "state_flags"));
267 if (flags
& EPHY_STATE_WINDOW_SAVE_SIZE
)
269 ephy_state_window_save_size (widget
, node
);
272 if (flags
& EPHY_STATE_WINDOW_SAVE_POSITION
)
274 ephy_state_window_save_position (widget
, node
);
279 window_configure_event_cb (GtkWidget
*widget
,
280 GdkEventConfigure
*event
,
283 GdkWindowState state
;
285 state
= gdk_window_get_state (widget
->window
);
287 if (!(state
& GDK_WINDOW_STATE_FULLSCREEN
))
289 ephy_state_window_save (widget
, node
);
296 window_state_event_cb (GtkWidget
*widget
,
297 GdkEventWindowState
*event
,
300 if (!(event
->new_window_state
& GDK_WINDOW_STATE_FULLSCREEN
))
302 ephy_state_window_save (widget
, node
);
309 create_window_node (const char *name
,
313 EphyStateWindowFlags flags
)
317 node
= ephy_node_new (states_db
);
318 ephy_node_add_child (states
, node
);
320 ephy_node_set_property_string (node
, EPHY_NODE_STATE_PROP_NAME
,
322 ephy_node_set_property_boolean (node
, EPHY_NODE_STATE_PROP_MAXIMIZE
,
325 if (flags
& EPHY_STATE_WINDOW_SAVE_SIZE
)
327 ephy_state_save_unmaximized_size (node
,
332 if (flags
& EPHY_STATE_WINDOW_SAVE_POSITION
)
334 /* Constants for now, these should be default_width
335 and default_height. */
336 ephy_state_save_position (node
, 0, 0);
343 ephy_state_add_window (GtkWidget
*window
,
348 EphyStateWindowFlags flags
)
354 node
= find_by_name (name
);
357 node
= create_window_node (name
, default_width
, default_height
,
361 ephy_state_window_set_size (window
, node
);
362 ephy_state_window_set_position (window
, node
);
364 g_object_set_data (G_OBJECT (window
), "state_flags", GINT_TO_POINTER (flags
));
366 g_signal_connect (window
, "configure_event",
367 G_CALLBACK (window_configure_event_cb
), node
);
368 g_signal_connect (window
, "window_state_event",
369 G_CALLBACK (window_state_event_cb
), node
);
373 paned_sync_position_cb (GtkWidget
*paned
,
379 width
= gtk_paned_get_position (GTK_PANED (paned
));
380 ephy_node_set_property_int (node
, EPHY_NODE_STATE_PROP_WIDTH
,
386 ephy_state_add_paned (GtkWidget
*paned
,
395 node
= find_by_name (name
);
398 node
= ephy_node_new (states_db
);
399 ephy_node_add_child (states
, node
);
401 ephy_node_set_property_string (node
,
402 EPHY_NODE_STATE_PROP_NAME
,
404 ephy_node_set_property_int (node
,
405 EPHY_NODE_STATE_PROP_WIDTH
,
409 width
= ephy_node_get_property_int (node
, EPHY_NODE_STATE_PROP_WIDTH
);
410 gtk_paned_set_position (GTK_PANED (paned
), width
);
412 g_signal_connect (paned
, "notify::position",
413 G_CALLBACK (paned_sync_position_cb
), node
);
417 sync_expander_cb (GtkExpander
*expander
,
421 gboolean is_expanded
;
423 is_expanded
= gtk_expander_get_expanded (expander
);
424 ephy_node_set_property_boolean (node
,
425 EPHY_NODE_STATE_PROP_ACTIVE
,
430 sync_toggle_cb (GtkToggleButton
*toggle
,
436 is_active
= gtk_toggle_button_get_active (toggle
);
437 ephy_node_set_property_boolean (node
,
438 EPHY_NODE_STATE_PROP_ACTIVE
,
443 ephy_state_add_expander (GtkWidget
*widget
,
445 gboolean default_state
)
452 node
= find_by_name (name
);
455 node
= ephy_node_new (states_db
);
456 ephy_node_add_child (states
, node
);
458 ephy_node_set_property_string (node
,
459 EPHY_NODE_STATE_PROP_NAME
,
461 ephy_node_set_property_boolean (node
,
462 EPHY_NODE_STATE_PROP_ACTIVE
,
466 active
= ephy_node_get_property_boolean
467 (node
, EPHY_NODE_STATE_PROP_ACTIVE
);
469 if (GTK_IS_TOGGLE_BUTTON (widget
))
471 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget
), active
);
472 g_signal_connect (widget
, "notify::active",
473 G_CALLBACK (sync_toggle_cb
), node
);
475 else if (GTK_IS_EXPANDER (widget
))
477 gtk_expander_set_expanded (GTK_EXPANDER (widget
), active
);
478 g_signal_connect (widget
, "notify::expanded",
479 G_CALLBACK (sync_expander_cb
), node
);
484 ephy_state_save (void)
489 ephy_node_unref (states
);
490 g_object_unref (states_db
);