~noskcaj/ubuntu/wily/epiphany-browser/merge

« back to all changes in this revision

Viewing changes to lib/ephy-state.c

  • Committer: Package Import Robot
  • Author(s): Gustavo Noronha Silva
  • Date: 2013-03-20 20:45:41 UTC
  • mto: (120.1.2 experimental) (1.10.1) (105.1.14 sid)
  • mto: This revision was merged to the branch mainline in revision 121.
  • Revision ID: package-import@ubuntu.com-20130320204541-0t2adqjzvpflkni2
Tags: upstream-3.7.91
Import upstream version 3.7.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
 
/*
3
 
 *  Copyright © 2001 Matthew Mueller
4
 
 *  Copyright © 2002 Jorn Baayen <jorn@nl.linux.org>
5
 
 *  Copyright © 2003 Marco Pesenti Gritti <mpeseng@tin.it>
6
 
 *
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)
10
 
 *  any later version.
11
 
 *
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.
16
 
 *
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.
20
 
 *
21
 
 */
22
 
 
23
 
#include "config.h"
24
 
 
25
 
#include "ephy-state.h"
26
 
#include "ephy-lib-type-builtins.h"
27
 
#include "ephy-file-helpers.h"
28
 
#include "ephy-node-db.h"
29
 
#include "ephy-node-common.h"
30
 
 
31
 
#include <string.h>
32
 
#include <gtk/gtk.h>
33
 
 
34
 
#define EPHY_STATES_XML_FILE    "states.xml"
35
 
#define EPHY_STATES_XML_ROOT    (const xmlChar *)"ephy_states"
36
 
#define EPHY_STATES_XML_VERSION (const xmlChar *)"1.0"
37
 
 
38
 
enum
39
 
{
40
 
        EPHY_NODE_STATE_PROP_NAME = 2,
41
 
        EPHY_NODE_STATE_PROP_WIDTH = 3,
42
 
        EPHY_NODE_STATE_PROP_HEIGHT = 4,
43
 
        EPHY_NODE_STATE_PROP_MAXIMIZE = 5,
44
 
        EPHY_NODE_STATE_PROP_POSITION_X = 6,
45
 
        EPHY_NODE_STATE_PROP_POSITION_Y = 7,
46
 
        EPHY_NODE_STATE_PROP_SIZE = 8,
47
 
        EPHY_NODE_STATE_PROP_POSITION = 9,
48
 
        EPHY_NODE_STATE_PROP_ACTIVE = 10
49
 
};
50
 
 
51
 
static EphyNode *states = NULL;
52
 
static EphyNodeDb *states_db = NULL;
53
 
 
54
 
static void
55
 
ephy_states_save (void)
56
 
{
57
 
        char *xml_file;
58
 
 
59
 
        xml_file = g_build_filename (ephy_dot_dir (),
60
 
                                     EPHY_STATES_XML_FILE,
61
 
                                     NULL);
62
 
 
63
 
        ephy_node_db_write_to_xml_safe
64
 
                (states_db, 
65
 
                 (const xmlChar *)xml_file,
66
 
                 EPHY_STATES_XML_ROOT,
67
 
                 EPHY_STATES_XML_VERSION,
68
 
                 NULL, /* comment */
69
 
                 states, NULL, NULL,
70
 
                 NULL);
71
 
 
72
 
        g_free (xml_file);      
73
 
}
74
 
 
75
 
static EphyNode *
76
 
find_by_name (const char *name)
77
 
{
78
 
        EphyNode *result = NULL;
79
 
        GPtrArray *children;
80
 
        int i;
81
 
 
82
 
        children = ephy_node_get_children (states);
83
 
        for (i = 0; i < children->len; i++)
84
 
        {
85
 
                EphyNode *kid;
86
 
                const char *node_name;
87
 
 
88
 
                kid = g_ptr_array_index (children, i);
89
 
 
90
 
                node_name = ephy_node_get_property_string
91
 
                        (kid, EPHY_NODE_STATE_PROP_NAME);
92
 
                if (strcmp (node_name, name) == 0)
93
 
                {
94
 
                        result = kid;
95
 
                }
96
 
        }
97
 
 
98
 
        return result;
99
 
}
100
 
 
101
 
static void
102
 
ensure_states (void)
103
 
{
104
 
        if (states == NULL)
105
 
        {
106
 
                char *xml_file;
107
 
 
108
 
                xml_file = g_build_filename (ephy_dot_dir (),
109
 
                                             EPHY_STATES_XML_FILE,
110
 
                                             NULL);
111
 
 
112
 
                states_db = ephy_node_db_new (EPHY_NODE_DB_STATES);
113
 
                states = ephy_node_new_with_id (states_db, STATES_NODE_ID);
114
 
                ephy_node_db_load_from_file (states_db, xml_file,
115
 
                                             EPHY_STATES_XML_ROOT,
116
 
                                             EPHY_STATES_XML_VERSION);
117
 
        
118
 
                g_free (xml_file);
119
 
        }
120
 
}
121
 
 
122
 
static void
123
 
ephy_state_window_set_size (GtkWidget *window, EphyNode *node)
124
 
{
125
 
        int width, height, w = -1, h = -1;
126
 
        gboolean maximize, size;
127
 
 
128
 
        width = ephy_node_get_property_int (node, EPHY_NODE_STATE_PROP_WIDTH);
129
 
        height = ephy_node_get_property_int (node, EPHY_NODE_STATE_PROP_HEIGHT);
130
 
        maximize = ephy_node_get_property_boolean (node, EPHY_NODE_STATE_PROP_MAXIMIZE);
131
 
        size = ephy_node_get_property_boolean (node, EPHY_NODE_STATE_PROP_SIZE);
132
 
 
133
 
        gtk_window_get_default_size (GTK_WINDOW (window), &w, &h);
134
 
        if (size && w == -1 && h == -1)
135
 
        {
136
 
                GdkScreen *screen;
137
 
                int screen_width, screen_height;
138
 
 
139
 
                screen = gdk_screen_get_default ();
140
 
                screen_width = gdk_screen_get_width (screen);
141
 
                screen_height = gdk_screen_get_height (screen);
142
 
 
143
 
                gtk_window_set_default_size (GTK_WINDOW (window),
144
 
                                             MIN (width, screen_width),
145
 
                                             MIN (height, screen_height));
146
 
        }
147
 
 
148
 
        if (maximize)
149
 
        {
150
 
                gtk_window_maximize (GTK_WINDOW (window));
151
 
        }
152
 
}
153
 
 
154
 
static void
155
 
ephy_state_window_set_position (GtkWidget *window, EphyNode *node)
156
 
{
157
 
        GdkScreen *screen;
158
 
        int x, y;
159
 
        int screen_width, screen_height;
160
 
        gboolean maximize, size;
161
 
 
162
 
        g_return_if_fail (GTK_IS_WINDOW (window));
163
 
 
164
 
        /* Setting the default size doesn't work when the window is already showing. */
165
 
        g_return_if_fail (!gtk_widget_get_visible (window));
166
 
 
167
 
        maximize = ephy_node_get_property_boolean (node, EPHY_NODE_STATE_PROP_MAXIMIZE);
168
 
        size = ephy_node_get_property_boolean (node, EPHY_NODE_STATE_PROP_POSITION);
169
 
 
170
 
        /* Don't set the position of the window if it is maximized */
171
 
        if ((!maximize) && size)
172
 
        {
173
 
                x = ephy_node_get_property_int (node, EPHY_NODE_STATE_PROP_POSITION_X);
174
 
                y = ephy_node_get_property_int (node, EPHY_NODE_STATE_PROP_POSITION_Y);
175
 
 
176
 
                screen = gtk_window_get_screen (GTK_WINDOW (window));
177
 
                screen_width  = gdk_screen_get_width  (screen);
178
 
                screen_height = gdk_screen_get_height (screen);
179
 
 
180
 
                if ((x <= screen_width) && (y <= screen_height) &&
181
 
                    (x >= 0) && (y >= 0))
182
 
                {
183
 
                        gtk_window_move (GTK_WINDOW (window), x, y);
184
 
                }
185
 
        }
186
 
}
187
 
 
188
 
static void
189
 
ephy_state_save_unmaximized_size (EphyNode *node, int width, int height)
190
 
{
191
 
        ephy_node_set_property_int (node, EPHY_NODE_STATE_PROP_WIDTH,
192
 
                                    width);
193
 
        ephy_node_set_property_int (node, EPHY_NODE_STATE_PROP_HEIGHT,
194
 
                                    height);
195
 
        ephy_node_set_property_boolean (node, EPHY_NODE_STATE_PROP_SIZE,
196
 
                                        TRUE);
197
 
}
198
 
 
199
 
static void
200
 
ephy_state_save_position (EphyNode *node, int x, int y)
201
 
{
202
 
        ephy_node_set_property_int (node, EPHY_NODE_STATE_PROP_POSITION_X,
203
 
                                    x);
204
 
        ephy_node_set_property_int (node, EPHY_NODE_STATE_PROP_POSITION_Y,
205
 
                                    y);
206
 
        ephy_node_set_property_boolean (node, EPHY_NODE_STATE_PROP_POSITION,
207
 
                                        TRUE);
208
 
}
209
 
 
210
 
 
211
 
static void
212
 
ephy_state_window_save_size (GtkWidget *window, EphyNode *node)
213
 
{
214
 
        int width, height;
215
 
        gboolean maximize;
216
 
        GdkWindowState state;
217
 
 
218
 
        state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
219
 
        maximize = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
220
 
 
221
 
        gtk_window_get_size (GTK_WINDOW(window),
222
 
                             &width, &height);
223
 
 
224
 
        if (!maximize)
225
 
        {
226
 
                ephy_state_save_unmaximized_size (node, width, height);
227
 
        }
228
 
        
229
 
        ephy_node_set_property_boolean (node,
230
 
                                        EPHY_NODE_STATE_PROP_MAXIMIZE,
231
 
                                        maximize);
232
 
}
233
 
 
234
 
static void
235
 
ephy_state_window_save_position (GtkWidget *window, EphyNode *node)
236
 
{
237
 
        int x,y;
238
 
        gboolean maximize;
239
 
        GdkWindowState state;
240
 
 
241
 
        state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
242
 
        maximize = ((state & GDK_WINDOW_STATE_MAXIMIZED) > 0);
243
 
 
244
 
        /* Don't save the position if maximized */
245
 
        if (!maximize)
246
 
        {
247
 
                gtk_window_get_position (GTK_WINDOW (window), &x, &y);
248
 
                ephy_state_save_position (node, x, y);
249
 
        }
250
 
}
251
 
 
252
 
static void
253
 
ephy_state_window_save (GtkWidget *widget, EphyNode *node)
254
 
{
255
 
        EphyStateWindowFlags flags;
256
 
 
257
 
        flags = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "state_flags"));
258
 
 
259
 
        if (flags & EPHY_STATE_WINDOW_SAVE_SIZE)
260
 
        {
261
 
                ephy_state_window_save_size (widget, node);
262
 
        }
263
 
 
264
 
        if (flags & EPHY_STATE_WINDOW_SAVE_POSITION)
265
 
        {
266
 
                ephy_state_window_save_position (widget, node);
267
 
        }
268
 
}
269
 
 
270
 
static gboolean
271
 
window_configure_event_cb (GtkWidget *widget,
272
 
                           GdkEventConfigure *event,
273
 
                           EphyNode *node)
274
 
{
275
 
        GdkWindowState state;
276
 
 
277
 
        state = gdk_window_get_state (gtk_widget_get_window (widget));
278
 
 
279
 
        if (!(state & GDK_WINDOW_STATE_FULLSCREEN))
280
 
        {
281
 
                ephy_state_window_save (widget, node);
282
 
        }
283
 
 
284
 
        return FALSE;
285
 
}
286
 
 
287
 
static gboolean
288
 
window_state_event_cb (GtkWidget *widget,
289
 
                       GdkEventWindowState *event,
290
 
                       EphyNode *node)
291
 
{
292
 
        if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN))
293
 
        {
294
 
                ephy_state_window_save (widget, node);
295
 
        }
296
 
 
297
 
        return FALSE;
298
 
}
299
 
 
300
 
static EphyNode *
301
 
create_window_node (const char *name,
302
 
                    int default_width,
303
 
                    int default_height,
304
 
                    gboolean maximize,
305
 
                    EphyStateWindowFlags flags)
306
 
{
307
 
        EphyNode *node;
308
 
 
309
 
        node = ephy_node_new (states_db);
310
 
        ephy_node_add_child (states, node);
311
 
 
312
 
        ephy_node_set_property_string (node, EPHY_NODE_STATE_PROP_NAME,
313
 
                                       name);
314
 
        ephy_node_set_property_boolean (node, EPHY_NODE_STATE_PROP_MAXIMIZE,
315
 
                                        maximize);
316
 
 
317
 
        if (flags & EPHY_STATE_WINDOW_SAVE_SIZE)
318
 
        {
319
 
                ephy_state_save_unmaximized_size (node,
320
 
                                                 default_width,
321
 
                                                 default_height);
322
 
        }
323
 
 
324
 
        if (flags & EPHY_STATE_WINDOW_SAVE_POSITION)
325
 
        {
326
 
                /* Constants for now, these should be default_width
327
 
                   and default_height. */
328
 
                ephy_state_save_position (node, 0, 0);
329
 
        }
330
 
 
331
 
        return node;
332
 
}
333
 
 
334
 
void
335
 
ephy_state_add_window (GtkWidget *window,
336
 
                       const char *name,
337
 
                       int default_width,
338
 
                       int default_height,
339
 
                       gboolean maximize,
340
 
                       EphyStateWindowFlags flags)
341
 
{
342
 
        EphyNode *node;
343
 
 
344
 
        ensure_states ();
345
 
 
346
 
        node = find_by_name (name);
347
 
        if (node == NULL)
348
 
        {
349
 
                node = create_window_node (name, default_width, default_height,
350
 
                                           maximize, flags);
351
 
        }
352
 
 
353
 
        ephy_state_window_set_size (window, node);
354
 
        ephy_state_window_set_position (window, node);
355
 
 
356
 
        g_object_set_data (G_OBJECT (window), "state_flags", GINT_TO_POINTER (flags));
357
 
 
358
 
        g_signal_connect (window, "configure_event",
359
 
                          G_CALLBACK (window_configure_event_cb), node);
360
 
        g_signal_connect (window, "window_state_event",
361
 
                          G_CALLBACK (window_state_event_cb), node);
362
 
}
363
 
 
364
 
static gboolean
365
 
paned_sync_position_cb (GtkWidget *paned,
366
 
                        GParamSpec *pspec,
367
 
                        EphyNode *node)
368
 
{
369
 
        int width;
370
 
 
371
 
        width = gtk_paned_get_position (GTK_PANED (paned));
372
 
        ephy_node_set_property_int (node, EPHY_NODE_STATE_PROP_WIDTH,
373
 
                                    width);
374
 
        return FALSE;
375
 
}
376
 
 
377
 
void
378
 
ephy_state_add_paned (GtkWidget *paned,
379
 
                      const char *name,
380
 
                      int default_width)
381
 
{
382
 
        EphyNode *node;
383
 
        int width;
384
 
 
385
 
        ensure_states ();
386
 
 
387
 
        node = find_by_name (name);
388
 
        if (node == NULL)
389
 
        {
390
 
                node = ephy_node_new (states_db);
391
 
                ephy_node_add_child (states, node);
392
 
 
393
 
                ephy_node_set_property_string (node,
394
 
                                               EPHY_NODE_STATE_PROP_NAME,
395
 
                                               name);
396
 
                ephy_node_set_property_int (node,
397
 
                                            EPHY_NODE_STATE_PROP_WIDTH,
398
 
                                            default_width);
399
 
        }
400
 
 
401
 
        width = ephy_node_get_property_int (node, EPHY_NODE_STATE_PROP_WIDTH);
402
 
        gtk_paned_set_position (GTK_PANED (paned), width);
403
 
 
404
 
        g_signal_connect (paned, "notify::position",
405
 
                          G_CALLBACK (paned_sync_position_cb), node);
406
 
}
407
 
 
408
 
static void
409
 
sync_expander_cb (GtkExpander *expander,
410
 
                  GParamSpec *pspec,
411
 
                  EphyNode *node)
412
 
{
413
 
        gboolean is_expanded;
414
 
 
415
 
        is_expanded = gtk_expander_get_expanded (expander);
416
 
        ephy_node_set_property_boolean (node,
417
 
                                        EPHY_NODE_STATE_PROP_ACTIVE,
418
 
                                        is_expanded);
419
 
}
420
 
 
421
 
static void
422
 
sync_toggle_cb (GtkToggleButton *toggle,
423
 
                GParamSpec *pspec,
424
 
                EphyNode *node)
425
 
{
426
 
        gboolean is_active;
427
 
 
428
 
        is_active = gtk_toggle_button_get_active (toggle);
429
 
        ephy_node_set_property_boolean (node,
430
 
                                        EPHY_NODE_STATE_PROP_ACTIVE,
431
 
                                        is_active);
432
 
}
433
 
 
434
 
void 
435
 
ephy_state_add_expander (GtkWidget *widget,
436
 
                         const char *name,
437
 
                         gboolean default_state)
438
 
{
439
 
        EphyNode *node;
440
 
        gboolean active;
441
 
 
442
 
        ensure_states ();
443
 
 
444
 
        node = find_by_name (name);
445
 
        if (node == NULL)
446
 
        {
447
 
                node = ephy_node_new (states_db);
448
 
                ephy_node_add_child (states, node);
449
 
 
450
 
                ephy_node_set_property_string (node,
451
 
                                               EPHY_NODE_STATE_PROP_NAME,
452
 
                                               name);
453
 
                ephy_node_set_property_boolean (node,
454
 
                                                EPHY_NODE_STATE_PROP_ACTIVE,
455
 
                                                default_state);
456
 
        }
457
 
 
458
 
        active = ephy_node_get_property_boolean
459
 
                (node, EPHY_NODE_STATE_PROP_ACTIVE);
460
 
 
461
 
        if (GTK_IS_TOGGLE_BUTTON (widget))
462
 
        {
463
 
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), active);
464
 
                g_signal_connect (widget, "notify::active",
465
 
                                  G_CALLBACK (sync_toggle_cb), node);
466
 
        }
467
 
        else if (GTK_IS_EXPANDER (widget))
468
 
        {
469
 
                gtk_expander_set_expanded (GTK_EXPANDER (widget), active);
470
 
                g_signal_connect (widget, "notify::expanded",
471
 
                                  G_CALLBACK (sync_expander_cb), node);
472
 
        }
473
 
}
474
 
 
475
 
void
476
 
ephy_state_save (void)
477
 
{
478
 
        if (states)
479
 
        {
480
 
                ephy_states_save ();
481
 
                ephy_node_unref (states);
482
 
                g_object_unref (states_db);
483
 
                states = NULL;
484
 
                states_db = NULL;
485
 
        }
486
 
}