1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright © 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
4 * Copyright © 2003, 2004 Christian Persch
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "ephy-window.h"
26 #include "ephy-type-builtins.h"
27 #include "ephy-embed-type-builtins.h"
28 #include "ephy-command-manager.h"
29 #include "ephy-state.h"
30 #include "ppview-toolbar.h"
31 #include "window-commands.h"
32 #include "ephy-embed-shell.h"
33 #include "ephy-embed-single.h"
34 #include "ephy-shell.h"
35 #include "eel-gconf-extensions.h"
36 #include "ephy-prefs.h"
37 #include "ephy-embed-prefs.h"
38 #include "ephy-zoom.h"
39 #include "ephy-debug.h"
40 #include "ephy-file-helpers.h"
41 #include "ephy-statusbar.h"
42 #include "egg-editable-toolbar.h"
43 #include "ephy-toolbar.h"
44 #include "popup-commands.h"
45 #include "ephy-encoding-menu.h"
46 #include "ephy-tabs-menu.h"
47 #include "ephy-stock-icons.h"
48 #include "ephy-extension.h"
49 #include "ephy-bookmarks-ui.h"
50 #include "ephy-link.h"
52 #include "ephy-notebook.h"
53 #include "ephy-fullscreen-popup.h"
54 #include "ephy-action-helper.h"
55 #include "ephy-find-toolbar.h"
58 #include <glib/gi18n.h>
59 #include <libgnomevfs/gnome-vfs-uri.h>
60 #include <libgnomeui/gnome-stock-icons.h>
62 #include <gdk/gdkkeysyms.h>
63 #include <gtk/gtkactiongroup.h>
64 #include <gtk/gtktoggleaction.h>
65 #include <gtk/gtkuimanager.h>
66 #include <gtk/gtktoggleaction.h>
67 #include <gtk/gtkdialog.h>
68 #include <gtk/gtkmessagedialog.h>
70 #ifdef HAVE_X11_XF86KEYSYM_H
71 #include <X11/XF86keysym.h>
75 #include "ephy-python.h"
78 static void ephy_window_class_init (EphyWindowClass *klass);
79 static void ephy_window_link_iface_init (EphyLinkIface *iface);
80 static void ephy_window_init (EphyWindow *gs);
81 static GObject *ephy_window_constructor (GType type,
82 guint n_construct_properties,
83 GObjectConstructParam *construct_params);
84 static void ephy_window_finalize (GObject *object);
85 static void ephy_window_show (GtkWidget *widget);
86 static EphyTab *ephy_window_open_link (EphyLink *link,
90 static void notebook_switch_page_cb (GtkNotebook *notebook,
91 GtkNotebookPage *page,
94 static void ephy_window_view_statusbar_cb (GtkAction *action,
96 static void ephy_window_view_toolbar_cb (GtkAction *action,
98 static void ephy_window_view_popup_windows_cb (GtkAction *action,
100 static void sync_tab_load_status (EphyTab *tab,
103 static void sync_tab_security (EphyTab *tab,
106 static void sync_tab_zoom (EphyTab *tab,
111 static const GtkActionEntry ephy_menu_entries [] = {
115 { "File", NULL, N_("_File") },
116 { "Edit", NULL, N_("_Edit") },
117 { "View", NULL, N_("_View") },
118 { "Bookmarks", NULL, N_("_Bookmarks") },
119 { "Go", NULL, N_("_Go") },
120 { "Tools", NULL, N_("T_ools") },
121 { "Tabs", NULL, N_("_Tabs") },
122 { "Help", NULL, N_("_Help") },
123 { "Toolbar", NULL, N_("_Toolbars") },
124 { "PopupAction", NULL, "" },
125 { "NotebookPopupAction", NULL, "" },
129 { "FileOpen", GTK_STOCK_OPEN, N_("_Open…"), "<control>O",
131 G_CALLBACK (window_cmd_file_open) },
132 { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("Save _As…"), "<shift><control>S",
133 N_("Save the current page"),
134 G_CALLBACK (window_cmd_file_save_as) },
135 { "FilePrintSetup", STOCK_PRINT_SETUP, N_("Print Set_up…"), NULL,
136 N_("Setup the page settings for printing"),
137 G_CALLBACK (window_cmd_file_print_setup) },
138 { "FilePrintPreview", GTK_STOCK_PRINT_PREVIEW, N_("Print Pre_view"),"<control><shift>P",
140 G_CALLBACK (window_cmd_file_print_preview) },
141 { "FilePrint", GTK_STOCK_PRINT, N_("_Print…"), "<control>P",
142 N_("Print the current page"),
143 G_CALLBACK (window_cmd_file_print) },
144 { "FileSendTo", STOCK_SEND_MAIL, N_("S_end Link by Email…"), NULL,
145 N_("Send a link of the current page"),
146 G_CALLBACK (window_cmd_file_send_to) },
147 { "FileCloseTab", GTK_STOCK_CLOSE, N_("_Close"), "<control>W",
148 N_("Close this tab"),
149 G_CALLBACK (window_cmd_file_close_window) },
153 { "EditUndo", GTK_STOCK_UNDO, N_("_Undo"), "<control>Z",
154 N_("Undo the last action"),
155 G_CALLBACK (window_cmd_edit_undo) },
156 { "EditRedo", GTK_STOCK_REDO, N_("Re_do"), "<shift><control>Z",
157 N_("Redo the last undone action"),
158 G_CALLBACK (window_cmd_edit_redo) },
159 { "EditCut", GTK_STOCK_CUT, N_("Cu_t"), "<control>X",
160 N_("Cut the selection"),
161 G_CALLBACK (window_cmd_edit_cut) },
162 { "EditCopy", GTK_STOCK_COPY, N_("_Copy"), "<control>C",
163 N_("Copy the selection"),
164 G_CALLBACK (window_cmd_edit_copy) },
165 { "EditPaste", GTK_STOCK_PASTE, N_("_Paste"), "<control>V",
166 N_("Paste clipboard"),
167 G_CALLBACK (window_cmd_edit_paste) },
168 { "EditDelete", GTK_STOCK_DELETE, NULL, NULL,
170 G_CALLBACK (window_cmd_edit_delete) },
171 { "EditSelectAll", GTK_STOCK_SELECT_ALL, N_("Select _All"), "<control>A",
172 N_("Select the entire page"),
173 G_CALLBACK (window_cmd_edit_select_all) },
174 { "EditFind", GTK_STOCK_FIND, N_("_Find…"), "<control>F",
175 N_("Find a word or phrase in the page"),
176 G_CALLBACK (window_cmd_edit_find) },
177 { "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G",
178 N_("Find next occurrence of the word or phrase"),
179 G_CALLBACK (window_cmd_edit_find_next) },
180 { "EditFindPrev", NULL, N_("Find Pre_vious"), "<shift><control>G",
181 N_("Find previous occurrence of the word or phrase"),
182 G_CALLBACK (window_cmd_edit_find_prev) },
183 { "EditPersonalData", NULL, N_("P_ersonal Data"), NULL,
184 N_("View and remove cookies and passwords"),
185 G_CALLBACK (window_cmd_edit_personal_data) },
186 #ifdef ENABLE_CERTIFICATE_MANAGER
187 { "EditCertificates", NULL, N_("Certificate_s"), NULL,
188 N_("Manage Certificates"),
189 G_CALLBACK (window_cmd_edit_certificates) },
191 { "EditPrefs", GTK_STOCK_PREFERENCES, N_("P_references"), NULL,
192 N_("Configure the web browser"),
193 G_CALLBACK (window_cmd_edit_prefs) },
197 { "ViewToolbarEditor", NULL, N_("_Customize Toolbars…"), NULL,
198 N_("Customize toolbars"),
199 G_CALLBACK (window_cmd_edit_toolbar) },
200 { "ViewStop", GTK_STOCK_STOP, N_("_Stop"), "Escape",
201 N_("Stop current data transfer"),
202 G_CALLBACK (window_cmd_view_stop) },
203 { "ViewAlwaysStop", GTK_STOCK_STOP, N_("_Stop"), "Escape",
204 NULL, G_CALLBACK (window_cmd_view_stop) },
205 { "ViewReload", GTK_STOCK_REFRESH, N_("_Reload"), "<control>R",
206 N_("Display the latest content of the current page"),
207 G_CALLBACK (window_cmd_view_reload) },
208 { "ViewZoomIn", GTK_STOCK_ZOOM_IN, N_("_Larger Text"), "<control>plus",
209 N_("Increase the text size"),
210 G_CALLBACK (window_cmd_view_zoom_in) },
211 { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, N_("S_maller Text"), "<control>minus",
212 N_("Decrease the text size"),
213 G_CALLBACK (window_cmd_view_zoom_out) },
214 { "ViewZoomNormal", GTK_STOCK_ZOOM_100, N_("_Normal Size"), "<control>0",
215 N_("Use the normal text size"),
216 G_CALLBACK (window_cmd_view_zoom_normal) },
217 { "ViewEncoding", NULL, N_("Text _Encoding"), NULL,
218 N_("Change the text encoding"),
220 { "ViewPageSource", NULL, N_("_Page Source"), "<control>U",
221 N_("View the source code of the page"),
222 G_CALLBACK (window_cmd_view_page_source) },
223 { "ViewPageSecurityInfo", NULL, N_("Page _Security Information…"), NULL,
224 N_("Display security information for the web page"),
225 G_CALLBACK (window_cmd_view_page_security_info) },
229 { "FileBookmarkPage", STOCK_ADD_BOOKMARK, N_("_Add Bookmark…"), "<control>D",
230 N_("Add a bookmark for the current page"),
231 G_CALLBACK (window_cmd_file_bookmark_page) },
232 { "GoBookmarks", EPHY_STOCK_BOOKMARKS, N_("_Edit Bookmarks"), "<control>B",
233 N_("Open the bookmarks window"),
234 G_CALLBACK (window_cmd_go_bookmarks) },
238 { "GoLocation", NULL, N_("_Location…"), "<control>L",
239 N_("Go to a specified location"),
240 G_CALLBACK (window_cmd_go_location) },
241 { "GoHistory", EPHY_STOCK_HISTORY, N_("Hi_story"), "<control>H",
242 N_("Open the history window"),
243 G_CALLBACK (window_cmd_go_history) },
247 { "TabsPrevious", NULL, N_("_Previous Tab"), "<control>Page_Up",
248 N_("Activate previous tab"),
249 G_CALLBACK (window_cmd_tabs_previous) },
250 { "TabsNext", NULL, N_("_Next Tab"), "<control>Page_Down",
251 N_("Activate next tab"),
252 G_CALLBACK (window_cmd_tabs_next) },
253 { "TabsMoveLeft", NULL, N_("Move Tab _Left"), "<shift><control>Page_Up",
254 N_("Move current tab to left"),
255 G_CALLBACK (window_cmd_tabs_move_left) },
256 { "TabsMoveRight", NULL, N_("Move Tab _Right"), "<shift><control>Page_Down",
257 N_("Move current tab to right"),
258 G_CALLBACK (window_cmd_tabs_move_right) },
262 {"HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1",
263 N_("Display web browser help"),
264 G_CALLBACK (window_cmd_help_contents) },
265 { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL,
266 N_("Display credits for the web browser creators"),
267 G_CALLBACK (window_cmd_help_about) },
270 static const GtkToggleActionEntry ephy_menu_toggle_entries [] =
274 { "FileWorkOffline", NULL, N_("_Work Offline"), NULL,
275 N_("Switch to offline mode"),
276 G_CALLBACK (window_cmd_file_work_offline), FALSE },
280 { "ViewToolbar", NULL, N_("_Hide Toolbars"), NULL,
281 N_("Show or hide toolbar"),
282 G_CALLBACK (ephy_window_view_toolbar_cb), FALSE },
283 { "ViewStatusbar", NULL, N_("St_atusbar"), NULL,
284 N_("Show or hide statusbar"),
285 G_CALLBACK (ephy_window_view_statusbar_cb), TRUE },
286 { "ViewFullscreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11",
287 N_("Browse at full screen"),
288 G_CALLBACK (window_cmd_view_fullscreen), FALSE },
289 { "ViewPopupWindows", EPHY_STOCK_POPUPS, N_("Popup _Windows"), NULL,
290 N_("Show or hide unrequested popup windows from this site"),
291 G_CALLBACK (ephy_window_view_popup_windows_cb), FALSE },
292 { "BrowseWithCaret", NULL, N_("Selection Caret"), "F7",
294 G_CALLBACK (window_cmd_browse_with_caret), FALSE }
297 static const GtkActionEntry ephy_popups_entries [] = {
300 { "ContextBookmarkPage", STOCK_ADD_BOOKMARK, N_("Add Boo_kmark…"), "<control>D",
301 N_("Add a bookmark for the current page"),
302 G_CALLBACK (window_cmd_file_bookmark_page) },
304 /* Framed document */
306 { "OpenFrame", NULL, N_("Show Only _This Frame"), NULL,
307 N_("Show only this frame in this window"),
308 G_CALLBACK (popup_cmd_open_frame) },
312 { "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL,
313 N_("Open link in this window"),
314 G_CALLBACK (popup_cmd_open_link) },
315 { "OpenLinkInNewWindow", NULL, N_("Open Link in New _Window"), NULL,
316 N_("Open link in a new window"),
317 G_CALLBACK (popup_cmd_link_in_new_window) },
318 { "OpenLinkInNewTab", NULL, N_("Open Link in New _Tab"), NULL,
319 N_("Open link in a new tab"),
320 G_CALLBACK (popup_cmd_link_in_new_tab) },
321 { "DownloadLink", STOCK_DOWNLOAD, N_("_Download Link"), NULL,
322 NULL, G_CALLBACK (popup_cmd_download_link) },
323 { "DownloadLinkAs", GTK_STOCK_SAVE_AS, N_("_Save Link As…"), NULL,
324 N_("Save link with a different name"),
325 G_CALLBACK (popup_cmd_download_link_as) },
326 { "BookmarkLink", STOCK_ADD_BOOKMARK, N_("_Bookmark Link…"),
327 NULL, NULL, G_CALLBACK (popup_cmd_bookmark_link) },
328 { "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
329 NULL, G_CALLBACK (popup_cmd_copy_link_address) },
333 /* This is on the context menu on a mailto: link and opens the mail program */
334 { "SendEmail", GTK_STOCK_OPEN, N_("_Send Email…"),
335 NULL, NULL, G_CALLBACK (popup_cmd_open_link) },
336 { "CopyEmailAddress", NULL, N_("_Copy Email Address"), NULL,
337 NULL, G_CALLBACK (popup_cmd_copy_link_address) },
341 { "OpenImage", GTK_STOCK_OPEN, N_("Open _Image"), NULL,
342 NULL, G_CALLBACK (popup_cmd_open_image) },
343 { "SaveImageAs", GTK_STOCK_SAVE_AS, N_("_Save Image As…"), NULL,
344 NULL, G_CALLBACK (popup_cmd_save_image_as) },
345 { "SetImageAsBackground", NULL, N_("_Use Image As Background"), NULL,
346 NULL, G_CALLBACK (popup_cmd_set_image_as_background) },
347 { "CopyImageLocation", NULL, N_("Copy I_mage Address"), NULL,
348 NULL, G_CALLBACK (popup_cmd_copy_image_location) },
349 { "StartImageAnimation", NULL, N_("St_art Animation"), NULL,
351 { "StopImageAnimation", NULL, N_("St_op Animation"), NULL,
358 GdkModifierType modifier;
360 gboolean fromToolbar;
361 } extra_keybindings [] = {
362 { GDK_s, GDK_CONTROL_MASK, "FileSaveAs", FALSE },
363 { GDK_R, GDK_CONTROL_MASK |
364 GDK_SHIFT_MASK, "ViewReload", FALSE },
365 /* Support all the MSIE tricks as well ;) */
366 { GDK_F5, 0, "ViewReload", FALSE },
367 { GDK_F5, GDK_CONTROL_MASK, "ViewReload", FALSE },
368 { GDK_F5, GDK_SHIFT_MASK, "ViewReload", FALSE },
369 { GDK_F5, GDK_CONTROL_MASK |
370 GDK_SHIFT_MASK, "ViewReload", FALSE },
371 { GDK_KP_Add, GDK_CONTROL_MASK, "ViewZoomIn", FALSE },
372 { GDK_KP_Subtract, GDK_CONTROL_MASK, "ViewZoomOut", FALSE },
373 { GDK_equal, GDK_CONTROL_MASK, "ViewZoomIn", FALSE },
374 /* These keys are a bit strange: when pressed with no modifiers, they emit
375 * KP_PageUp/Down Control; when pressed with Control+Shift they are KP_9/3,
376 * when NumLock is on they are KP_9/3 and with NumLock and Control+Shift
377 * They're KP_PageUp/Down again!
379 { GDK_KP_Left, GDK_MOD1_MASK /*Alt*/, "NavigationBack", TRUE },
380 { GDK_KP_4, GDK_MOD1_MASK /*Alt*/, "NavigationBack", TRUE },
381 { GDK_KP_Right, GDK_MOD1_MASK /*Alt*/, "NavigationForward", TRUE },
382 { GDK_KP_6, GDK_MOD1_MASK /*Alt*/, "NavigationForward", TRUE },
383 { GDK_KP_Up, GDK_MOD1_MASK /*Alt*/, "NavigationUp", TRUE },
384 { GDK_KP_8, GDK_MOD1_MASK /*Alt*/, "NavigationUp", TRUE },
385 { GDK_KP_Page_Up, GDK_CONTROL_MASK, "TabsPrevious", FALSE },
386 { GDK_KP_9, GDK_CONTROL_MASK, "TabsPrevious", FALSE },
387 { GDK_KP_Page_Down, GDK_CONTROL_MASK, "TabsNext", FALSE },
388 { GDK_KP_3, GDK_CONTROL_MASK, "TabsNext", FALSE },
389 { GDK_KP_Page_Up, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "TabsMoveLeft", FALSE },
390 { GDK_KP_9, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "TabsMoveLeft", FALSE },
391 { GDK_KP_Page_Down, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "TabsMoveRight", FALSE },
392 { GDK_KP_3, GDK_SHIFT_MASK | GDK_CONTROL_MASK, "TabsMoveRight", FALSE },
393 #ifdef HAVE_X11_XF86KEYSYM_H
394 { XF86XK_Back, 0, "NavigationBack", TRUE },
395 { XF86XK_Favorites, 0, "GoBookmarks", FALSE },
396 { XF86XK_Forward, 0, "NavigationForward", TRUE },
397 { XF86XK_Go, 0, "GoLocation", FALSE },
398 { XF86XK_History, 0, "GoHistory", FALSE },
399 { XF86XK_HomePage, 0, "GoHome", TRUE },
400 { XF86XK_OpenURL, 0, "GoLocation", FALSE },
401 { XF86XK_AddFavorite, 0, "FileBookmarkPage", FALSE },
402 { XF86XK_Refresh, 0, "ViewReload", FALSE },
403 { XF86XK_Reload, 0, "ViewReload", FALSE },
404 { XF86XK_Search, 0, "EditFind", FALSE },
405 { XF86XK_Send, 0, "FileSendTo", FALSE },
406 { XF86XK_Start, 0, "GoHome", TRUE },
407 { XF86XK_Stop, 0, "ViewStop", FALSE },
408 { XF86XK_ZoomIn, 0, "ViewZoomIn", FALSE },
409 { XF86XK_ZoomOut, 0, "ViewZoomOut", FALSE }
410 /* FIXME: what about ScrollUp, ScrollDown, Menu*, Option, LogOff, Save,.. any others? */
411 #endif /* HAVE_X11_XF86KEYSYM_H */
414 #define CONF_LOCKDOWN_HIDE_MENUBAR "/apps/epiphany/lockdown/hide_menubar"
416 #define BOOKMARKS_MENU_PATH "/menubar/BookmarksMenu"
418 #define SETTINGS_CONNECTION_DATA_KEY "EphyWindowSettings"
420 /* Until https://bugzilla.mozilla.org/show_bug.cgi?id=296002 is fixed */
422 #define EPHY_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_WINDOW, EphyWindowPrivate))
424 struct _EphyWindowPrivate
426 GtkWidget *main_vbox;
427 GtkWidget *menu_dock;
428 GtkWidget *fullscreen_popup;
429 EphyToolbar *toolbar;
430 GtkWidget *statusbar;
431 GtkUIManager *manager;
432 GtkActionGroup *action_group;
433 GtkActionGroup *popups_action_group;
434 EphyEncodingMenu *enc_menu;
435 EphyTabsMenu *tabs_menu;
436 PPViewToolbar *ppview_toolbar;
437 GtkNotebook *notebook;
439 EphyFindToolbar *find_toolbar;
441 guint tab_message_cid;
442 guint help_message_cid;
443 EphyEmbedChrome chrome;
444 guint idle_resize_handler;
445 GHashTable *tabs_to_remove;
446 EphyEmbedEvent *context_event;
449 guint browse_with_caret_notifier_id;
450 guint allow_popups_notifier_id;
452 guint menubar_accel_keyval;
453 guint menubar_accel_modifier;
457 guint fullscreen_mode : 1;
459 guint should_save_chrome : 1;
462 guint key_theme_is_emacs : 1;
474 /* Make sure not to overlap with those in ephy-lockdown.c */
477 SENS_FLAG_CHROME = 1 << 0,
478 SENS_FLAG_CONTEXT = 1 << 1,
479 SENS_FLAG_DOCUMENT = 1 << 2,
480 SENS_FLAG_LOADING = 1 << 3,
481 SENS_FLAG_NAVIGATION = 1 << 4
484 static GObjectClass *parent_class = NULL;
487 ephy_window_get_type (void)
489 static GType type = 0;
491 if (G_UNLIKELY (type == 0))
493 const GTypeInfo our_info =
495 sizeof (EphyWindowClass),
496 NULL, /* base_init */
497 NULL, /* base_finalize */
498 (GClassInitFunc) ephy_window_class_init,
500 NULL, /* class_data */
503 (GInstanceInitFunc) ephy_window_init
505 const GInterfaceInfo link_info =
507 (GInterfaceInitFunc) ephy_window_link_iface_init,
512 type = g_type_register_static (GTK_TYPE_WINDOW,
516 g_type_add_interface_static (type,
525 settings_change_notify (GtkSettings *settings,
528 EphyWindowPrivate *priv = window->priv;
529 char *key_theme_name, *menubar_accel_accel;
531 g_object_get (settings,
532 "gtk-key-theme-name", &key_theme_name,
533 "gtk-menu-bar-accel", &menubar_accel_accel,
536 g_return_if_fail (menubar_accel_accel != NULL);
538 if (menubar_accel_accel != NULL && menubar_accel_accel[0] != '\0')
540 gtk_accelerator_parse (menubar_accel_accel,
541 &priv->menubar_accel_keyval,
542 &priv->menubar_accel_modifier);
543 if (priv->menubar_accel_keyval == 0)
545 g_warning ("Failed to parse menu bar accelerator '%s'\n",
546 menubar_accel_accel);
551 priv->menubar_accel_keyval = 0;
552 priv->menubar_accel_modifier = 0;
555 priv->key_theme_is_emacs =
557 g_ascii_strcasecmp (key_theme_name, "Emacs") == 0;
559 g_free (key_theme_name);
560 g_free (menubar_accel_accel);
564 settings_changed_cb (GtkSettings *settings)
568 /* FIXME: multi-head */
569 list = gtk_window_list_toplevels ();
571 for (l = list; l != NULL; l = l->next)
573 if (EPHY_IS_WINDOW (l->data))
575 settings_change_notify (settings, l->data);
583 destroy_fullscreen_popup (EphyWindow *window)
585 if (window->priv->fullscreen_popup != NULL)
587 gtk_widget_destroy (window->priv->fullscreen_popup);
588 window->priv->fullscreen_popup = NULL;
593 add_widget (GtkUIManager *manager,
597 gtk_box_pack_start (GTK_BOX (window->priv->menu_dock),
598 widget, FALSE, FALSE, 0);
602 exit_fullscreen_clicked_cb (EphyWindow *window)
606 action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
607 g_return_if_fail (action != NULL);
609 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
613 get_toolbar_visibility (EphyWindow *window)
615 return ((window->priv->chrome & EPHY_EMBED_CHROME_TOOLBAR) != 0) &&
616 !window->priv->ppv_mode;
620 get_chromes_visibility (EphyWindow *window,
621 gboolean *show_menubar,
622 gboolean *show_statusbar,
623 gboolean *show_toolbar,
624 gboolean *show_tabsbar)
626 EphyWindowPrivate *priv = window->priv;
627 EphyEmbedChrome flags = priv->chrome;
629 if (window->priv->ppv_mode)
631 *show_menubar = *show_statusbar
636 else if (window->priv->fullscreen_mode)
638 *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0;
639 *show_menubar = *show_statusbar = FALSE;
640 *show_tabsbar = !priv->is_popup;
644 *show_menubar = (flags & EPHY_EMBED_CHROME_MENUBAR) != 0;
645 *show_statusbar = (flags & EPHY_EMBED_CHROME_STATUSBAR) != 0;
646 *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0;
647 *show_tabsbar = !priv->is_popup;
652 sync_chromes_visibility (EphyWindow *window)
654 EphyWindowPrivate *priv = window->priv;
656 gboolean show_statusbar, show_menubar, show_toolbar, show_tabsbar;
658 if (priv->closing) return;
660 get_chromes_visibility (window, &show_menubar,
661 &show_statusbar, &show_toolbar,
664 menubar = gtk_ui_manager_get_widget (window->priv->manager, "/menubar");
665 g_assert (menubar != NULL);
667 g_object_set (menubar, "visible", show_menubar, NULL);
668 g_object_set (priv->toolbar, "visible", show_toolbar, NULL);
669 g_object_set (priv->statusbar, "visible", show_statusbar, NULL);
671 ephy_notebook_set_show_tabs (EPHY_NOTEBOOK (priv->notebook), show_tabsbar);
673 if (priv->fullscreen_popup != NULL)
675 g_object_set (priv->fullscreen_popup, "visible", !show_toolbar, NULL);
680 ephy_window_fullscreen (EphyWindow *window)
682 EphyWindowPrivate *priv = window->priv;
686 gboolean lockdown_fs;
688 priv->fullscreen_mode = TRUE;
690 lockdown_fs = eel_gconf_get_boolean (CONF_LOCKDOWN_FULLSCREEN);
692 popup = ephy_fullscreen_popup_new (window);
693 ephy_fullscreen_popup_set_show_leave
694 (EPHY_FULLSCREEN_POPUP (popup), !lockdown_fs);
695 priv->fullscreen_popup = popup;
696 g_signal_connect_swapped (popup, "exit-clicked",
697 G_CALLBACK (exit_fullscreen_clicked_cb), window);
699 action = gtk_action_group_get_action (priv->action_group, "ViewPageSecurityInfo");
700 g_signal_connect_swapped (popup, "lock-clicked",
701 G_CALLBACK (gtk_action_activate), action);
704 tab = ephy_window_get_active_tab (window);
705 sync_tab_load_status (tab, NULL, window);
706 sync_tab_security (tab, NULL, window);
708 egg_editable_toolbar_set_model
709 (EGG_EDITABLE_TOOLBAR (priv->toolbar),
711 ephy_shell_get_toolbars_model (ephy_shell, TRUE)));
713 ephy_toolbar_set_show_leave_fullscreen (priv->toolbar,
716 sync_chromes_visibility (window);
720 ephy_window_unfullscreen (EphyWindow *window)
722 window->priv->fullscreen_mode = FALSE;
724 destroy_fullscreen_popup (window);
726 ephy_toolbar_set_show_leave_fullscreen (window->priv->toolbar, FALSE);
728 egg_editable_toolbar_set_model
729 (EGG_EDITABLE_TOOLBAR (window->priv->toolbar),
731 ephy_shell_get_toolbars_model (ephy_shell, FALSE)));
733 sync_chromes_visibility (window);
737 construct_confirm_close_dialog (EphyWindow *window)
741 dialog = gtk_message_dialog_new
742 (GTK_WINDOW (window),
746 _("There are unsubmitted changes to form elements"));
748 gtk_message_dialog_format_secondary_text
749 (GTK_MESSAGE_DIALOG (dialog),
750 _("If you close the document anyway, "
751 "you will lose that information."));
753 gtk_dialog_add_button (GTK_DIALOG (dialog),
754 _("Close _Document"), GTK_RESPONSE_ACCEPT);
756 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
758 /* FIXME gtk_window_set_title (GTK_WINDOW (dialog), _("Close Document?")); */
759 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
761 gtk_window_group_add_window (GTK_WINDOW (window)->group, GTK_WINDOW (dialog));
767 confirm_close_with_modified_forms (EphyWindow *window)
772 dialog = construct_confirm_close_dialog (window);
773 response = gtk_dialog_run (GTK_DIALOG (dialog));
775 gtk_widget_destroy (dialog);
777 return response == GTK_RESPONSE_ACCEPT;
781 menubar_deactivate_cb (GtkWidget *menubar,
784 g_signal_handlers_disconnect_by_func
785 (menubar, G_CALLBACK (menubar_deactivate_cb), window);
787 gtk_menu_shell_deselect (GTK_MENU_SHELL (menubar));
789 sync_chromes_visibility (window);
793 ephy_window_key_press_event (GtkWidget *widget,
796 EphyWindow *window = EPHY_WINDOW (widget);
797 EphyWindowPrivate *priv = window->priv;
798 GtkWidget *menubar, *focus_widget;
799 gboolean shortcircuit = FALSE, force_chain = FALSE, handled = FALSE;
800 guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
803 /* In an attempt to get the mozembed playing nice with things like emacs keybindings
804 * we are passing important events to the focused child widget before letting the window's
805 * base handler see them. This is *completely against* stated gtk2 policy but the
806 * 'correct' behaviour is exceptionally useless. We need to keep an eye out for
807 * unexpected consequences of this decision. IME's should be a high concern, but
808 * considering that the IME folks complained about the upside-down event propagation
809 * rules, we might be doing them a favour.
811 * We achieve this by first evaluating the event to see if it's important, and if
812 * so, we get the focus widget and attempt to get the widget to handle that event.
813 * If the widget does handle it, we're done (unless force_chain is true, in which
814 * case the event is handled as normal in addition to being sent to the focus
815 * widget), otherwise the event follows the normal handling path.
818 if (event->keyval == GDK_Escape && modifier == 0)
820 /* Always pass Escape to both the widget, and the parent */
824 else if (priv->key_theme_is_emacs &&
825 (modifier == GDK_CONTROL_MASK) &&
827 /* But don't pass Ctrl+Enter twice */
828 event->keyval != GDK_Return &&
829 event->keyval != GDK_KP_Enter &&
830 event->keyval != GDK_ISO_Enter)
832 /* Pass CTRL+letter characters to the widget */
838 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
840 if (GTK_IS_WIDGET (focus_widget))
842 handled = gtk_widget_event (focus_widget,
846 if (handled && !force_chain)
852 /* Handle accelerators that we want bound, but aren't associated with
854 for (i = 0; i < G_N_ELEMENTS (extra_keybindings); i++)
856 if (event->keyval == extra_keybindings[i].keyval &&
857 modifier == extra_keybindings[i].modifier)
859 GtkAction * action = gtk_action_group_get_action
860 (extra_keybindings[i].fromToolbar ?
861 ephy_toolbar_get_action_group (priv->toolbar) :
863 extra_keybindings[i].action);
864 if (gtk_action_is_sensitive (action))
866 gtk_action_activate (action);
873 /* Don't activate menubar in ppv mode, or in lockdown mode */
874 if (priv->ppv_mode || eel_gconf_get_boolean (CONF_LOCKDOWN_HIDE_MENUBAR))
876 return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
879 /* Show and activate the menubar, if it isn't visible */
880 if (priv->menubar_accel_keyval != 0 &&
881 event->keyval == priv->menubar_accel_keyval &&
882 modifier == priv->menubar_accel_modifier)
884 menubar = gtk_ui_manager_get_widget (window->priv->manager, "/menubar");
885 g_return_val_if_fail (menubar != NULL , FALSE);
887 if (!GTK_WIDGET_VISIBLE (menubar))
889 g_signal_connect (menubar, "deactivate",
890 G_CALLBACK (menubar_deactivate_cb), window);
892 gtk_widget_show (menubar);
893 gtk_menu_shell_select_first (GTK_MENU_SHELL (menubar), FALSE);
899 return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
903 ephy_window_delete_event (GtkWidget *widget,
906 EphyWindow *window = EPHY_WINDOW (widget);
907 EphyWindowPrivate *priv = window->priv;
908 EphyTab *modified_tab = NULL;
910 gboolean modified = FALSE;
912 /* We ignore the delete_event if the disable_quit lockdown has been set
914 if (eel_gconf_get_boolean("/apps/epiphany/lockdown/disable_quit")) return TRUE;
916 /* Workaround a crash when closing a window while in print preview mode. See
917 * mozilla bug #241809. /
918 * Go back to normal mode instead of closing, see bug #326136.
924 embed = ephy_window_get_active_embed (window);
925 ephy_embed_set_print_preview_mode (embed, FALSE);
927 ephy_window_set_print_preview (window, FALSE);
932 tabs = ephy_window_get_tabs (window);
933 for (l = tabs; l != NULL; l = l->next)
935 EphyTab *tab = (EphyTab *) l->data;
938 g_return_val_if_fail (EPHY_IS_TAB (tab), FALSE);
940 embed = ephy_tab_get_embed (tab);
941 g_return_val_if_fail (EPHY_IS_EMBED (embed), FALSE);
943 if (ephy_embed_has_modified_forms (embed))
954 /* jump to the first tab with modified forms */
955 ephy_window_jump_to_tab (window, modified_tab);
957 if (confirm_close_with_modified_forms (window) == FALSE)
959 /* stop window close */
964 /* See bug #114689 */
965 gtk_widget_hide (widget);
967 /* proceed with window close */
968 if (GTK_WIDGET_CLASS (parent_class)->delete_event)
970 return GTK_WIDGET_CLASS (parent_class)->delete_event (widget, event);
977 update_popup_actions_visibility (EphyWindow *window,
982 GtkActionGroup *action_group;
984 action_group = window->priv->popups_action_group;
986 action = gtk_action_group_get_action (action_group, "OpenImage");
987 gtk_action_set_visible (action, is_image);
988 action = gtk_action_group_get_action (action_group, "SaveImageAs");
989 gtk_action_set_visible (action, is_image);
990 action = gtk_action_group_get_action (action_group, "SetImageAsBackground");
991 gtk_action_set_visible (action, is_image);
992 action = gtk_action_group_get_action (action_group, "CopyImageLocation");
993 gtk_action_set_visible (action, is_image);
995 action = gtk_action_group_get_action (action_group, "OpenFrame");
996 gtk_action_set_visible (action, is_frame);
1000 update_edit_actions_sensitivity (EphyWindow *window, gboolean hide)
1002 GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
1003 GtkActionGroup *action_group;
1005 gboolean can_copy, can_cut, can_undo, can_redo, can_paste;
1007 if (GTK_IS_EDITABLE (widget))
1009 gboolean has_selection;
1011 has_selection = gtk_editable_get_selection_bounds
1012 (GTK_EDITABLE (widget), NULL, NULL);
1014 can_copy = has_selection;
1015 can_cut = has_selection;
1024 embed = ephy_window_get_active_embed (window);
1025 g_return_if_fail (embed != NULL);
1027 can_copy = ephy_command_manager_can_do_command
1028 (EPHY_COMMAND_MANAGER (embed), "cmd_copy");
1029 can_cut = ephy_command_manager_can_do_command
1030 (EPHY_COMMAND_MANAGER (embed), "cmd_cut");
1031 can_paste = ephy_command_manager_can_do_command
1032 (EPHY_COMMAND_MANAGER (embed), "cmd_paste");
1033 can_undo = ephy_command_manager_can_do_command
1034 (EPHY_COMMAND_MANAGER (embed), "cmd_undo");
1035 can_redo = ephy_command_manager_can_do_command
1036 (EPHY_COMMAND_MANAGER (embed), "cmd_redo");
1039 action_group = window->priv->action_group;
1041 action = gtk_action_group_get_action (action_group, "EditCopy");
1042 gtk_action_set_sensitive (action, can_copy);
1043 gtk_action_set_visible (action, !hide || can_copy);
1044 action = gtk_action_group_get_action (action_group, "EditCut");
1045 gtk_action_set_sensitive (action, can_cut);
1046 gtk_action_set_visible (action, !hide || can_cut);
1047 action = gtk_action_group_get_action (action_group, "EditPaste");
1048 gtk_action_set_sensitive (action, can_paste);
1049 gtk_action_set_visible (action, !hide || can_paste);
1050 action = gtk_action_group_get_action (action_group, "EditUndo");
1051 gtk_action_set_sensitive (action, can_undo);
1052 gtk_action_set_visible (action, !hide || can_undo);
1053 action = gtk_action_group_get_action (action_group, "EditRedo");
1054 gtk_action_set_sensitive (action, can_redo);
1055 gtk_action_set_visible (action, !hide || can_redo);
1059 enable_edit_actions_sensitivity (EphyWindow *window)
1061 GtkActionGroup *action_group;
1064 action_group = window->priv->action_group;
1066 action = gtk_action_group_get_action (action_group, "EditCopy");
1067 gtk_action_set_sensitive (action, TRUE);
1068 gtk_action_set_visible (action, TRUE);
1069 action = gtk_action_group_get_action (action_group, "EditCut");
1070 gtk_action_set_sensitive (action, TRUE);
1071 gtk_action_set_visible (action, TRUE);
1072 action = gtk_action_group_get_action (action_group, "EditPaste");
1073 gtk_action_set_sensitive (action, TRUE);
1074 gtk_action_set_visible (action, TRUE);
1075 action = gtk_action_group_get_action (action_group, "EditUndo");
1076 gtk_action_set_sensitive (action, TRUE);
1077 gtk_action_set_visible (action, TRUE);
1078 action = gtk_action_group_get_action (action_group, "EditRedo");
1079 gtk_action_set_sensitive (action, TRUE);
1080 gtk_action_set_visible (action, TRUE);
1084 edit_menu_show_cb (GtkWidget *menu,
1087 update_edit_actions_sensitivity (window, FALSE);
1091 edit_menu_hide_cb (GtkWidget *menu,
1094 enable_edit_actions_sensitivity (window);
1098 init_menu_updaters (EphyWindow *window)
1100 GtkWidget *edit_menu_item, *edit_menu;
1102 edit_menu_item = gtk_ui_manager_get_widget
1103 (window->priv->manager, "/menubar/EditMenu");
1104 edit_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (edit_menu_item));
1106 g_signal_connect (edit_menu, "show",
1107 G_CALLBACK (edit_menu_show_cb), window);
1108 g_signal_connect (edit_menu, "hide",
1109 G_CALLBACK (edit_menu_hide_cb), window);
1113 menu_item_select_cb (GtkMenuItem *proxy,
1119 action = g_object_get_data (G_OBJECT (proxy), "gtk-action");
1120 g_return_if_fail (action != NULL);
1122 g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
1125 gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar),
1126 window->priv->help_message_cid, message);
1132 menu_item_deselect_cb (GtkMenuItem *proxy,
1135 gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
1136 window->priv->help_message_cid);
1140 tool_item_enter_cb (GtkWidget *proxy,
1141 GdkEventCrossing *event,
1144 if (event->mode == GDK_CROSSING_NORMAL)
1150 item = GTK_TOOL_ITEM (gtk_widget_get_ancestor (proxy, GTK_TYPE_TOOL_ITEM));
1152 action = g_object_get_data (G_OBJECT (item), "gtk-action");
1153 g_return_val_if_fail (action != NULL, FALSE);
1155 g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
1158 gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar),
1159 window->priv->help_message_cid, message);
1168 tool_item_leave_cb (GtkWidget *proxy,
1169 GdkEventCrossing *event,
1172 if (event->mode == GDK_CROSSING_NORMAL)
1174 gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
1175 window->priv->help_message_cid);
1182 tool_item_drag_begin_cb (GtkWidget *widget,
1183 GdkDragContext *context,
1186 gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
1187 window->priv->help_message_cid);
1192 connect_tool_item (GtkWidget *proxy, EphyWindow *window)
1194 if (GTK_IS_CONTAINER (proxy))
1196 gtk_container_foreach (GTK_CONTAINER (proxy),
1197 (GtkCallback) connect_tool_item,
1201 g_signal_connect (proxy, "drag_begin",
1202 G_CALLBACK (tool_item_drag_begin_cb), window);
1203 g_signal_connect (proxy, "enter-notify-event",
1204 G_CALLBACK (tool_item_enter_cb), window);
1205 g_signal_connect (proxy, "leave-notify-event",
1206 G_CALLBACK (tool_item_leave_cb), window);
1210 disconnect_tool_item (GtkWidget *proxy, EphyWindow *window)
1212 if (GTK_IS_CONTAINER (proxy))
1214 gtk_container_foreach (GTK_CONTAINER (proxy),
1215 (GtkCallback) disconnect_tool_item,
1219 g_signal_handlers_disconnect_by_func
1220 (proxy, G_CALLBACK (tool_item_enter_cb), window);
1221 g_signal_handlers_disconnect_by_func
1222 (proxy, G_CALLBACK (tool_item_leave_cb), window);
1226 disconnect_proxy_cb (GtkUIManager *manager,
1231 if (GTK_IS_MENU_ITEM (proxy))
1233 g_signal_handlers_disconnect_by_func
1234 (proxy, G_CALLBACK (menu_item_select_cb), window);
1235 g_signal_handlers_disconnect_by_func
1236 (proxy, G_CALLBACK (menu_item_deselect_cb), window);
1238 else if (GTK_IS_TOOL_ITEM (proxy))
1240 disconnect_tool_item (proxy, window);
1245 connect_proxy_cb (GtkUIManager *manager,
1250 if (GTK_IS_MENU_ITEM (proxy))
1252 g_signal_connect (proxy, "select",
1253 G_CALLBACK (menu_item_select_cb), window);
1254 g_signal_connect (proxy, "deselect",
1255 G_CALLBACK (menu_item_deselect_cb), window);
1257 else if (GTK_IS_TOOL_ITEM (proxy))
1259 connect_tool_item (proxy, window);
1264 update_chromes_actions (EphyWindow *window)
1266 GtkActionGroup *action_group = window->priv->action_group;
1268 gboolean show_statusbar, show_menubar, show_toolbar, show_tabsbar;
1270 get_chromes_visibility (window, &show_menubar,
1271 &show_statusbar, &show_toolbar,
1274 action = gtk_action_group_get_action (action_group, "ViewToolbar");
1275 g_signal_handlers_block_by_func (G_OBJECT (action),
1276 G_CALLBACK (ephy_window_view_toolbar_cb),
1278 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !show_toolbar);
1279 g_signal_handlers_unblock_by_func (G_OBJECT (action),
1280 G_CALLBACK (ephy_window_view_toolbar_cb),
1283 action = gtk_action_group_get_action (action_group, "ViewStatusbar");
1284 g_signal_handlers_block_by_func (G_OBJECT (action),
1285 G_CALLBACK (ephy_window_view_statusbar_cb),
1287 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), show_statusbar);
1288 g_signal_handlers_unblock_by_func (G_OBJECT (action),
1289 G_CALLBACK (ephy_window_view_statusbar_cb),
1294 setup_ui_manager (EphyWindow *window)
1296 GtkActionGroup *action_group;
1298 GtkUIManager *manager;
1300 window->priv->main_vbox = gtk_vbox_new (FALSE, 0);
1301 gtk_widget_show (window->priv->main_vbox);
1302 gtk_container_add (GTK_CONTAINER (window),
1303 window->priv->main_vbox);
1305 window->priv->menu_dock = gtk_vbox_new (FALSE, 0);
1306 gtk_widget_show (window->priv->menu_dock);
1307 gtk_box_pack_start (GTK_BOX (window->priv->main_vbox),
1308 GTK_WIDGET (window->priv->menu_dock),
1311 manager = gtk_ui_manager_new ();
1313 g_signal_connect (manager, "connect_proxy",
1314 G_CALLBACK (connect_proxy_cb), window);
1315 g_signal_connect (manager, "disconnect_proxy",
1316 G_CALLBACK (disconnect_proxy_cb), window);
1318 action_group = gtk_action_group_new ("WindowActions");
1319 gtk_action_group_set_translation_domain (action_group, NULL);
1320 gtk_action_group_add_actions (action_group, ephy_menu_entries,
1321 G_N_ELEMENTS (ephy_menu_entries), window);
1322 gtk_action_group_add_toggle_actions (action_group,
1323 ephy_menu_toggle_entries,
1324 G_N_ELEMENTS (ephy_menu_toggle_entries),
1326 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1327 window->priv->action_group = action_group;
1328 g_object_unref (action_group);
1330 action = gtk_action_group_get_action (action_group, "FileOpen");
1331 g_object_set (action, "short_label", _("Open"), NULL);
1332 action = gtk_action_group_get_action (action_group, "FileSaveAs");
1333 g_object_set (action, "short_label", _("Save As"), NULL);
1334 action = gtk_action_group_get_action (action_group, "FilePrint");
1335 g_object_set (action, "short_label", _("Print"), NULL);
1336 action = gtk_action_group_get_action (action_group, "FileBookmarkPage");
1337 g_object_set (action, "short_label", _("Bookmark"), NULL);
1338 action = gtk_action_group_get_action (action_group, "EditFind");
1339 g_object_set (action, "short_label", _("Find"), NULL);
1340 action = gtk_action_group_get_action (action_group, "GoBookmarks");
1341 g_object_set (action, "short_label", _("Bookmarks"), NULL);
1343 action = gtk_action_group_get_action (action_group, "EditFind");
1344 g_object_set (action, "is_important", TRUE, NULL);
1345 action = gtk_action_group_get_action (action_group, "GoBookmarks");
1346 g_object_set (action, "is_important", TRUE, NULL);
1348 action = gtk_action_group_get_action (action_group, "ViewEncoding");
1349 g_object_set (action, "hide_if_empty", FALSE, NULL);
1350 action = gtk_action_group_get_action (action_group, "ViewZoomIn");
1351 /* Translators: This refers to text size */
1352 g_object_set (action, "short-label", _("Larger"), NULL);
1353 action = gtk_action_group_get_action (action_group, "ViewZoomOut");
1354 /* Translators: This refers to text size */
1355 g_object_set (action, "short-label", _("Smaller"), NULL);
1357 action_group = gtk_action_group_new ("PopupsActions");
1358 gtk_action_group_set_translation_domain (action_group, NULL);
1359 gtk_action_group_add_actions (action_group, ephy_popups_entries,
1360 G_N_ELEMENTS (ephy_popups_entries), window);
1361 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1362 window->priv->popups_action_group = action_group;
1363 g_object_unref (action_group);
1365 window->priv->manager = manager;
1366 g_signal_connect (manager, "add_widget", G_CALLBACK (add_widget), window);
1367 gtk_window_add_accel_group (GTK_WINDOW (window),
1368 gtk_ui_manager_get_accel_group (manager));
1372 sync_tab_address (EphyTab *tab,
1376 EphyWindowPrivate *priv = window->priv;
1378 if (priv->closing) return;
1380 ephy_toolbar_set_location (priv->toolbar,
1381 ephy_tab_get_address (tab),
1382 ephy_tab_get_typed_address (tab));
1383 ephy_find_toolbar_request_close (priv->find_toolbar);
1387 sync_tab_document_type (EphyTab *tab,
1391 EphyWindowPrivate *priv = window->priv;
1392 GtkActionGroup *action_group = priv->action_group;
1394 EphyEmbedDocumentType type;
1395 gboolean can_find, disable, is_image;
1397 if (priv->closing) return;
1399 /* update zoom actions */
1400 sync_tab_zoom (tab, NULL, window);
1402 type = ephy_tab_get_document_type (tab);
1403 can_find = (type != EPHY_EMBED_DOCUMENT_IMAGE);
1404 is_image = type == EPHY_EMBED_DOCUMENT_IMAGE;
1405 disable = (type != EPHY_EMBED_DOCUMENT_HTML);
1407 action = gtk_action_group_get_action (action_group, "ViewEncoding");
1408 ephy_action_change_sensitivity_flags (action, SENS_FLAG_DOCUMENT, disable);
1409 action = gtk_action_group_get_action (action_group, "ViewPageSource");
1410 ephy_action_change_sensitivity_flags (action, SENS_FLAG_DOCUMENT, is_image);
1411 action = gtk_action_group_get_action (action_group, "EditFind");
1412 ephy_action_change_sensitivity_flags (action, SENS_FLAG_DOCUMENT, !can_find);
1413 action = gtk_action_group_get_action (action_group, "EditFindNext");
1414 ephy_action_change_sensitivity_flags (action, SENS_FLAG_DOCUMENT, !can_find);
1415 action = gtk_action_group_get_action (action_group, "EditFindPrev");
1416 ephy_action_change_sensitivity_flags (action, SENS_FLAG_DOCUMENT, !can_find);
1420 ephy_find_toolbar_request_close (priv->find_toolbar);
1425 sync_tab_icon (EphyTab *tab,
1429 EphyWindowPrivate *priv = window->priv;
1432 if (priv->closing) return;
1434 icon = ephy_tab_get_icon (tab);
1436 ephy_toolbar_set_favicon (priv->toolbar, icon);
1440 sync_tab_load_progress (EphyTab *tab, GParamSpec *pspec, EphyWindow *window)
1442 if (window->priv->closing) return;
1444 ephy_statusbar_set_progress (EPHY_STATUSBAR (window->priv->statusbar),
1445 ephy_tab_get_load_percent (tab));
1449 sync_tab_message (EphyTab *tab, GParamSpec *pspec, EphyWindow *window)
1451 GtkStatusbar *s = GTK_STATUSBAR (window->priv->statusbar);
1452 const char *message;
1454 if (window->priv->closing) return;
1456 message = ephy_tab_get_status_message (tab);
1458 gtk_statusbar_pop (s, window->priv->tab_message_cid);
1462 gtk_statusbar_push (s, window->priv->tab_message_cid, message);
1467 sync_tab_navigation (EphyTab *tab,
1471 EphyTabNavigationFlags flags;
1472 gboolean up = FALSE, back = FALSE, forward = FALSE;
1474 if (window->priv->closing) return;
1476 flags = ephy_tab_get_navigation_flags (tab);
1478 if (flags & EPHY_TAB_NAV_UP)
1482 if (flags & EPHY_TAB_NAV_BACK)
1486 if (flags & EPHY_TAB_NAV_FORWARD)
1491 ephy_toolbar_set_navigation_actions (window->priv->toolbar,
1496 sync_tab_security (EphyTab *tab,
1500 EphyWindowPrivate *priv = window->priv;
1502 EphyEmbedSecurityLevel level;
1503 char *description = NULL;
1506 const char *stock_id = STOCK_LOCK_INSECURE;
1507 gboolean show_lock = FALSE, is_secure = FALSE;
1510 if (priv->closing) return;
1512 embed = ephy_tab_get_embed (tab);
1514 ephy_embed_get_security_level (embed, &level, &description);
1518 case EPHY_EMBED_STATE_IS_UNKNOWN:
1519 state = _("Unknown");
1521 case EPHY_EMBED_STATE_IS_INSECURE:
1522 state = _("Insecure");
1523 g_free (description);
1526 case EPHY_EMBED_STATE_IS_BROKEN:
1527 state = _("Broken");
1528 stock_id = STOCK_LOCK_BROKEN;
1531 #ifndef HAVE_GECKO_1_8_1
1532 /* In Gecko 1.8.1/1.9, we get a useful tooltip here */
1533 g_free (description);
1537 case EPHY_EMBED_STATE_IS_SECURE_LOW:
1538 case EPHY_EMBED_STATE_IS_SECURE_MED:
1540 /* We deliberately don't show the 'secure' icon
1541 * for low & medium secure sites; see bug #151709.
1543 stock_id = STOCK_LOCK_INSECURE;
1545 case EPHY_EMBED_STATE_IS_SECURE_HIGH:
1547 stock_id = STOCK_LOCK_SECURE;
1552 g_assert_not_reached ();
1556 tooltip = g_strdup_printf (_("Security level: %s"), state);
1557 if (description != NULL)
1559 char *tmp = tooltip;
1561 tooltip = g_strconcat (tmp, "\n", description, NULL);
1562 g_free (description);
1566 ephy_statusbar_set_security_state (EPHY_STATUSBAR (priv->statusbar),
1569 ephy_toolbar_set_security_state (priv->toolbar, is_secure,
1570 show_lock, stock_id, tooltip);
1572 if (priv->fullscreen_popup != NULL)
1574 ephy_fullscreen_popup_set_security_state
1575 (EPHY_FULLSCREEN_POPUP (priv->fullscreen_popup),
1576 show_lock, stock_id, tooltip);
1579 action = gtk_action_group_get_action (priv->action_group, "ViewPageSecurityInfo");
1580 gtk_action_set_sensitive (action, is_secure);
1586 sync_tab_popup_windows (EphyTab *tab,
1590 guint num_popups = 0;
1591 char *tooltip = NULL;
1593 g_object_get (G_OBJECT (tab),
1594 "hidden-popup-count", &num_popups,
1599 tooltip = g_strdup_printf (ngettext ("%d hidden popup window",
1600 "%d hidden popup windows",
1605 ephy_statusbar_set_popups_state
1606 (EPHY_STATUSBAR (window->priv->statusbar),
1614 sync_tab_popups_allowed (EphyTab *tab,
1621 g_return_if_fail (EPHY_IS_TAB (tab));
1622 g_return_if_fail (EPHY_IS_WINDOW (window));
1624 action = gtk_action_group_get_action (window->priv->action_group,
1625 "ViewPopupWindows");
1626 g_return_if_fail (GTK_IS_ACTION (action));
1628 g_object_get (G_OBJECT (tab), "popups-allowed", &allow, NULL);
1630 g_signal_handlers_block_by_func
1632 G_CALLBACK (ephy_window_view_popup_windows_cb),
1635 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), allow);
1637 g_signal_handlers_unblock_by_func
1639 G_CALLBACK (ephy_window_view_popup_windows_cb),
1644 sync_tab_load_status (EphyTab *tab,
1648 EphyWindowPrivate *priv = window->priv;
1649 GtkActionGroup *action_group = priv->action_group;
1653 if (window->priv->closing) return;
1655 loading = ephy_tab_get_load_status (tab);
1657 action = gtk_action_group_get_action (action_group, "ViewStop");
1658 gtk_action_set_sensitive (action, loading);
1660 /* disable print while loading, see bug #116344 */
1661 action = gtk_action_group_get_action (action_group, "FilePrintPreview");
1662 ephy_action_change_sensitivity_flags (action, SENS_FLAG_LOADING, loading);
1663 action = gtk_action_group_get_action (action_group, "FilePrint");
1664 ephy_action_change_sensitivity_flags (action, SENS_FLAG_LOADING, loading);
1666 ephy_toolbar_set_spinning (priv->toolbar, loading);
1668 if (priv->fullscreen_popup)
1670 ephy_fullscreen_popup_set_spinning
1671 (EPHY_FULLSCREEN_POPUP (priv->fullscreen_popup),
1677 sync_tab_title (EphyTab *tab,
1681 EphyWindowPrivate *priv = window->priv;
1683 if (priv->closing) return;
1685 gtk_window_set_title (GTK_WINDOW(window),
1686 ephy_tab_get_title_composite (tab));
1690 sync_tab_visibility (EphyTab *tab,
1694 EphyWindowPrivate *priv = window->priv;
1696 gboolean visible = FALSE;
1698 if (priv->closing) return;
1700 tabs = ephy_window_get_tabs (window);
1701 for (l = tabs; l != NULL; l = l->next)
1703 EphyTab *tab = EPHY_TAB(l->data);
1704 g_return_if_fail (EPHY_IS_TAB(tab));
1706 if (ephy_tab_get_visibility (tab))
1714 g_object_set (window, "visible", visible, NULL);
1718 sync_tab_zoom (EphyTab *tab, GParamSpec *pspec, EphyWindow *window)
1720 GtkActionGroup *action_group;
1722 EphyEmbedDocumentType type;
1723 gboolean can_zoom_in = TRUE, can_zoom_out = TRUE, can_zoom_normal = FALSE, can_zoom;
1726 if (window->priv->closing) return;
1728 zoom = ephy_tab_get_zoom (tab);
1729 type = ephy_tab_get_document_type (tab);
1730 can_zoom = (type != EPHY_EMBED_DOCUMENT_IMAGE);
1732 if (zoom >= ZOOM_MAXIMAL)
1734 can_zoom_in = FALSE;
1736 if (zoom <= ZOOM_MINIMAL)
1738 can_zoom_out = FALSE;
1742 can_zoom_normal = TRUE;
1745 ephy_toolbar_set_zoom (window->priv->toolbar, can_zoom, zoom);
1747 action_group = window->priv->action_group;
1748 action = gtk_action_group_get_action (action_group, "ViewZoomIn");
1749 gtk_action_set_sensitive (action, can_zoom_in && can_zoom);
1750 action = gtk_action_group_get_action (action_group, "ViewZoomOut");
1751 gtk_action_set_sensitive (action, can_zoom_out && can_zoom);
1752 action = gtk_action_group_get_action (action_group, "ViewZoomNormal");
1753 gtk_action_set_sensitive (action, can_zoom_normal && can_zoom);
1757 sync_network_status (EphyEmbedSingle *single,
1761 EphyWindowPrivate *priv = window->priv;
1765 is_online = ephy_embed_single_get_network_status (single);
1767 action = gtk_action_group_get_action (priv->action_group,
1769 g_signal_handlers_block_by_func
1770 (action, G_CALLBACK (window_cmd_file_work_offline), window);
1771 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), !is_online);
1772 g_signal_handlers_unblock_by_func
1773 (action, G_CALLBACK (window_cmd_file_work_offline), window);
1777 popup_menu_at_coords (GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
1780 EphyWindow *window = EPHY_WINDOW (user_data);
1781 EphyWindowPrivate *priv = window->priv;
1784 g_return_if_fail (priv->context_event != NULL);
1786 ephy_embed_event_get_coords (priv->context_event, &ux, &uy);
1789 /* FIXME: better position the popup within the window bounds? */
1790 ephy_gui_sanitise_popup_position (menu, GTK_WIDGET (window), x, y);
1796 idle_unref_context_event (EphyWindow *window)
1798 EphyWindowPrivate *priv = window->priv;
1800 LOG ("Idle unreffing context event %p", priv->context_event);
1802 if (priv->context_event != NULL)
1804 g_object_unref (priv->context_event);
1805 priv->context_event = NULL;
1808 priv->idle_worker = 0;
1813 _ephy_window_set_context_event (EphyWindow *window,
1814 EphyEmbedEvent *event)
1816 EphyWindowPrivate *priv = window->priv;
1818 if (priv->idle_worker != 0)
1820 g_source_remove (priv->idle_worker);
1821 priv->idle_worker = 0;
1824 if (priv->context_event != NULL)
1826 g_object_unref (priv->context_event);
1829 priv->context_event = event != NULL ? g_object_ref (event) : NULL;
1833 _ephy_window_unset_context_event (EphyWindow *window)
1835 EphyWindowPrivate *priv = window->priv;
1837 /* Unref the event from idle since we still need it
1838 * from the action callbacks which will run before idle.
1840 if (priv->idle_worker == 0 && priv->context_event != NULL)
1843 g_idle_add ((GSourceFunc) idle_unref_context_event, window);
1848 embed_popup_deactivate_cb (GtkWidget *popup,
1851 LOG ("Deactivating popup menu");
1853 enable_edit_actions_sensitivity (window);
1855 g_signal_handlers_disconnect_by_func
1856 (popup, G_CALLBACK (embed_popup_deactivate_cb), window);
1858 _ephy_window_unset_context_event (window);
1862 get_name_from_address_value (const GValue *value)
1867 uri = gnome_vfs_uri_new (g_value_get_string (value));
1870 name = gnome_vfs_uri_extract_short_name (uri);
1871 gnome_vfs_uri_unref (uri);
1874 return name != NULL ? name : g_strdup ("");
1878 update_popups_tooltips (EphyWindow *window, EphyEmbedEvent *event)
1880 EphyEmbedEventContext context;
1881 GtkActionGroup *group = window->priv->popups_action_group;
1882 const GValue *value;
1884 char *tooltip, *name;
1886 context = ephy_embed_event_get_context (event);
1888 if (context & EPHY_EMBED_CONTEXT_IMAGE)
1890 value = ephy_embed_event_get_property (event, "image");
1891 name = get_name_from_address_value (value);
1893 action = gtk_action_group_get_action (group, "OpenImage");
1894 tooltip = g_strdup_printf (_("Open image “%s”"), name);
1895 g_object_set (action, "tooltip", tooltip, NULL);
1898 action = gtk_action_group_get_action (group, "SetImageAsBackground");
1899 tooltip = g_strdup_printf (_("Use as desktop background “%s”"), name);
1900 g_object_set (action, "tooltip", tooltip, NULL);
1903 action = gtk_action_group_get_action (group, "SaveImageAs");
1904 tooltip = g_strdup_printf (_("Save image “%s”"), name);
1905 g_object_set (action, "tooltip", tooltip, NULL);
1908 action = gtk_action_group_get_action (group, "CopyImageLocation");
1909 tooltip = g_strdup_printf (_("Copy image address “%s”"),
1910 g_value_get_string (value));
1911 g_object_set (action, "tooltip", tooltip, NULL);
1917 if (context & EPHY_EMBED_CONTEXT_EMAIL_LINK)
1919 value = ephy_embed_event_get_property (event, "link");
1921 action = gtk_action_group_get_action (group, "SendEmail");
1922 tooltip = g_strdup_printf (_("Send email to address “%s”"),
1923 g_value_get_string (value));
1924 g_object_set (action, "tooltip", tooltip, NULL);
1927 action = gtk_action_group_get_action (group, "CopyEmailAddress");
1928 tooltip = g_strdup_printf (_("Copy email address “%s”"),
1929 g_value_get_string (value));
1930 g_object_set (action, "tooltip", tooltip, NULL);
1934 if (context & EPHY_EMBED_CONTEXT_LINK)
1936 value = ephy_embed_event_get_property (event, "link");
1938 action = gtk_action_group_get_action (group, "DownloadLink");
1939 name = get_name_from_address_value (value);
1940 tooltip = g_strdup_printf (_("Save link “%s”"), name);
1941 g_object_set (action, "tooltip", tooltip, NULL);
1945 action = gtk_action_group_get_action (group, "BookmarkLink");
1946 tooltip = g_strdup_printf (_("Bookmark link “%s”"),
1947 g_value_get_string (value));
1948 g_object_set (action, "tooltip", tooltip, NULL);
1951 action = gtk_action_group_get_action (group, "CopyLinkAddress");
1952 tooltip = g_strdup_printf (_("Copy link's address “%s”"),
1953 g_value_get_string (value));
1954 g_object_set (action, "tooltip", tooltip, NULL);
1960 show_embed_popup (EphyWindow *window,
1962 EphyEmbedEvent *event)
1964 EphyWindowPrivate *priv = window->priv;
1965 GtkActionGroup *action_group;
1967 EphyEmbedEventContext context;
1969 const GValue *value;
1970 gboolean framed, can_open_in_new;
1974 /* Do not show the menu in print preview mode */
1980 value = ephy_embed_event_get_property (event, "framed_page");
1981 framed = g_value_get_int (value);
1983 can_open_in_new = ephy_embed_event_has_property (event, "link-has-web-scheme");
1985 context = ephy_embed_event_get_context (event);
1987 LOG ("show_embed_popup context %x", context);
1989 if (context & EPHY_EMBED_CONTEXT_EMAIL_LINK)
1991 popup = "/EphyEmailLinkPopup";
1992 update_edit_actions_sensitivity (window, TRUE);
1994 else if (context & EPHY_EMBED_CONTEXT_LINK)
1996 popup = "/EphyLinkPopup";
1997 update_edit_actions_sensitivity (window, TRUE);
1999 else if (context & EPHY_EMBED_CONTEXT_INPUT)
2001 popup = "/EphyInputPopup";
2002 update_edit_actions_sensitivity (window, FALSE);
2006 popup = "/EphyDocumentPopup";
2007 update_edit_actions_sensitivity (window, TRUE);
2010 update_popups_tooltips (window, event);
2012 widget = gtk_ui_manager_get_widget (priv->manager, popup);
2013 g_return_if_fail (widget != NULL);
2015 action_group = window->priv->popups_action_group;
2017 action = gtk_action_group_get_action (action_group, "OpenLinkInNewWindow");
2018 gtk_action_set_sensitive (action, can_open_in_new);
2020 action = gtk_action_group_get_action (action_group, "OpenLinkInNewTab");
2021 ephy_action_change_sensitivity_flags (action, SENS_FLAG_CONTEXT, !can_open_in_new);
2024 update_popup_actions_visibility (window,
2025 context & EPHY_EMBED_CONTEXT_IMAGE,
2028 _ephy_window_set_context_event (window, event);
2030 g_signal_connect (widget, "deactivate",
2031 G_CALLBACK (embed_popup_deactivate_cb), window);
2033 button = ephy_embed_event_get_button (event);
2037 gtk_menu_popup (GTK_MENU (widget), NULL, NULL,
2038 popup_menu_at_coords, window, 0,
2039 gtk_get_current_event_time ());
2040 gtk_menu_shell_select_first (GTK_MENU_SHELL (widget), FALSE);
2044 gtk_menu_popup (GTK_MENU (widget), NULL, NULL,
2046 gtk_get_current_event_time ());
2051 tab_context_menu_cb (EphyEmbed *embed,
2052 EphyEmbedEvent *event,
2057 tab = ephy_tab_for_embed (embed);
2058 g_return_val_if_fail (EPHY_IS_TAB (tab), FALSE);
2059 g_return_val_if_fail (window->priv->active_tab == tab, FALSE);
2061 show_embed_popup (window, tab, event);
2067 let_me_resize_hack (EphyWindow *window)
2069 EphyWindowPrivate *priv = window->priv;
2071 gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2073 priv->idle_resize_handler = 0;
2078 tab_size_to_cb (EphyEmbed *embed,
2083 EphyWindowPrivate *priv = window->priv;
2084 GtkWidget *widget = GTK_WIDGET (window);
2085 GtkWidget *embed_widget = GTK_WIDGET (embed);
2090 int ww, wh, ew, eh, dw, dh;
2092 LOG ("tab_size_to_cb window %p embed %p width %d height %d", window, embed, width, height);
2094 tab = ephy_tab_for_embed (embed);
2095 g_return_if_fail (tab != NULL);
2097 /* FIXME: allow sizing also for non-popup single-tab windows? */
2098 if (tab != ephy_window_get_active_tab (window) || !priv->is_popup) return;
2100 /* contrain size so that the window will be fully contained within the screen */
2101 screen = gtk_widget_get_screen (widget);
2102 monitor = gdk_screen_get_monitor_at_window (screen, widget->window);
2103 gdk_screen_get_monitor_geometry (screen, monitor, &rect);
2104 /* FIXME: get and subtract the panel size */
2106 gtk_window_get_size (GTK_WINDOW (window), &ww, &wh);
2108 ew = embed_widget->allocation.width;
2109 eh = embed_widget->allocation.height;
2111 /* This should approximate the chrome extent */
2112 dw = ww - ew; dw = MAX (dw, 0); dw = MIN (dw, rect.width - 1);
2113 dh = wh - eh; dh = MAX (dh, 0); dh = MIN (dh, rect.height - 1);
2115 width = MIN (rect.width - dw, width);
2116 height = MIN (rect.height - dh, height);
2118 /* FIXME: move window if this will place it partially outside the screen rect? */
2120 gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
2121 ephy_tab_set_size (tab, width, height);
2123 if (priv->idle_resize_handler == 0)
2125 priv->idle_resize_handler =
2126 g_idle_add ((GSourceFunc) let_me_resize_hack, window);
2131 ephy_window_set_active_tab (EphyWindow *window, EphyTab *new_tab)
2136 g_return_if_fail (EPHY_IS_WINDOW (window));
2137 g_return_if_fail (gtk_widget_get_toplevel (GTK_WIDGET (new_tab)) == GTK_WIDGET (window));
2139 old_tab = window->priv->active_tab;
2141 if (old_tab == new_tab) return;
2143 if (old_tab != NULL)
2145 g_signal_handlers_disconnect_by_func (old_tab,
2146 G_CALLBACK (sync_tab_address),
2148 g_signal_handlers_disconnect_by_func (old_tab,
2149 G_CALLBACK (sync_tab_document_type),
2151 g_signal_handlers_disconnect_by_func (old_tab,
2152 G_CALLBACK (sync_tab_icon),
2154 g_signal_handlers_disconnect_by_func (old_tab,
2155 G_CALLBACK (sync_tab_load_progress),
2157 g_signal_handlers_disconnect_by_func (old_tab,
2158 G_CALLBACK (sync_tab_load_status),
2160 g_signal_handlers_disconnect_by_func (old_tab,
2161 G_CALLBACK (sync_tab_message),
2163 g_signal_handlers_disconnect_by_func (old_tab,
2164 G_CALLBACK (sync_tab_navigation),
2166 g_signal_handlers_disconnect_by_func (old_tab,
2167 G_CALLBACK (sync_tab_security),
2169 g_signal_handlers_disconnect_by_func (old_tab,
2170 G_CALLBACK (sync_tab_popup_windows),
2172 g_signal_handlers_disconnect_by_func (old_tab,
2173 G_CALLBACK (sync_tab_popups_allowed),
2175 g_signal_handlers_disconnect_by_func (old_tab,
2176 G_CALLBACK (sync_tab_title),
2178 g_signal_handlers_disconnect_by_func (old_tab,
2179 G_CALLBACK (sync_tab_zoom),
2182 embed = ephy_tab_get_embed (old_tab);
2183 g_signal_handlers_disconnect_by_func
2184 (embed, G_CALLBACK (tab_context_menu_cb), window);
2185 g_signal_handlers_disconnect_by_func
2186 (embed, G_CALLBACK (tab_size_to_cb), window);
2190 window->priv->active_tab = new_tab;
2192 if (new_tab != NULL)
2194 sync_tab_address (new_tab, NULL, window);
2195 sync_tab_document_type (new_tab, NULL, window);
2196 sync_tab_icon (new_tab, NULL, window);
2197 sync_tab_load_progress (new_tab, NULL, window);
2198 sync_tab_load_status (new_tab, NULL, window);
2199 sync_tab_message (new_tab, NULL, window);
2200 sync_tab_navigation (new_tab, NULL, window);
2201 sync_tab_security (new_tab, NULL, window);
2202 sync_tab_popup_windows (new_tab, NULL, window);
2203 sync_tab_popups_allowed (new_tab, NULL, window);
2204 sync_tab_title (new_tab, NULL, window);
2205 sync_tab_zoom (new_tab, NULL, window);
2207 g_signal_connect_object (new_tab, "notify::address",
2208 G_CALLBACK (sync_tab_address),
2210 g_signal_connect_object (new_tab, "notify::document-type",
2211 G_CALLBACK (sync_tab_document_type),
2213 g_signal_connect_object (new_tab, "notify::icon",
2214 G_CALLBACK (sync_tab_icon),
2216 g_signal_connect_object (new_tab, "notify::load-progress",
2217 G_CALLBACK (sync_tab_load_progress),
2219 g_signal_connect_object (new_tab, "notify::load-status",
2220 G_CALLBACK (sync_tab_load_status),
2222 g_signal_connect_object (new_tab, "notify::message",
2223 G_CALLBACK (sync_tab_message),
2225 g_signal_connect_object (new_tab, "notify::navigation",
2226 G_CALLBACK (sync_tab_navigation),
2228 g_signal_connect_object (new_tab, "notify::security-level",
2229 G_CALLBACK (sync_tab_security),
2231 g_signal_connect_object (new_tab, "notify::hidden-popup-count",
2232 G_CALLBACK (sync_tab_popup_windows),
2234 g_signal_connect_object (new_tab, "notify::popups-allowed",
2235 G_CALLBACK (sync_tab_popups_allowed),
2237 g_signal_connect_object (new_tab, "notify::title",
2238 G_CALLBACK (sync_tab_title),
2240 g_signal_connect_object (new_tab, "notify::zoom",
2241 G_CALLBACK (sync_tab_zoom),
2244 embed = ephy_tab_get_embed (new_tab);
2245 g_signal_connect_object (embed, "ge-context-menu",
2246 G_CALLBACK (tab_context_menu_cb),
2247 window, G_CONNECT_AFTER);
2248 g_signal_connect_object (embed, "size-to",
2249 G_CALLBACK (tab_size_to_cb),
2252 g_object_notify (G_OBJECT (window), "active-tab");
2257 update_tabs_menu_sensitivity (EphyWindow *window)
2259 EphyWindowPrivate *priv = window->priv;
2260 GtkActionGroup *action_group;
2262 GtkNotebook *notebook;
2264 gboolean not_first, not_last;
2266 notebook = GTK_NOTEBOOK (priv->notebook);
2267 page = gtk_notebook_get_current_page (notebook);
2268 n_pages = gtk_notebook_get_n_pages (notebook);
2269 not_first = page > 0;
2270 not_last = page + 1 < n_pages;
2272 action_group = priv->action_group;
2273 action = gtk_action_group_get_action (action_group, "TabsPrevious");
2274 gtk_action_set_sensitive (action, not_first);
2275 action = gtk_action_group_get_action (action_group, "TabsNext");
2276 gtk_action_set_sensitive (action, not_last);
2277 action = gtk_action_group_get_action (action_group, "TabsMoveLeft");
2278 gtk_action_set_sensitive (action, not_first);
2279 action = gtk_action_group_get_action (action_group, "TabsMoveRight");
2280 gtk_action_set_sensitive (action, not_last);
2284 embed_modal_alert_cb (EphyEmbed *embed,
2287 EphyWindowPrivate *priv = window->priv;
2289 const char *address;
2291 tab = ephy_tab_for_embed (embed);
2292 g_return_val_if_fail (tab != NULL, FALSE);
2294 /* if we're in ppv mode, we cannot switch tabs, so inhibit the alert */
2295 if (priv->ppv_mode) return TRUE;
2297 /* switch the window to the tab, and bring the window to the foreground
2298 * (since the alert is modal, the user won't be able to do anything
2299 * with his current window anyway :|)
2301 ephy_window_jump_to_tab (window, tab);
2302 gtk_window_present (GTK_WINDOW (window));
2304 /* make sure the location entry shows the real URL of the tab's page */
2305 address = ephy_tab_get_address (tab);
2306 ephy_toolbar_set_location (priv->toolbar, address, NULL);
2308 /* don't suppress alert */
2313 idle_tab_remove_cb (GtkWidget *tab)
2315 GtkWidget *toplevel;
2317 EphyWindowPrivate *priv;
2318 GtkNotebook *notebook;
2321 toplevel = gtk_widget_get_toplevel (tab);
2322 if (!EPHY_IS_WINDOW (toplevel)) return FALSE; /* FIXME should this ever occur? */
2324 window = EPHY_WINDOW (toplevel);
2325 priv = window->priv;
2327 if (priv->closing) return FALSE;
2329 g_hash_table_remove (priv->tabs_to_remove, tab);
2331 notebook = GTK_NOTEBOOK (ephy_window_get_notebook (window));
2333 position = gtk_notebook_page_num (notebook, tab);
2334 gtk_notebook_remove_page (notebook, position);
2336 /* don't run again */
2341 schedule_tab_close (EphyWindow *window,
2344 EphyWindowPrivate *priv = window->priv;
2348 LOG ("scheduling close of embed %p in window %p", embed, window);
2350 if (priv->closing) return;
2352 tab = ephy_tab_for_embed (embed);
2353 g_return_if_fail (tab != NULL);
2355 if (g_hash_table_lookup (priv->tabs_to_remove, tab) != NULL) return;
2357 /* do this on idle, because otherwise we'll crash in certain circumstances
2358 * (see galeon bug #116256)
2360 id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
2361 (GSourceFunc) idle_tab_remove_cb,
2364 g_hash_table_insert (priv->tabs_to_remove, tab, GUINT_TO_POINTER (id));
2366 /* don't wait until idle to hide the window */
2367 if (g_hash_table_size (priv->tabs_to_remove) == priv->num_tabs)
2369 gtk_widget_hide (GTK_WIDGET (window));
2374 embed_close_request_cb (EphyEmbed *embed,
2377 LOG ("embed_close_request_cb embed %p window %p", embed, window);
2379 schedule_tab_close (window, embed);
2386 embed_destroy_browser_cb (EphyEmbed *embed,
2389 g_return_if_reached ();
2393 show_notebook_popup_menu (GtkNotebook *notebook,
2395 GdkEventButton *event)
2397 GtkWidget *menu, *tab, *tab_label;
2400 menu = gtk_ui_manager_get_widget (window->priv->manager, "/EphyNotebookPopup");
2401 g_return_val_if_fail (menu != NULL, FALSE);
2403 /* allow extensions to sync when showing the popup */
2404 action = gtk_action_group_get_action (window->priv->action_group,
2405 "NotebookPopupAction");
2406 g_return_val_if_fail (action != NULL, FALSE);
2407 gtk_action_activate (action);
2411 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
2413 event->button, event->time);
2417 tab = GTK_WIDGET (ephy_window_get_active_tab (window));
2418 tab_label = gtk_notebook_get_tab_label (notebook, tab);
2420 gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
2421 ephy_gui_menu_position_under_widget, tab_label,
2422 0, gtk_get_current_event_time ());
2423 gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
2430 notebook_button_press_cb (GtkNotebook *notebook,
2431 GdkEventButton *event,
2434 if (GDK_BUTTON_PRESS == event->type && 3 == event->button)
2436 return show_notebook_popup_menu (notebook, window, event);
2443 notebook_popup_menu_cb (GtkNotebook *notebook,
2446 /* Only respond if the notebook is the actual focus */
2447 if (EPHY_IS_NOTEBOOK (gtk_window_get_focus (GTK_WINDOW (window))))
2449 return show_notebook_popup_menu (notebook, window, NULL);
2456 notebook_page_added_cb (EphyNotebook *notebook,
2461 EphyWindowPrivate *priv = window->priv;
2462 EphyExtension *manager;
2465 LOG ("page-added notebook %p tab %p position %u\n", notebook, tab, position);
2467 g_return_if_fail (EPHY_IS_TAB (tab));
2471 update_tabs_menu_sensitivity (window);
2473 g_signal_connect_object (tab, "notify::visibility",
2474 G_CALLBACK (sync_tab_visibility), window, 0);
2475 g_signal_connect_object (tab, "open-link",
2476 G_CALLBACK (ephy_link_open), window,
2479 embed = ephy_tab_get_embed (tab);
2480 g_return_if_fail (embed != NULL);
2482 g_signal_connect_object (embed, "close-request",
2483 G_CALLBACK (embed_close_request_cb),
2485 g_signal_connect_object (embed, "destroy-browser",
2486 G_CALLBACK (embed_destroy_browser_cb),
2488 g_signal_connect_object (embed, "ge-modal-alert",
2489 G_CALLBACK (embed_modal_alert_cb), window, G_CONNECT_AFTER);
2491 /* Let the extensions attach themselves to the tab */
2492 manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell));
2493 ephy_extension_attach_tab (manager, window, tab);
2497 notebook_page_removed_cb (EphyNotebook *notebook,
2502 EphyWindowPrivate *priv = window->priv;
2503 EphyExtension *manager;
2506 LOG ("page-removed notebook %p tab %p position %u\n", notebook, tab, position);
2508 if (priv->closing) return;
2510 g_return_if_fail (EPHY_IS_TAB (tab));
2512 /* Let the extensions remove themselves from the tab */
2513 manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell));
2514 ephy_extension_detach_tab (manager, window, tab);
2516 g_signal_handlers_disconnect_by_func (G_OBJECT (tab),
2517 G_CALLBACK (sync_tab_visibility),
2519 g_signal_handlers_disconnect_by_func (G_OBJECT (tab),
2520 G_CALLBACK (ephy_link_open),
2525 if (priv->num_tabs > 0)
2527 update_tabs_menu_sensitivity (window);
2530 embed = ephy_tab_get_embed (tab);
2531 g_return_if_fail (embed != NULL);
2533 g_signal_handlers_disconnect_by_func
2534 (embed, G_CALLBACK (embed_modal_alert_cb), window);
2535 g_signal_handlers_disconnect_by_func
2536 (embed, G_CALLBACK (embed_close_request_cb), window);
2537 g_signal_handlers_disconnect_by_func
2538 (embed, G_CALLBACK (embed_destroy_browser_cb), window);
2542 notebook_page_reordered_cb (EphyNotebook *notebook,
2547 update_tabs_menu_sensitivity (window);
2551 notebook_page_close_request_cb (EphyNotebook *notebook,
2555 EphyWindowPrivate *priv = window->priv;
2558 if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_QUIT) &&
2559 gtk_notebook_get_n_pages (priv->notebook) == 1)
2564 embed = ephy_tab_get_embed (tab);
2565 g_return_if_fail (embed != NULL);
2567 if (!ephy_embed_has_modified_forms (embed) ||
2568 confirm_close_with_modified_forms (window))
2570 ephy_embed_close (embed);
2574 static GtkNotebook *
2575 setup_notebook (EphyWindow *window)
2577 GtkNotebook *notebook;
2579 notebook = GTK_NOTEBOOK (g_object_new (EPHY_TYPE_NOTEBOOK, NULL));
2581 g_signal_connect_after (notebook, "switch-page",
2582 G_CALLBACK (notebook_switch_page_cb),
2585 g_signal_connect (notebook, "popup-menu",
2586 G_CALLBACK (notebook_popup_menu_cb), window);
2587 g_signal_connect (notebook, "button-press-event",
2588 G_CALLBACK (notebook_button_press_cb), window);
2590 g_signal_connect (notebook, "page-added",
2591 G_CALLBACK (notebook_page_added_cb), window);
2592 g_signal_connect (notebook, "page-removed",
2593 G_CALLBACK (notebook_page_removed_cb), window);
2594 g_signal_connect (notebook, "page-reordered",
2595 G_CALLBACK (notebook_page_reordered_cb), window);
2596 g_signal_connect (notebook, "tab-close-request",
2597 G_CALLBACK (notebook_page_close_request_cb), window);
2603 ephy_window_set_chrome (EphyWindow *window, EphyEmbedChrome mask)
2605 EphyEmbedChrome chrome_mask = mask;
2607 if (mask == EPHY_EMBED_CHROME_ALL)
2609 window->priv->should_save_chrome = TRUE;
2612 if (!eel_gconf_get_boolean (CONF_WINDOWS_SHOW_TOOLBARS))
2614 chrome_mask &= ~EPHY_EMBED_CHROME_TOOLBAR;
2617 if (!eel_gconf_get_boolean (CONF_WINDOWS_SHOW_STATUSBAR))
2619 chrome_mask &= ~EPHY_EMBED_CHROME_STATUSBAR;
2622 if (eel_gconf_get_boolean (CONF_LOCKDOWN_HIDE_MENUBAR))
2624 chrome_mask &= ~EPHY_EMBED_CHROME_MENUBAR;
2627 window->priv->chrome = chrome_mask;
2631 ephy_window_set_is_popup (EphyWindow *window,
2634 EphyWindowPrivate *priv = window->priv;
2636 priv->is_popup = is_popup;
2638 g_object_notify (G_OBJECT (window), "is-popup");
2648 ephy_window_dispose (GObject *object)
2650 EphyWindow *window = EPHY_WINDOW (object);
2651 EphyWindowPrivate *priv = window->priv;
2655 LOG ("EphyWindow dispose %p", window);
2657 /* Only do these once */
2658 if (window->priv->closing == FALSE)
2660 EphyExtension *manager;
2662 window->priv->closing = TRUE;
2664 /* Let the extensions detach themselves from the window */
2665 manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell));
2666 ephy_extension_detach_window (manager, window);
2667 ephy_bookmarks_ui_detach_window (window);
2669 /* Deactivate menus */
2670 popups = gtk_ui_manager_get_toplevels (window->priv->manager, GTK_UI_MANAGER_POPUP);
2671 g_slist_foreach (popups, (GFunc) gtk_menu_shell_deactivate, NULL);
2672 g_slist_free (popups);
2674 single = ephy_embed_shell_get_embed_single (embed_shell);
2675 g_signal_handlers_disconnect_by_func
2676 (single, G_CALLBACK (sync_network_status), window);
2678 eel_gconf_notification_remove (priv->browse_with_caret_notifier_id);
2679 eel_gconf_notification_remove (priv->allow_popups_notifier_id);
2680 priv->browse_with_caret_notifier_id = 0;
2681 priv->allow_popups_notifier_id = 0;
2683 if (priv->idle_resize_handler != 0)
2685 g_source_remove (priv->idle_resize_handler);
2686 priv->idle_resize_handler = 0;
2689 g_hash_table_foreach_remove (priv->tabs_to_remove, (GHRFunc) remove_true, NULL);
2691 g_object_unref (priv->enc_menu);
2692 priv->enc_menu = NULL;
2694 g_object_unref (priv->tabs_menu);
2695 priv->tabs_menu = NULL;
2697 if (priv->ppview_toolbar)
2699 g_object_unref (priv->ppview_toolbar);
2700 priv->ppview_toolbar = NULL;
2703 priv->action_group = NULL;
2704 priv->popups_action_group = NULL;
2706 g_object_unref (priv->manager);
2707 priv->manager = NULL;
2709 _ephy_window_set_context_event (window, NULL);
2712 destroy_fullscreen_popup (window);
2714 G_OBJECT_CLASS (parent_class)->dispose (object);
2718 ephy_window_set_property (GObject *object,
2720 const GValue *value,
2723 EphyWindow *window = EPHY_WINDOW (object);
2727 case PROP_ACTIVE_TAB:
2728 ephy_window_set_active_tab (window, g_value_get_object (value));
2731 ephy_window_set_chrome (window, g_value_get_flags (value));
2734 ephy_window_set_print_preview (window, g_value_get_boolean (value));
2736 case PROP_SINGLE_TAB_MODE:
2737 ephy_window_set_is_popup (window, g_value_get_boolean (value));
2743 ephy_window_get_property (GObject *object,
2748 EphyWindow *window = EPHY_WINDOW (object);
2752 case PROP_ACTIVE_TAB:
2753 g_value_set_object (value, window->priv->active_tab);
2756 g_value_set_flags (value, window->priv->chrome);
2759 g_value_set_boolean (value, window->priv->ppv_mode);
2761 case PROP_SINGLE_TAB_MODE:
2762 g_value_set_boolean (value, window->priv->is_popup);
2768 ephy_window_focus_in_event (GtkWidget *widget,
2769 GdkEventFocus *event)
2771 EphyWindow *window = EPHY_WINDOW (widget);
2772 EphyWindowPrivate *priv = window->priv;
2774 if (priv->fullscreen_popup && !get_toolbar_visibility (window))
2776 gtk_widget_show (priv->fullscreen_popup);
2779 return GTK_WIDGET_CLASS (parent_class)->focus_in_event (widget, event);
2783 ephy_window_focus_out_event (GtkWidget *widget,
2784 GdkEventFocus *event)
2786 EphyWindow *window = EPHY_WINDOW (widget);
2787 EphyWindowPrivate *priv = window->priv;
2789 if (priv->fullscreen_popup)
2791 gtk_widget_hide (priv->fullscreen_popup);
2794 return GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, event);
2798 ephy_window_state_event (GtkWidget *widget,
2799 GdkEventWindowState *event)
2801 EphyWindow *window = EPHY_WINDOW (widget);
2802 EphyWindowPrivate *priv = window->priv;
2803 gboolean (* window_state_event) (GtkWidget *, GdkEventWindowState *);
2805 window_state_event = GTK_WIDGET_CLASS (parent_class)->window_state_event;
2806 if (window_state_event)
2808 window_state_event (widget, event);
2811 if (event->changed_mask & (GDK_WINDOW_STATE_MAXIMIZED))
2815 show = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) == 0;
2817 gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (priv->statusbar), show);
2820 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
2822 GtkActionGroup *action_group;
2824 gboolean fullscreen;
2826 fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN;
2830 ephy_window_fullscreen (window);
2834 ephy_window_unfullscreen (window);
2837 action_group = priv->action_group;
2839 action = gtk_action_group_get_action (action_group, "ViewFullscreen");
2840 g_signal_handlers_block_by_func
2841 (action, G_CALLBACK (window_cmd_view_fullscreen), window);
2842 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), fullscreen);
2843 g_signal_handlers_unblock_by_func
2844 (action, G_CALLBACK (window_cmd_view_fullscreen), window);
2846 action = gtk_action_group_get_action (action_group, "ViewToolbarEditor");
2847 ephy_action_change_sensitivity_flags (action, SENS_FLAG_CHROME, fullscreen);
2854 ephy_window_link_iface_init (EphyLinkIface *iface)
2856 iface->open_link = ephy_window_open_link;
2860 ephy_window_class_init (EphyWindowClass *klass)
2862 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2863 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
2865 parent_class = g_type_class_peek_parent (klass);
2867 object_class->constructor = ephy_window_constructor;
2868 object_class->dispose = ephy_window_dispose;
2869 object_class->finalize = ephy_window_finalize;
2870 object_class->get_property = ephy_window_get_property;
2871 object_class->set_property = ephy_window_set_property;
2873 widget_class->show = ephy_window_show;
2874 widget_class->key_press_event = ephy_window_key_press_event;
2875 widget_class->focus_in_event = ephy_window_focus_in_event;
2876 widget_class->focus_out_event = ephy_window_focus_out_event;
2877 widget_class->window_state_event = ephy_window_state_event;
2878 widget_class->delete_event = ephy_window_delete_event;
2880 g_object_class_install_property (object_class,
2882 g_param_spec_object ("active-tab",
2886 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2888 g_object_class_install_property (object_class,
2890 g_param_spec_flags ("chrome",
2893 EPHY_TYPE_EMBED_CHROME,
2894 EPHY_EMBED_CHROME_ALL,
2895 G_PARAM_CONSTRUCT_ONLY |
2896 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2898 g_object_class_install_property (object_class,
2900 g_param_spec_boolean ("print-preview-mode",
2901 "Print preview mode",
2902 "Whether the window is in print preview mode",
2904 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
2906 g_object_class_install_property (object_class,
2907 PROP_SINGLE_TAB_MODE,
2908 g_param_spec_boolean ("is-popup",
2910 "Whether the window is a popup",
2912 G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB |
2913 G_PARAM_CONSTRUCT_ONLY));
2915 g_type_class_add_private (object_class, sizeof (EphyWindowPrivate));
2919 browse_with_caret_notifier (GConfClient *client,
2924 EphyWindowPrivate *priv = window->priv;
2928 enabled = eel_gconf_get_boolean (CONF_BROWSE_WITH_CARET);
2929 action = gtk_action_group_get_action (window->priv->action_group,
2931 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), enabled);
2933 ephy_statusbar_set_caret_mode (EPHY_STATUSBAR (priv->statusbar), enabled);
2937 allow_popups_notifier (GConfClient *client,
2945 g_return_if_fail (EPHY_IS_WINDOW (window));
2947 tabs = ephy_window_get_tabs (window);
2949 for (; tabs; tabs = g_list_next (tabs))
2951 tab = EPHY_TAB (tabs->data);
2952 g_return_if_fail (EPHY_IS_TAB (tab));
2954 g_object_notify (G_OBJECT (tab), "popups-allowed");
2959 ephy_window_open_link (EphyLink *link,
2960 const char *address,
2962 EphyLinkFlags flags)
2964 EphyWindow *window = EPHY_WINDOW (link);
2965 EphyWindowPrivate *priv = window->priv;
2968 g_return_val_if_fail (address != NULL, NULL);
2970 /* don't do anything in ppv mode */
2971 if (window->priv->ppv_mode) return NULL;
2975 tab = ephy_window_get_active_tab (window);
2978 if (flags & (EPHY_LINK_JUMP_TO |
2980 EPHY_LINK_NEW_WINDOW))
2982 EphyNewTabFlags ntflags = EPHY_NEW_TAB_OPEN_PAGE;
2984 if (flags & EPHY_LINK_JUMP_TO)
2986 ntflags |= EPHY_NEW_TAB_JUMP;
2988 if (flags & EPHY_LINK_NEW_WINDOW ||
2989 (flags & EPHY_LINK_NEW_TAB && priv->is_popup))
2991 ntflags |= EPHY_NEW_TAB_IN_NEW_WINDOW;
2995 ntflags |= EPHY_NEW_TAB_IN_EXISTING_WINDOW;
2997 if (flags & EPHY_LINK_ALLOW_FIXUP)
2999 ntflags |= EPHY_NEW_TAB_ALLOW_FIXUP;
3002 new_tab = ephy_shell_new_tab
3004 EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))),
3005 tab, address, ntflags);
3011 embed = ephy_tab_get_embed (tab);
3013 if (flags & EPHY_LINK_ALLOW_FIXUP)
3015 ephy_embed_load (embed,
3017 EPHY_EMBED_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP,
3022 ephy_embed_load_url (embed, address);
3025 if (address == NULL || address[0] == '\0' || strcmp (address, "about:blank") == 0)
3027 ephy_toolbar_activate_location (priv->toolbar);
3031 gtk_widget_grab_focus (GTK_WIDGET (embed));
3041 find_toolbar_close_cb (EphyFindToolbar *toolbar,
3044 EphyWindowPrivate *priv = window->priv;
3047 if (priv->closing) return;
3049 ephy_find_toolbar_close (priv->find_toolbar);
3051 tab = ephy_window_get_active_tab (window);
3052 if (tab == NULL) return;
3054 gtk_widget_grab_focus (GTK_WIDGET (tab));
3058 cancel_handler (gpointer idptr)
3060 guint id = GPOINTER_TO_UINT (idptr);
3062 g_source_remove (id);
3066 ephy_window_init (EphyWindow *window)
3068 LOG ("EphyWindow initialising %p", window);
3070 g_object_ref (ephy_shell);
3072 window->priv = EPHY_WINDOW_GET_PRIVATE (window);
3076 ephy_window_constructor (GType type,
3077 guint n_construct_properties,
3078 GObjectConstructParam *construct_params)
3082 EphyWindowPrivate *priv;
3083 EphyExtension *manager;
3084 EphyEmbedSingle *single;
3085 EggToolbarsModel *model;
3086 GtkSettings *settings;
3088 GtkActionGroup *toolbar_action_group;
3089 GError *error = NULL;
3090 guint settings_connection;
3092 object = parent_class->constructor (type, n_construct_properties,
3095 window = EPHY_WINDOW (object);
3097 priv = window->priv;
3099 priv->tabs_to_remove = g_hash_table_new_full (g_direct_hash, g_direct_equal,
3100 NULL, cancel_handler);
3102 ephy_gui_ensure_window_group (GTK_WINDOW (window));
3104 /* initialize the listener for the key theme
3105 * FIXME: Need to handle multi-head and migration.
3107 settings = gtk_settings_get_default ();
3108 settings_connection = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (settings),
3109 SETTINGS_CONNECTION_DATA_KEY));
3110 if (settings_connection == 0)
3112 settings_connection =
3113 g_signal_connect (settings, "notify::gtk-key-theme-name",
3114 G_CALLBACK (settings_changed_cb), NULL);
3115 g_object_set_data (G_OBJECT (settings), SETTINGS_CONNECTION_DATA_KEY,
3116 GUINT_TO_POINTER (settings_connection));
3120 settings_change_notify (settings, window);
3122 /* Setup the UI manager and connect verbs */
3123 setup_ui_manager (window);
3125 priv->notebook = setup_notebook (window);
3126 g_signal_connect_swapped (priv->notebook, "open-link",
3127 G_CALLBACK (ephy_link_open), window);
3128 gtk_box_pack_start (GTK_BOX (priv->main_vbox),
3129 GTK_WIDGET (priv->notebook),
3131 gtk_widget_show (GTK_WIDGET (priv->notebook));
3132 ephy_notebook_set_dnd_enabled (EPHY_NOTEBOOK (priv->notebook), !priv->is_popup);
3134 priv->find_toolbar = ephy_find_toolbar_new (window);
3135 g_signal_connect (priv->find_toolbar, "close",
3136 G_CALLBACK (find_toolbar_close_cb), window);
3137 gtk_box_pack_start (GTK_BOX (priv->main_vbox),
3138 GTK_WIDGET (priv->find_toolbar), FALSE, FALSE, 0);
3139 /* don't show the find toolbar here! */
3141 priv->statusbar = ephy_statusbar_new ();
3142 gtk_box_pack_end (GTK_BOX (priv->main_vbox),
3143 GTK_WIDGET (priv->statusbar),
3145 priv->tab_message_cid = gtk_statusbar_get_context_id
3146 (GTK_STATUSBAR (priv->statusbar), "tab_message");
3147 priv->help_message_cid = gtk_statusbar_get_context_id
3148 (GTK_STATUSBAR (priv->statusbar), "help_message");
3150 /* get the toolbars model *before* getting the bookmarksbar model
3151 * (via ephy_bookmarsbar_new()), so that the toolbars model is
3152 * instantiated *before* the bookmarksbarmodel, to make forwarding
3153 * works. See bug #151267.
3155 model= EGG_TOOLBARS_MODEL (ephy_shell_get_toolbars_model (ephy_shell, FALSE));
3157 /* create the toolbars */
3158 priv->toolbar = ephy_toolbar_new (window);
3159 g_signal_connect_swapped (priv->toolbar, "open-link",
3160 G_CALLBACK (ephy_link_open), window);
3161 g_signal_connect_swapped (priv->toolbar, "exit-clicked",
3162 G_CALLBACK (exit_fullscreen_clicked_cb), window);
3163 g_signal_connect_swapped (priv->toolbar, "activation-finished",
3164 G_CALLBACK (sync_chromes_visibility), window);
3166 /* now load the UI definition */
3167 gtk_ui_manager_add_ui_from_file
3168 (priv->manager, ephy_file ("epiphany-ui.xml"), &error);
3171 g_warning ("Could not merge epiphany-ui.xml: %s", error->message);
3172 g_error_free (error);
3174 #if ENABLE_CERTIFICATE_MANAGER
3177 ui_id = gtk_ui_manager_new_merge_id (priv->manager);
3178 gtk_ui_manager_add_ui (priv->manager, ui_id,
3179 "/menubar/EditMenu/EditPersonalDataMenu",
3180 "EditCertificates", "EditCertificates",
3181 GTK_UI_MANAGER_MENUITEM, FALSE);
3185 /* Initialize the menus */
3186 priv->tabs_menu = ephy_tabs_menu_new (window);
3187 priv->enc_menu = ephy_encoding_menu_new (window);
3189 /* Add the toolbars to the window */
3190 gtk_box_pack_end (GTK_BOX (priv->menu_dock),
3191 GTK_WIDGET (priv->toolbar),
3194 /* Once the window is sufficiently created let the extensions attach to it */
3195 manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell));
3196 ephy_extension_attach_window (manager, window);
3197 ephy_bookmarks_ui_attach_window (window);
3199 /* We only set the model now after attaching the extensions, so that
3200 * extensions already have created their actions which may be on
3203 egg_editable_toolbar_set_model
3204 (EGG_EDITABLE_TOOLBAR (priv->toolbar), model);
3206 /* other notifiers */
3207 browse_with_caret_notifier (NULL, 0, NULL, window);
3208 priv->browse_with_caret_notifier_id = eel_gconf_notification_add
3209 (CONF_BROWSE_WITH_CARET,
3210 (GConfClientNotifyFunc)browse_with_caret_notifier, window);
3212 priv->allow_popups_notifier_id = eel_gconf_notification_add
3213 (CONF_SECURITY_ALLOW_POPUPS,
3214 (GConfClientNotifyFunc)allow_popups_notifier, window);
3216 /* network status */
3217 single = EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell));
3218 sync_network_status (single, NULL, window);
3219 g_signal_connect (single, "notify::network-status",
3220 G_CALLBACK (sync_network_status), window);
3223 toolbar_action_group = ephy_toolbar_get_action_group (priv->toolbar);
3224 action = gtk_action_group_get_action (toolbar_action_group, "FileNewTab");
3225 ephy_action_change_sensitivity_flags (action, SENS_FLAG_CHROME, priv->is_popup);
3227 action = gtk_action_group_get_action (priv->popups_action_group, "OpenLinkInNewTab");
3228 ephy_action_change_sensitivity_flags (action, SENS_FLAG_CHROME, priv->is_popup);
3230 /* Connect lock clicks */
3231 action = gtk_action_group_get_action (priv->action_group, "ViewPageSecurityInfo");
3232 g_signal_connect_swapped (priv->statusbar, "lock-clicked",
3233 G_CALLBACK (gtk_action_activate), action);
3234 g_signal_connect_swapped (priv->toolbar, "lock-clicked",
3235 G_CALLBACK (gtk_action_activate), action);
3237 /* ensure the UI is updated */
3238 gtk_ui_manager_ensure_update (priv->manager);
3240 init_menu_updaters (window);
3242 update_chromes_actions (window);
3244 sync_chromes_visibility (window);
3250 ephy_window_finalize (GObject *object)
3252 EphyWindow *window = EPHY_WINDOW (object);
3253 EphyWindowPrivate *priv = window->priv;
3255 g_hash_table_destroy (priv->tabs_to_remove);
3257 G_OBJECT_CLASS (parent_class)->finalize (object);
3259 LOG ("EphyWindow finalised %p", object);
3261 #ifdef ENABLE_PYTHON
3262 ephy_python_schedule_gc ();
3265 g_object_unref (ephy_shell);
3271 * Equivalent to g_object_new() but returns an #EphyWindow so you don't have
3274 * Return value: a new #EphyWindow
3277 ephy_window_new (void)
3279 return EPHY_WINDOW (g_object_new (EPHY_TYPE_WINDOW, NULL));
3283 * ephy_window_new_with_chrome:
3284 * @chrome: an #EphyEmbedChrome
3285 * @is_popup: whether the new window is a popup window
3287 * Identical to ephy_window_new(), but allows you to specify a chrome.
3289 * Return value: a new #EphyWindow
3292 ephy_window_new_with_chrome (EphyEmbedChrome chrome,
3295 return EPHY_WINDOW (g_object_new (EPHY_TYPE_WINDOW,
3297 "is-popup", is_popup,
3302 * ephy_window_set_print_preview:
3303 * @window: an #EphyWindow
3304 * @enabled: %TRUE to enable print preview mode
3306 * Sets whether the window is in print preview mode.
3309 ephy_window_set_print_preview (EphyWindow *window,
3312 EphyWindowPrivate *priv = window->priv;
3313 GtkAccelGroup *accel_group;
3315 accel_group = gtk_ui_manager_get_accel_group (window->priv->manager);
3317 if (priv->ppv_mode == enabled) return;
3319 priv->ppv_mode = enabled;
3321 sync_chromes_visibility (window);
3325 g_return_if_fail (priv->ppview_toolbar == NULL);
3327 ephy_find_toolbar_request_close (priv->find_toolbar);
3329 priv->ppview_toolbar = ppview_toolbar_new (window);
3330 gtk_window_remove_accel_group (GTK_WINDOW (window), accel_group);
3334 g_return_if_fail (priv->ppview_toolbar != NULL);
3336 g_object_unref (priv->ppview_toolbar);
3337 priv->ppview_toolbar = NULL;
3338 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
3341 g_object_notify (G_OBJECT (window), "print-preview-mode");
3345 * ephy_window_get_ui_manager:
3346 * @window: an #EphyWindow
3348 * Returns this window's UI manager.
3350 * Return value: an #GtkUIManager
3353 ephy_window_get_ui_manager (EphyWindow *window)
3355 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3357 return G_OBJECT (window->priv->manager);
3361 * ephy_window_get_toolbar:
3362 * @window: an #EphyWindow
3364 * Returns this window's toolbar as an #EggEditableToolbar.
3366 * Return value: an #EggEditableToolbar
3369 ephy_window_get_toolbar (EphyWindow *window)
3371 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3373 return GTK_WIDGET (window->priv->toolbar);
3377 * ephy_window_get_notebook:
3378 * @window: an #EphyWindow
3380 * Returns the #GtkNotebook used by this window.
3382 * Return value: the @window's #GtkNotebook
3385 ephy_window_get_notebook (EphyWindow *window)
3387 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3389 return GTK_WIDGET (window->priv->notebook);
3393 * ephy_window_get_find_toolbar:
3394 * @window: an #EphyWindow
3396 * Returns the #EphyFindToolbar used by this window.
3398 * Return value: the @window's #EphyFindToolbar
3401 ephy_window_get_find_toolbar (EphyWindow *window)
3403 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3405 return GTK_WIDGET (window->priv->find_toolbar);
3409 * ephy_window_get_statusbar:
3410 * @window: an #EphyWindow
3412 * Returns this window's statusbar as an #EphyStatusbar.
3414 * Return value: This window's statusbar
3417 ephy_window_get_statusbar (EphyWindow *window)
3419 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3421 return GTK_WIDGET (window->priv->statusbar);
3425 * ephy_window_add_tab:
3426 * @window: an #EphyWindow
3428 * @position: the position in @window's #GtkNotebook
3429 * @jump_to: %TRUE to switch to @tab's new notebook page after insertion
3431 * Inserts @tab into @window.
3434 ephy_window_add_tab (EphyWindow *window,
3441 g_return_if_fail (EPHY_IS_WINDOW (window));
3442 g_return_if_fail (EPHY_IS_TAB (tab));
3443 g_return_if_fail (!window->priv->is_popup ||
3444 gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) < 1);
3446 widget = GTK_WIDGET(ephy_tab_get_embed (tab));
3448 ephy_notebook_add_tab (EPHY_NOTEBOOK (window->priv->notebook),
3449 tab, position, jump_to);
3453 * ephy_window_jump_to_tab:
3454 * @window: an #EphyWindow
3455 * @tab: an #EphyTab inside @window
3457 * Switches @window's #GtkNotebook to open @tab as its current page.
3460 ephy_window_jump_to_tab (EphyWindow *window,
3465 page = gtk_notebook_page_num
3466 (window->priv->notebook, GTK_WIDGET (tab));
3467 gtk_notebook_set_current_page
3468 (window->priv->notebook, page);
3472 real_get_active_tab (EphyWindow *window, int page_num)
3478 page_num = gtk_notebook_get_current_page (window->priv->notebook);
3480 tab = gtk_notebook_get_nth_page (window->priv->notebook, page_num);
3482 g_return_val_if_fail (EPHY_IS_TAB (tab), NULL);
3484 return EPHY_TAB (tab);
3488 * ephy_window_remove_tab:
3489 * @window: an #EphyWindow
3492 * Removes @tab from @window.
3495 ephy_window_remove_tab (EphyWindow *window,
3498 EphyWindowPrivate *priv = window->priv;
3500 GtkNotebook *notebook;
3504 g_return_if_fail (EPHY_IS_WINDOW (window));
3505 g_return_if_fail (EPHY_IS_TAB (tab));
3507 embed = ephy_tab_get_embed (tab);
3508 g_return_if_fail (EPHY_IS_EMBED (embed));
3510 modified = ephy_embed_has_modified_forms (embed);
3511 if (ephy_embed_has_modified_forms (embed)
3512 && confirm_close_with_modified_forms (window) == FALSE)
3514 /* don't close the tab */
3518 notebook = GTK_NOTEBOOK (priv->notebook);
3519 position = gtk_notebook_page_num (notebook, GTK_WIDGET (tab));
3520 gtk_notebook_remove_page (notebook, position);
3524 * ephy_window_load_url:
3525 * @window: a #EphyWindow
3526 * @url: the url to load
3528 * Loads a new url in the active tab of @window.
3529 * Unlike ephy_embed_load_url(), this function activates
3534 ephy_window_load_url (EphyWindow *window,
3537 g_return_if_fail (url != NULL);
3539 ephy_link_open (EPHY_LINK (window), url, NULL, 0);
3543 * ephy_window_activate_location:
3544 * @window: an #EphyWindow
3546 * Activates the location entry on @window's toolbar.
3549 ephy_window_activate_location (EphyWindow *window)
3551 if (window->priv->fullscreen_popup)
3553 gtk_widget_hide (window->priv->fullscreen_popup);
3556 ephy_toolbar_activate_location (window->priv->toolbar);
3560 ephy_window_show (GtkWidget *widget)
3562 EphyWindow *window = EPHY_WINDOW(widget);
3563 EphyWindowPrivate *priv = window->priv;
3565 if (!priv->has_size)
3570 tab = ephy_window_get_active_tab (EPHY_WINDOW (window));
3571 g_return_if_fail (tab != NULL);
3573 ephy_tab_get_size (tab, &width, &height);
3574 if (width == -1 && height == -1)
3576 ephy_state_add_window (widget, "main_window", 600, 500,
3577 TRUE, EPHY_STATE_WINDOW_SAVE_SIZE);
3580 priv->has_size = TRUE;
3583 GTK_WIDGET_CLASS (parent_class)->show (widget);
3587 * ephy_window_get_active_tab:
3588 * @window: an #EphyWindow
3590 * Returns @window's active #EphyTab.
3592 * Return value: @window's active tab
3595 ephy_window_get_active_tab (EphyWindow *window)
3597 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3599 return window->priv->active_tab;
3603 * ephy_window_get_active_embed:
3604 * @window: an #EphyWindow
3606 * Return @window's active #EphyEmbed. This is identical to calling
3607 * ephy_window_get_active_tab() followed by ephy_tab_get_embed().
3609 * Return value: @window's active embed
3612 ephy_window_get_active_embed (EphyWindow *window)
3616 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3618 tab = ephy_window_get_active_tab (window);
3619 if (tab == NULL) return NULL;
3621 return ephy_tab_get_embed (tab);
3625 * ephy_window_get_tabs:
3626 * @window: a #EphyWindow
3628 * Returns the list of #EphyTab:s in the window.
3630 * Return value: a newly-allocated list of #EphyTab:s
3633 ephy_window_get_tabs (EphyWindow *window)
3635 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3637 return gtk_container_get_children (GTK_CONTAINER (window->priv->notebook));
3641 notebook_switch_page_cb (GtkNotebook *notebook,
3642 GtkNotebookPage *page,
3646 EphyWindowPrivate *priv = window->priv;
3650 LOG ("switch-page notebook %p position %u\n", notebook, page_num);
3652 if (priv->closing) return;
3654 /* get the new tab */
3655 tab = real_get_active_tab (window, page_num);
3656 embed = ephy_tab_get_embed (tab);
3658 /* update new tab */
3659 ephy_window_set_active_tab (window, tab);
3661 ephy_find_toolbar_set_embed (priv->find_toolbar, embed);
3663 /* update window controls */
3664 update_tabs_menu_sensitivity (window);
3668 * ephy_window_set_zoom:
3669 * @window: an #EphyWindow
3670 * @zoom: the desired zoom level
3672 * Sets the zoom on @window's active #EphyEmbed. A @zoom of 1.0 corresponds to
3673 * 100% zoom (normal size).
3676 ephy_window_set_zoom (EphyWindow *window,
3680 float current_zoom = 1.0;
3682 g_return_if_fail (EPHY_IS_WINDOW (window));
3684 embed = ephy_window_get_active_embed (window);
3685 g_return_if_fail (embed != NULL);
3687 current_zoom = ephy_embed_get_zoom (embed);
3689 if (zoom == ZOOM_IN)
3691 zoom = ephy_zoom_get_changed_zoom_level (current_zoom, 1);
3693 else if (zoom == ZOOM_OUT)
3695 zoom = ephy_zoom_get_changed_zoom_level (current_zoom, -1);
3698 if (zoom != current_zoom)
3700 ephy_embed_set_zoom (embed, zoom);
3705 sync_prefs_with_chrome (EphyWindow *window)
3707 EphyEmbedChrome flags = window->priv->chrome;
3709 if (window->priv->should_save_chrome)
3711 eel_gconf_set_boolean (CONF_WINDOWS_SHOW_TOOLBARS,
3712 flags & EPHY_EMBED_CHROME_TOOLBAR);
3713 eel_gconf_set_boolean (CONF_WINDOWS_SHOW_STATUSBAR,
3714 flags & EPHY_EMBED_CHROME_STATUSBAR);
3719 sync_chrome_with_view_toggle (GtkAction *action,
3721 EphyEmbedChrome chrome_flag,
3726 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3727 window->priv->chrome = (active != invert) ?
3728 window->priv->chrome | chrome_flag :
3729 window->priv->chrome & (~chrome_flag);
3731 sync_chromes_visibility (window);
3732 sync_prefs_with_chrome (window);
3736 ephy_window_view_statusbar_cb (GtkAction *action,
3739 sync_chrome_with_view_toggle (action, window,
3740 EPHY_EMBED_CHROME_STATUSBAR, FALSE);
3744 ephy_window_view_toolbar_cb (GtkAction *action,
3747 sync_chrome_with_view_toggle (action, window,
3748 EPHY_EMBED_CHROME_TOOLBAR, TRUE);
3752 ephy_window_view_popup_windows_cb (GtkAction *action,
3758 g_return_if_fail (EPHY_IS_WINDOW (window));
3760 tab = ephy_window_get_active_tab (window);
3761 g_return_if_fail (EPHY_IS_TAB (tab));
3763 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3772 g_object_set (G_OBJECT (tab), "popups-allowed", allow, NULL);
3776 * ephy_window_get_is_popup:
3777 * @window: an #EphyWindow
3779 * Returns whether this window is a popup window.
3781 * Return value: %TRUE if it is a popup window
3784 ephy_window_get_is_popup (EphyWindow *window)
3786 g_return_val_if_fail (EPHY_IS_WINDOW (window), FALSE);
3788 return window->priv->is_popup;
3792 * ephy_window_get_is_print_preview:
3793 * @window: an #EphyWindow
3795 * Returns whether this window is in print preview mode.
3797 * Return value: %TRUE if it is in print preview mode
3800 ephy_window_get_is_print_preview (EphyWindow *window)
3802 g_return_val_if_fail (EPHY_IS_WINDOW (window), FALSE);
3804 return window->priv->ppv_mode;
3808 * ephy_window_get_context_event:
3809 * @window: an #EphyWindow
3811 * Returns the #EphyEmbedEvent for the current context menu.
3812 * Use this to get the event from the action callback.
3814 * Return value: an #EphyEmbedEvent, or %NULL
3817 ephy_window_get_context_event (EphyWindow *window)
3819 g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL);
3821 return window->priv->context_event;