From ffdcb7ffd0191129ccee3d377cae306c81b10594 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Sun, 17 Apr 2005 19:39:00 +0000 Subject: Rework popup windows. Introduce "is-popup" property on EphyWindow to 2005-04-17 Christian Persch * src/ephy-automation.c: (impl_ephy_automation_loadUrlWithStartupId): * src/ephy-notebook.c: (ephy_notebook_set_dnd_enabled), (ephy_notebook_get_property), (ephy_notebook_set_property), (ephy_notebook_class_init), (move_tab_to_another_notebook), (button_press_cb), (ephy_notebook_init): * src/ephy-notebook.h: * src/ephy-session.c: (ephy_session_get_active_window): * src/ephy-shell.c: (ephy_shell_new_window_cb), (ephy_shell_new_tab_full), (ephy_shell_new_tab): * src/ephy-shell.h: * src/ephy-tab.c: (ephy_tab_class_init), (popups_manager_new_window_info), (ephy_tab_dispose), (ephy_tab_finalize), (let_me_resize_hack), (ephy_tab_set_size), (ephy_tab_init): * src/ephy-tab.h: * src/ephy-window.c: (get_chromes_visibility), (sync_chromes_visibility), (update_chromes_actions), (update_actions_sensitivity), (sync_tab_visibility), (show_embed_popup), (let_me_resize_hack), (tab_size_to_cb), (ephy_window_set_active_tab), (ephy_window_set_chrome), (ephy_window_set_is_popup), (ephy_window_dispose), (ephy_window_set_property), (ephy_window_get_property), (ephy_window_class_init), (ephy_window_init), (ephy_window_constructor), (ephy_window_new_with_chrome), (ephy_window_set_print_preview), (ephy_window_add_tab), (ephy_window_show), (ephy_window_view_popup_windows_cb), (ephy_window_get_is_popup): * src/ephy-window.h: Rework popup windows. Introduce "is-popup" property on EphyWindow to indicate a window who will only have one tab, and can be resized by javascript calls. Fixes bug #136288 and #155395. --- src/ephy-automation.c | 2 +- src/ephy-notebook.c | 100 +++++++++++++++-- src/ephy-notebook.h | 3 + src/ephy-session.c | 14 +-- src/ephy-shell.c | 9 +- src/ephy-shell.h | 1 + src/ephy-tab.c | 153 +++++++++++++++----------- src/ephy-tab.h | 4 + src/ephy-window.c | 294 +++++++++++++++++++++++++++++++++++++------------- src/ephy-window.h | 5 +- 10 files changed, 434 insertions(+), 151 deletions(-) (limited to 'src') diff --git a/src/ephy-automation.c b/src/ephy-automation.c index 99fb8071a..84b155a8a 100644 --- a/src/ephy-automation.c +++ b/src/ephy-automation.c @@ -106,7 +106,7 @@ impl_ephy_automation_loadUrlWithStartupId (PortableServer_Servant _servant, } ephy_shell_new_tab_full (ephy_shell, window, NULL, url, flags, - EPHY_EMBED_CHROME_ALL, user_time); + EPHY_EMBED_CHROME_ALL, FALSE, user_time); } static void diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c index 02bf907f6..8ba8c29ba 100644 --- a/src/ephy-notebook.c +++ b/src/ephy-notebook.c @@ -67,9 +67,12 @@ struct _EphyNotebookPrivate GtkTooltips *title_tips; guint tabs_vis_notifier_id; gulong motion_notify_handler_id; - gint x_start, y_start; - gboolean drag_in_progress; - gboolean show_tabs; + int x_start; + int y_start; + + guint drag_in_progress : 1; + guint show_tabs : 1; + guint dnd_enabled : 1; }; static void ephy_notebook_init (EphyNotebook *notebook); @@ -90,6 +93,13 @@ static GtkTargetEntry url_drag_types [] = }; static guint n_url_drag_types = G_N_ELEMENTS (url_drag_types); +enum +{ + PROP_0, + PROP_DND_ENABLED, + PROP_SHOW_TABS +}; + enum { TAB_ADDED, @@ -142,6 +152,57 @@ ephy_notebook_get_type (void) return type; } +void +ephy_notebook_set_dnd_enabled (EphyNotebook *notebook, + gboolean enabled) +{ + EphyNotebookPrivate *priv = notebook->priv; + + priv->dnd_enabled = enabled; + /* FIXME abort any DNDs in progress */ + + g_object_notify (G_OBJECT (notebook), "dnd-enabled"); +} + +static void +ephy_notebook_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyNotebook *notebook = EPHY_NOTEBOOK (object); + EphyNotebookPrivate *priv = notebook->priv; + + switch (prop_id) + { + case PROP_DND_ENABLED: + g_value_set_boolean (value, priv->dnd_enabled); + break; + case PROP_SHOW_TABS: + g_value_set_boolean (value, priv->show_tabs); + break; + } +} + +static void +ephy_notebook_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyNotebook *notebook = EPHY_NOTEBOOK (object); + + switch (prop_id) + { + case PROP_DND_ENABLED: + ephy_notebook_set_dnd_enabled (notebook, g_value_get_boolean (value)); + break; + case PROP_SHOW_TABS: + ephy_notebook_set_show_tabs (notebook, g_value_get_boolean (value)); + break; + } +} + static void ephy_notebook_class_init (EphyNotebookClass *klass) { @@ -150,6 +211,8 @@ ephy_notebook_class_init (EphyNotebookClass *klass) parent_class = g_type_class_peek_parent (klass); object_class->finalize = ephy_notebook_finalize; + object_class->get_property = ephy_notebook_get_property; + object_class->set_property = ephy_notebook_set_property; signals[TAB_ADDED] = g_signal_new ("tab_added", @@ -201,7 +264,23 @@ ephy_notebook_class_init (EphyNotebookClass *klass) 1, EPHY_TYPE_TAB); - g_type_class_add_private (object_class, sizeof(EphyNotebookPrivate)); + g_object_class_install_property (object_class, + PROP_DND_ENABLED, + g_param_spec_boolean ("dnd-enabled", + "DND enabled", + "Whether the notebook allows tab reordering by DND", + TRUE, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_SHOW_TABS, + g_param_spec_boolean ("show-tabs", + "Show tabs", + "Whether the notebook shows the tabs bar", + TRUE, + G_PARAM_READWRITE)); + + g_type_class_add_private (object_class, sizeof (EphyNotebookPrivate)); } static EphyNotebook * @@ -476,6 +555,9 @@ move_tab_to_another_notebook (EphyNotebook *src, g_assert (EPHY_IS_NOTEBOOK (dest)); g_assert (dest != src); + /* Check if the dest notebook can accept the drag */ + if (!dest->priv->dnd_enabled) return; + cur_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (src)); tab = EPHY_TAB (gtk_notebook_get_nth_page (GTK_NOTEBOOK (src), cur_page)); @@ -543,10 +625,13 @@ button_press_cb (EphyNotebook *notebook, GdkEventButton *event, gpointer data) { - gint tab_clicked = find_tab_num_at_pos (notebook, - event->x_root, - event->y_root); + int tab_clicked; + + if (!notebook->priv->dnd_enabled) return FALSE; + + tab_clicked = find_tab_num_at_pos (notebook, event->x_root, event->y_root); + /* FIXME: how could there be a drag in progress!? */ if (notebook->priv->drag_in_progress) { return TRUE; @@ -705,6 +790,7 @@ ephy_notebook_init (EphyNotebook *notebook) gtk_object_sink (GTK_OBJECT (notebook->priv->title_tips)); notebook->priv->show_tabs = TRUE; + notebook->priv->dnd_enabled = TRUE; g_signal_connect (notebook, "button-press-event", (GCallback)button_press_cb, NULL); diff --git a/src/ephy-notebook.h b/src/ephy-notebook.h index 19cdc2f3a..04ae54fcd 100644 --- a/src/ephy-notebook.h +++ b/src/ephy-notebook.h @@ -85,6 +85,9 @@ void ephy_notebook_move_tab (EphyNotebook *src, void ephy_notebook_set_show_tabs (EphyNotebook *nb, gboolean show_tabs); +void ephy_notebook_set_dnd_enabled (EphyNotebook *nb, + gboolean enabled); + G_END_DECLS #endif /* EPHY_NOTEBOOK_H */ diff --git a/src/ephy-session.c b/src/ephy-session.c index 68e448504..a54e81401 100644 --- a/src/ephy-session.c +++ b/src/ephy-session.c @@ -926,20 +926,22 @@ ephy_session_remove_window (EphySession *session, * need to take an action (like opening an url) on * a window but you dont have a target window. * - * Return value: the current active browser window, or NULL of there is none. + * Return value: the current active non-popup browser window, or NULL of there is none. **/ EphyWindow * ephy_session_get_active_window (EphySession *session) { - GList *first; + EphyWindow *window = NULL; + GList *l; g_return_val_if_fail (EPHY_IS_SESSION (session), NULL); - first = session->priv->windows; - if (first != NULL) + for (l = session->priv->windows; l != NULL; l = l->next) { - return EPHY_WINDOW (first->data); + window = EPHY_WINDOW (l->data); + + if (ephy_window_get_is_popup (window) == FALSE) break; } - return NULL; + return window; } diff --git a/src/ephy-shell.c b/src/ephy-shell.c index 9babb803b..807faff3b 100644 --- a/src/ephy-shell.c +++ b/src/ephy-shell.c @@ -182,7 +182,7 @@ ephy_shell_new_window_cb (EphyEmbedSingle *single, new_tab = ephy_shell_new_tab_full (shell, EPHY_IS_WINDOW (parent) ? EPHY_WINDOW (parent) : NULL, - NULL, NULL, flags, chromemask, 0); + NULL, NULL, flags, chromemask, TRUE, 0); return ephy_tab_get_embed (new_tab); } @@ -650,6 +650,7 @@ load_homepage (EphyEmbed *embed) * @previous_tab: the referrer tab or %NULL * @url: an url to load or %NULL * @chrome: a #EphyEmbedChrome mask to use if creating a new window + * @is_popup: whether the new window is a popup * @user_time: a timestamp, or 0 * * Create a new tab and the parent window when necessary. @@ -664,6 +665,7 @@ ephy_shell_new_tab_full (EphyShell *shell, const char *url, EphyNewTabFlags flags, EphyEmbedChrome chrome, + gboolean is_popup, guint32 user_time) { EphyWindow *window; @@ -680,6 +682,7 @@ ephy_shell_new_tab_full (EphyShell *shell, if (flags & EPHY_NEW_TAB_IN_EXISTING_WINDOW) in_new_window = FALSE; in_new_window = in_new_window && !eel_gconf_get_boolean (CONF_LOCKDOWN_FULLSCREEN); + g_return_val_if_fail (in_new_window || !is_popup, NULL); jump_to = (flags & EPHY_NEW_TAB_JUMP) != 0; @@ -692,7 +695,7 @@ ephy_shell_new_tab_full (EphyShell *shell, } else { - window = ephy_window_new_with_chrome (chrome); + window = ephy_window_new_with_chrome (chrome, is_popup); } toolbar = EPHY_TOOLBAR (ephy_window_get_toolbar (window)); @@ -764,7 +767,7 @@ ephy_shell_new_tab (EphyShell *shell, { return ephy_shell_new_tab_full (shell, parent_window, previous_tab, url, flags, - EPHY_EMBED_CHROME_ALL, 0); + EPHY_EMBED_CHROME_ALL, FALSE, 0); } /** diff --git a/src/ephy-shell.h b/src/ephy-shell.h index 32e5f9383..17319d79f 100644 --- a/src/ephy-shell.h +++ b/src/ephy-shell.h @@ -130,6 +130,7 @@ EphyTab *ephy_shell_new_tab_full (EphyShell *shell, const char *url, EphyNewTabFlags flags, EphyEmbedChrome chrome, + gboolean is_popup, guint32 user_time); GObject *ephy_shell_get_session (EphyShell *shell); diff --git a/src/ephy-tab.c b/src/ephy-tab.c index 09debb6f1..db7a005c2 100644 --- a/src/ephy-tab.c +++ b/src/ephy-tab.c @@ -87,10 +87,12 @@ struct _EphyTabPrivate GSList *shown_popups; EphyTabNavigationFlags nav_flags; EphyEmbedDocumentType document_type; + guint idle_resize_handler; }; static void ephy_tab_class_init (EphyTabClass *klass); static void ephy_tab_init (EphyTab *tab); +static void ephy_tab_dispose (GObject *object); static void ephy_tab_finalize (GObject *object); enum @@ -343,7 +345,8 @@ ephy_tab_class_init (EphyTabClass *class) parent_class = g_type_class_peek_parent (class); - object_class->finalize = ephy_tab_finalize; + object_class->dispose = ephy_tab_dispose; + object_class->finalize = ephy_tab_finalize; object_class->get_property = ephy_tab_get_property; object_class->set_property = ephy_tab_set_property; @@ -632,16 +635,20 @@ popups_manager_show_all (EphyTab *tab) static char * popups_manager_new_window_info (EphyWindow *window) { + EphyTab *tab; EphyEmbedChrome chrome; + gboolean is_popup; char *features; - int w, h; - g_object_get (window, "chrome", &chrome, NULL); - gtk_window_get_size (GTK_WINDOW (window), &w, &h); + g_object_get (window, "chrome", &chrome, "is-popup", &is_popup, NULL); + g_return_val_if_fail (is_popup, g_strdup ("")); + + tab = ephy_window_get_active_tab (window); + g_return_val_if_fail (tab != NULL, g_strdup ("")); features = g_strdup_printf ("width=%d,height=%d,menubar=%d,status=%d,toolbar=%d", - w, h, + tab->priv->width, tab->priv->height, (chrome & EPHY_EMBED_CHROME_MENUBAR) > 0, (chrome & EPHY_EMBED_CHROME_STATUSBAR) > 0, (chrome & EPHY_EMBED_CHROME_TOOLBAR) > 0); @@ -746,17 +753,31 @@ popups_manager_reset (EphyTab *tab) } static void -ephy_tab_finalize (GObject *object) +ephy_tab_dispose (GObject *object) { - EphyTab *tab = EPHY_TAB (object); + EphyTab *tab = EPHY_TAB (object); + EphyTabPrivate *priv = tab->priv; - g_idle_remove_by_data (tab); + if (priv->idle_resize_handler != 0) + { + g_source_remove (priv->idle_resize_handler); + priv->idle_resize_handler = 0; + } - g_free (tab->priv->title); - g_free (tab->priv->address); - g_free (tab->priv->icon_address); - g_free (tab->priv->link_message); - g_free (tab->priv->status_message); + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +ephy_tab_finalize (GObject *object) +{ + EphyTab *tab = EPHY_TAB (object); + EphyTabPrivate *priv = tab->priv; + + g_free (priv->title); + g_free (priv->address); + g_free (priv->icon_address); + g_free (priv->link_message); + g_free (priv->status_message); popups_manager_reset (tab); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -782,6 +803,17 @@ address_has_web_scheme (const char *address) return has_web_scheme; } +static gboolean +let_me_resize_hack (EphyTab *tab) +{ + EphyTabPrivate *priv = tab->priv; + + gtk_widget_set_size_request (GTK_WIDGET (tab), -1, -1); + + priv->idle_resize_handler = 0; + return FALSE; +} + /* Public functions */ /** @@ -937,6 +969,54 @@ ephy_tab_get_size (EphyTab *tab, int *width, int *height) } } +/** + * ephy_tab_set_size: + * @tab: an #EphyTab + * @width: + * @height: + * + * Sets the size of @tab. This is not guaranteed to actually resize the tab. + **/ +void +ephy_tab_set_size (EphyTab *tab, + int width, + int height) +{ + EphyTabPrivate *priv = tab->priv; + GtkWidget *widget = GTK_WIDGET (tab); + GtkAllocation allocation; + + priv->width = width; + priv->height = height; + + gtk_widget_set_size_request (widget, width, height); + + /* HACK: When the web site changes both width and height, + * we will first get a width change, then a height change, + * without actually resizing the window in between (since + * that happens only on idle). + * If we don't set the allocation, GtkMozEmbed doesn't tell + * mozilla the new width, so the height change sets the width + * back to the old value! + */ + allocation.x = widget->allocation.x; + allocation.y = widget->allocation.y; + allocation.width = width; + allocation.height = height; + gtk_widget_size_allocate (widget, &allocation); + + /* HACK: reset widget requisition after the container + * has been resized. It appears to be the only way + * to have the window sized according to embed + * size correctly. + */ + if (priv->idle_resize_handler == 0) + { + priv->idle_resize_handler = + g_idle_add ((GSourceFunc) let_me_resize_hack, tab); + } +} + /** * ephy_tab_get_visibility: * @tab: an #EphyTab @@ -1330,14 +1410,6 @@ ephy_tab_popup_blocked_cb (EphyEmbed *embed, const char *url, popups_manager_add (tab, url, features); } -static gboolean -let_me_resize_hack (GtkWidget *tab) -{ - gtk_widget_set_size_request (tab, -1, -1); - - return FALSE; -} - static void ephy_tab_visibility_cb (EphyEmbed *embed, gboolean visibility, EphyTab *tab) @@ -1379,42 +1451,6 @@ ephy_tab_destroy_brsr_cb (EphyEmbed *embed, EphyTab *tab) ephy_notebook_remove_tab (EPHY_NOTEBOOK (notebook), tab); } -static void -ephy_tab_size_to_cb (EphyEmbed *embed, gint width, gint height, - EphyTab *tab) -{ - GtkWidget *notebook; - EphyWindow *window; - - LOG ("ephy_tab_size_to_cb tab %p width %d height %d", tab, width, height); - - tab->priv->width = width; - tab->priv->height = height; - - window = ephy_tab_get_window (tab); - notebook = ephy_window_get_notebook (window); - - /* Do not resize window with multiple tabs. - * Do not resize window already showed because - * it's not possible to calculate a sensible window - * size based on the embed size */ - if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) == 1 && - !tab->priv->visibility) - { - gtk_widget_set_size_request - (GTK_WIDGET (tab), width, height); - - /* HACK reset widget requisition after the container - * has been resized. It appears to be the only way - * to have the window sized according to embed - * size correctly. - */ - - g_idle_add ((GSourceFunc) let_me_resize_hack, tab); - } -} - - static gboolean open_link_in_new_tab (EphyTab *tab, const char *link_address) @@ -1637,9 +1673,6 @@ ephy_tab_init (EphyTab *tab) g_signal_connect_object (embed, "destroy_browser", G_CALLBACK (ephy_tab_destroy_brsr_cb), tab, 0); - g_signal_connect_object (embed, "size_to", - G_CALLBACK (ephy_tab_size_to_cb), - tab, 0); g_signal_connect_object (embed, "ge_dom_mouse_click", G_CALLBACK (ephy_tab_dom_mouse_click_cb), tab, 0); diff --git a/src/ephy-tab.h b/src/ephy-tab.h index f341f6887..a21f0dfa5 100644 --- a/src/ephy-tab.h +++ b/src/ephy-tab.h @@ -99,6 +99,10 @@ void ephy_tab_get_size (EphyTab *tab, int *width, int *height); +void ephy_tab_set_size (EphyTab *tab, + int width, + int height); + const char *ephy_tab_get_status_message (EphyTab *tab); const char *ephy_tab_get_title (EphyTab *tab); diff --git a/src/ephy-window.c b/src/ephy-window.c index 859801e72..b24ebfa6e 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -77,6 +77,9 @@ static void ephy_window_class_init (EphyWindowClass *klass); static void ephy_window_link_iface_init (EphyLinkIface *iface); static void ephy_window_init (EphyWindow *gs); +static GObject *ephy_window_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params); static void ephy_window_finalize (GObject *object); static void ephy_window_show (GtkWidget *widget); static EphyTab *ephy_window_open_link (EphyLink *link, @@ -415,6 +418,7 @@ struct _EphyWindowPrivate guint tab_message_cid; guint help_message_cid; EphyEmbedChrome chrome; + guint idle_resize_handler; guint disable_arbitrary_url_notifier_id; guint disable_bookmark_editing_notifier_id; @@ -432,6 +436,7 @@ struct _EphyWindowPrivate guint fullscreen_mode : 1; guint ppv_mode : 1; guint should_save_chrome : 1; + guint is_popup : 1; }; enum @@ -439,7 +444,8 @@ enum PROP_0, PROP_ACTIVE_TAB, PROP_CHROME, - PROP_PPV_MODE + PROP_PPV_MODE, + PROP_SINGLE_TAB_MODE }; static GObjectClass *parent_class = NULL; @@ -520,20 +526,29 @@ get_toolbar_visibility (EphyWindow *window) } static void -get_chromes_visibility (EphyWindow *window, gboolean *show_menubar, - gboolean *show_statusbar, gboolean *show_toolbar, - gboolean *show_bookmarksbar) +get_chromes_visibility (EphyWindow *window, + gboolean *show_menubar, + gboolean *show_statusbar, + gboolean *show_toolbar, + gboolean *show_bookmarksbar, + gboolean *show_tabsbar) { - EphyEmbedChrome flags = window->priv->chrome; + EphyWindowPrivate *priv = window->priv; + EphyEmbedChrome flags = priv->chrome; if (window->priv->ppv_mode) { - *show_menubar = *show_statusbar = *show_toolbar = *show_bookmarksbar = FALSE; + *show_menubar = *show_statusbar + = *show_toolbar + = *show_bookmarksbar + = *show_tabsbar + = FALSE; } else if (window->priv->fullscreen_mode) { *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0; *show_menubar = *show_statusbar = *show_bookmarksbar = FALSE; + *show_tabsbar = !priv->is_popup; } else { @@ -541,6 +556,7 @@ get_chromes_visibility (EphyWindow *window, gboolean *show_menubar, *show_statusbar = (flags & EPHY_EMBED_CHROME_STATUSBAR) != 0; *show_toolbar = (flags & EPHY_EMBED_CHROME_TOOLBAR) != 0; *show_bookmarksbar = (flags & EPHY_EMBED_CHROME_BOOKMARKSBAR) != 0; + *show_tabsbar = !priv->is_popup; } } @@ -549,13 +565,13 @@ sync_chromes_visibility (EphyWindow *window) { EphyWindowPrivate *priv = window->priv; GtkWidget *menubar; - gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar; + gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar, show_tabsbar; if (priv->closing) return; get_chromes_visibility (window, &show_menubar, &show_statusbar, &show_toolbar, - &show_bookmarksbar); + &show_bookmarksbar, &show_tabsbar); menubar = gtk_ui_manager_get_widget (window->priv->manager, "/menubar"); g_assert (menubar != NULL); @@ -567,6 +583,8 @@ sync_chromes_visibility (EphyWindow *window) ephy_toolbar_set_lock_visibility (priv->toolbar, !show_statusbar); + ephy_notebook_set_show_tabs (EPHY_NOTEBOOK (priv->notebook), show_tabsbar); + if (priv->fullscreen_popup != NULL) { g_object_set (priv->fullscreen_popup, "visible", !show_toolbar, NULL); @@ -980,11 +998,11 @@ update_chromes_actions (EphyWindow *window) { GtkActionGroup *action_group = window->priv->action_group; GtkAction *action; - gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar; + gboolean show_statusbar, show_menubar, show_toolbar, show_bookmarksbar, show_tabsbar; get_chromes_visibility (window, &show_menubar, &show_statusbar, &show_toolbar, - &show_bookmarksbar); + &show_bookmarksbar, &show_tabsbar); action = gtk_action_group_get_action (action_group, "ViewToolbar"); g_signal_handlers_block_by_func (G_OBJECT (action), @@ -1038,11 +1056,15 @@ update_print_actions (EphyWindow *window, static void update_actions_sensitivity (EphyWindow *window) { - GtkActionGroup *action_group = window->priv->action_group; - GtkActionGroup *popups_action_group = window->priv->popups_action_group; + EphyWindowPrivate *priv = window->priv; + GtkActionGroup *action_group = priv->action_group; + GtkActionGroup *popups_action_group = priv->popups_action_group; GtkAction *action; gboolean bookmarks_editable, save_to_disk, fullscreen; + action = gtk_action_group_get_action (action_group, "FileNewTab"); + g_object_set (action, "sensitive", !priv->is_popup, NULL); + action = gtk_action_group_get_action (action_group, "ViewToolbar"); g_object_set (action, "sensitive", eel_gconf_key_is_writable (CONF_WINDOWS_SHOW_TOOLBARS), NULL); @@ -1528,12 +1550,15 @@ sync_tab_title (EphyTab *tab, GParamSpec *pspec, EphyWindow *window) } static void -sync_tab_visibility (EphyTab *tab, GParamSpec *pspec, EphyWindow *window) +sync_tab_visibility (EphyTab *tab, + GParamSpec *pspec, + EphyWindow *window) { + EphyWindowPrivate *priv = window->priv; GList *l, *tabs; gboolean visible = FALSE; - if (window->priv->closing) return; + if (priv->closing) return; tabs = ephy_window_get_tabs (window); for (l = tabs; l != NULL; l = l->next) @@ -1549,14 +1574,7 @@ sync_tab_visibility (EphyTab *tab, GParamSpec *pspec, EphyWindow *window) } g_list_free (tabs); - if (visible) - { - gtk_widget_show (GTK_WIDGET(window)); - } - else - { - gtk_widget_hide (GTK_WIDGET (window)); - } + g_object_set (window, "visible", visible, NULL); } static void @@ -1753,8 +1771,11 @@ update_popups_tooltips (EphyWindow *window, EphyEmbedEvent *event) } static void -show_embed_popup (EphyWindow *window, EphyTab *tab, EphyEmbedEvent *event) +show_embed_popup (EphyWindow *window, + EphyTab *tab, + EphyEmbedEvent *event) { + EphyWindowPrivate *priv = window->priv; GtkActionGroup *action_group; GtkAction *action; EphyEmbedEventContext context; @@ -1765,7 +1786,7 @@ show_embed_popup (EphyWindow *window, EphyTab *tab, EphyEmbedEvent *event) guint button; /* Do not show the menu in print preview mode */ - if (window->priv->ppv_mode) + if (priv->ppv_mode) { return; } @@ -1824,7 +1845,7 @@ show_embed_popup (EphyWindow *window, EphyTab *tab, EphyEmbedEvent *event) update_popups_tooltips (window, event); - widget = gtk_ui_manager_get_widget (window->priv->manager, popup); + widget = gtk_ui_manager_get_widget (priv->manager, popup); g_return_if_fail (widget != NULL); action_group = window->priv->popups_action_group; @@ -1834,7 +1855,7 @@ show_embed_popup (EphyWindow *window, EphyTab *tab, EphyEmbedEvent *event) action = gtk_action_group_get_action (action_group, "OpenLinkInNewWindow"); g_object_set (action, "sensitive", can_open_in_new, FALSE); action = gtk_action_group_get_action (action_group, "OpenLinkInNewTab"); - g_object_set (action, "sensitive", can_open_in_new, FALSE); + g_object_set (action, "sensitive", can_open_in_new && !priv->is_popup, FALSE); g_object_set_data_full (G_OBJECT (window), "context_event", g_object_ref (event), @@ -1875,6 +1896,70 @@ tab_context_menu_cb (EphyEmbed *embed, return TRUE; } +static gboolean +let_me_resize_hack (EphyWindow *window) +{ + EphyWindowPrivate *priv = window->priv; + + gtk_window_set_resizable (GTK_WINDOW (window), TRUE); + + priv->idle_resize_handler = 0; + return FALSE; +} + +static void +tab_size_to_cb (EphyEmbed *embed, + int width, + int height, + EphyWindow *window) +{ + EphyWindowPrivate *priv = window->priv; + GtkWidget *widget = GTK_WIDGET (window); + GtkWidget *embed_widget = GTK_WIDGET (embed); + GdkScreen *screen; + EphyTab *tab; + GdkRectangle rect; + int monitor; + int ww, wh, ew, eh, dw, dh; + + LOG ("tab_size_to_cb window %p embed %p width %d height %d", window, embed, width, height); + + tab = ephy_tab_for_embed (embed); + g_return_if_fail (tab != NULL); + + /* FIXME: allow sizing also for non-popup single-tab windows? */ + if (tab != ephy_window_get_active_tab (window) || !priv->is_popup) return; + + /* contrain size so that the window will be fully contained within the screen */ + screen = gtk_widget_get_screen (widget); + monitor = gdk_screen_get_monitor_at_window (screen, widget->window); + gdk_screen_get_monitor_geometry (screen, monitor, &rect); + /* FIXME: get and subtract the panel size */ + + gtk_window_get_size (GTK_WINDOW (window), &ww, &wh); + + ew = embed_widget->allocation.width; + eh = embed_widget->allocation.height; + + /* This should approximate the chrome extent */ + dw = ww - ew; dw = MAX (dw, 0); dw = MIN (dw, rect.width - 1); + dh = wh - eh; dh = MAX (dh, 0); dh = MIN (dh, rect.height - 1); + + width = MIN (rect.width - dw, width); + height = MIN (rect.height - dh, height); + + /* FIXME: move window if this will place it partially outside the screen rect? */ + + gtk_window_set_resizable (GTK_WINDOW (window), FALSE); + ephy_tab_set_size (tab, width, height); + + if (priv->idle_resize_handler == 0) + { + priv->idle_resize_handler = + g_idle_add ((GSourceFunc) let_me_resize_hack, window); + } +} + static void ephy_window_set_active_tab (EphyWindow *window, EphyTab *new_tab) { @@ -1890,47 +1975,48 @@ ephy_window_set_active_tab (EphyWindow *window, EphyTab *new_tab) if (old_tab != NULL) { - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_address), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_document_type), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_icon), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_load_progress), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_load_status), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_message), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_navigation), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_security), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_popup_windows), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_popups_allowed), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_title), window); - g_signal_handlers_disconnect_by_func (G_OBJECT (old_tab), + g_signal_handlers_disconnect_by_func (old_tab, G_CALLBACK (sync_tab_zoom), window); embed = ephy_tab_get_embed (old_tab); - g_signal_handlers_disconnect_by_func (G_OBJECT (embed), - G_CALLBACK (tab_context_menu_cb), - window); + g_signal_handlers_disconnect_by_func + (embed, G_CALLBACK (tab_context_menu_cb), window); + g_signal_handlers_disconnect_by_func + (embed, G_CALLBACK (tab_size_to_cb), window); } window->priv->active_tab = new_tab; @@ -1950,59 +2036,50 @@ ephy_window_set_active_tab (EphyWindow *window, EphyTab *new_tab) sync_tab_title (new_tab, NULL, window); sync_tab_zoom (new_tab, NULL, window); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::address", + g_signal_connect_object (new_tab, "notify::address", G_CALLBACK (sync_tab_address), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::document-type", + g_signal_connect_object (new_tab, "notify::document-type", G_CALLBACK (sync_tab_document_type), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::icon", + g_signal_connect_object (new_tab, "notify::icon", G_CALLBACK (sync_tab_icon), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::load-progress", + g_signal_connect_object (new_tab, "notify::load-progress", G_CALLBACK (sync_tab_load_progress), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::load-status", + g_signal_connect_object (new_tab, "notify::load-status", G_CALLBACK (sync_tab_load_status), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::message", + g_signal_connect_object (new_tab, "notify::message", G_CALLBACK (sync_tab_message), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::navigation", + g_signal_connect_object (new_tab, "notify::navigation", G_CALLBACK (sync_tab_navigation), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::security-level", + g_signal_connect_object (new_tab, "notify::security-level", G_CALLBACK (sync_tab_security), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::hidden-popup-count", + g_signal_connect_object (new_tab, "notify::hidden-popup-count", G_CALLBACK (sync_tab_popup_windows), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::popups-allowed", + g_signal_connect_object (new_tab, "notify::popups-allowed", G_CALLBACK (sync_tab_popups_allowed), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::title", + g_signal_connect_object (new_tab, "notify::title", G_CALLBACK (sync_tab_title), window, 0); - g_signal_connect_object (G_OBJECT (new_tab), - "notify::zoom", + g_signal_connect_object (new_tab, "notify::zoom", G_CALLBACK (sync_tab_zoom), window, 0); embed = ephy_tab_get_embed (new_tab); - g_signal_connect_object (embed, "ge_context_menu", + g_signal_connect_object (embed, "ge-context-menu", G_CALLBACK (tab_context_menu_cb), window, G_CONNECT_AFTER); + g_signal_connect_object (embed, "size-to", + G_CALLBACK (tab_size_to_cb), + window, 0); g_object_notify (G_OBJECT (window), "active-tab"); } @@ -2308,10 +2385,21 @@ ephy_window_set_chrome (EphyWindow *window, EphyEmbedChrome mask) window->priv->chrome = chrome_mask; - sync_chromes_visibility (window); update_chromes_actions (window); } +static void +ephy_window_set_is_popup (EphyWindow *window, + gboolean is_popup) +{ + EphyWindowPrivate *priv = window->priv; + + priv->is_popup = is_popup; + ephy_notebook_set_dnd_enabled (EPHY_NOTEBOOK (priv->notebook), !is_popup); + + g_object_notify (G_OBJECT (window), "is-popup"); +} + static void ephy_window_dispose (GObject *object) { @@ -2353,6 +2441,12 @@ ephy_window_dispose (GObject *object) eel_gconf_notification_remove (priv->browse_with_caret_notifier_id); eel_gconf_notification_remove (priv->allow_popups_notifier_id); + if (priv->idle_resize_handler != 0) + { + g_source_remove (priv->idle_resize_handler); + priv->idle_resize_handler = 0; + } + if (priv->find_dialog) { g_object_unref (G_OBJECT (priv->find_dialog)); @@ -2408,6 +2502,9 @@ ephy_window_set_property (GObject *object, case PROP_PPV_MODE: ephy_window_set_print_preview (window, g_value_get_boolean (value)); break; + case PROP_SINGLE_TAB_MODE: + ephy_window_set_is_popup (window, g_value_get_boolean (value)); + break; } } @@ -2430,6 +2527,9 @@ ephy_window_get_property (GObject *object, case PROP_PPV_MODE: g_value_set_boolean (value, window->priv->ppv_mode); break; + case PROP_SINGLE_TAB_MODE: + g_value_set_boolean (value, window->priv->is_popup); + break; } } @@ -2477,6 +2577,7 @@ ephy_window_class_init (EphyWindowClass *klass) parent_class = g_type_class_peek_parent (klass); + object_class->constructor = ephy_window_constructor; object_class->dispose = ephy_window_dispose; object_class->finalize = ephy_window_finalize; object_class->get_property = ephy_window_get_property; @@ -2513,6 +2614,15 @@ ephy_window_class_init (EphyWindowClass *klass) FALSE, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_SINGLE_TAB_MODE, + g_param_spec_boolean ("is-popup", + "Single Tab Mode", + "Whether the window is in single tab mode", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_type_class_add_private (object_class, sizeof (EphyWindowPrivate)); } @@ -2737,8 +2847,6 @@ ephy_window_init (EphyWindow *window) GTK_WIDGET (window->priv->toolbar), FALSE, FALSE, 0); - update_actions_sensitivity (window); - /* Once the window is sufficiently created let the extensions attach to it */ manager = EPHY_EXTENSION (ephy_shell_get_extensions_manager (ephy_shell)); ephy_extension_attach_window (manager, window); @@ -2819,6 +2927,25 @@ ephy_window_init (EphyWindow *window) init_menu_updaters (window); } +static GObject * +ephy_window_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + EphyWindow *window; + + object = parent_class->constructor (type, n_construct_properties, + construct_params); + + window = EPHY_WINDOW (object); + + update_actions_sensitivity (window); + sync_chromes_visibility (window); + + return object; +} + static void ephy_window_finalize (GObject *object) { @@ -2846,16 +2973,19 @@ ephy_window_new (void) /** * ephy_window_new_with_chrome: * @chrome: an #EphyEmbedChrome + * @is_popup: whether the new window is a popup window * * Identical to ephy_window_new(), but allows you to specify a chrome. * * Return value: a new #EphyWindow **/ EphyWindow * -ephy_window_new_with_chrome (EphyEmbedChrome chrome) +ephy_window_new_with_chrome (EphyEmbedChrome chrome, + gboolean is_popup) { return EPHY_WINDOW (g_object_new (EPHY_TYPE_WINDOW, "chrome", chrome, + "is-popup", is_popup, NULL)); } @@ -2878,7 +3008,6 @@ ephy_window_set_print_preview (EphyWindow *window, gboolean enabled) window->priv->ppv_mode = enabled; sync_chromes_visibility (window); - ephy_notebook_set_show_tabs (EPHY_NOTEBOOK (window->priv->notebook), !enabled); if (enabled) { @@ -2998,6 +3127,8 @@ ephy_window_add_tab (EphyWindow *window, g_return_if_fail (EPHY_IS_WINDOW (window)); g_return_if_fail (EPHY_IS_TAB (tab)); + g_return_if_fail (!window->priv->is_popup || + gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) < 1); widget = GTK_WIDGET(ephy_tab_get_embed (tab)); @@ -3111,8 +3242,9 @@ static void ephy_window_show (GtkWidget *widget) { EphyWindow *window = EPHY_WINDOW(widget); + EphyWindowPrivate *priv = window->priv; - if (!window->priv->has_size) + if (!priv->has_size) { EphyTab *tab; int width, height; @@ -3127,7 +3259,7 @@ ephy_window_show (GtkWidget *widget) TRUE, EPHY_STATE_WINDOW_SAVE_SIZE); } - window->priv->has_size = TRUE; + priv->has_size = TRUE; } GTK_WIDGET_CLASS (parent_class)->show (widget); @@ -3369,3 +3501,19 @@ ephy_window_view_popup_windows_cb (GtkAction *action, g_object_set (G_OBJECT (tab), "popups-allowed", allow, NULL); } + +/** + * ephy_window_get_is_popup: + * @window: an #EphyWindow + * + * Returns whether this window is a popup window. + * + * Return value: %TRUE if it is a popup window + **/ +gboolean +ephy_window_get_is_popup (EphyWindow *window) +{ + g_return_val_if_fail (EPHY_IS_WINDOW (window), FALSE); + + return window->priv->is_popup; +} diff --git a/src/ephy-window.h b/src/ephy-window.h index cee6a297a..df0486c8f 100644 --- a/src/ephy-window.h +++ b/src/ephy-window.h @@ -58,7 +58,8 @@ GType ephy_window_get_type (void); EphyWindow *ephy_window_new (void); -EphyWindow *ephy_window_new_with_chrome (EphyEmbedChrome chrome); +EphyWindow *ephy_window_new_with_chrome (EphyEmbedChrome chrome, + gboolean is_popup); void ephy_window_set_print_preview (EphyWindow *window, gboolean enabled); @@ -100,6 +101,8 @@ GList *ephy_window_get_tabs (EphyWindow *window); void ephy_window_find (EphyWindow *window); +gboolean ephy_window_get_is_popup (EphyWindow *window); + G_END_DECLS #endif -- cgit v1.2.3