[epiphany] Add pinned tabs
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Add pinned tabs
- Date: Thu, 4 Apr 2019 17:46:18 +0000 (UTC)
commit 4be31e56e0fcecc7e2831fa470128fefa28dcab9
Author: Jan-Michael Brummer <jan brummer tabos org>
Date: Thu Mar 28 18:42:46 2019 +0100
Add pinned tabs
Fixes: https://gitlab.gnome.org/GNOME/epiphany/issues/248
src/ephy-notebook.c | 68 +++++++++++++++++++++++++++++-
src/ephy-notebook.h | 5 +++
src/ephy-session.c | 25 +++++++++--
src/ephy-tab-label.c | 34 +++++++++++++++
src/ephy-tab-label.h | 3 ++
src/ephy-window.c | 19 ++++++++-
src/resources/gtk/notebook-context-menu.ui | 10 +++++
src/window-commands.c | 40 +++++++++++++++++-
src/window-commands.h | 6 +++
9 files changed, 204 insertions(+), 6 deletions(-)
---
diff --git a/src/ephy-notebook.c b/src/ephy-notebook.c
index fa1c0c0fe..78c1c846d 100644
--- a/src/ephy-notebook.c
+++ b/src/ephy-notebook.c
@@ -388,9 +388,10 @@ expand_tabs_changed_cb (GSettings *settings,
tabs = gtk_container_get_children (GTK_CONTAINER (nb));
for (l = tabs; l != NULL; l = l->next) {
+ gboolean pinned = ephy_notebook_tab_is_pinned (nb, l->data);
gtk_container_child_set (GTK_CONTAINER (nb),
l->data,
- "tab-expand", expand,
+ "tab-expand", pinned ? FALSE : expand,
NULL);
}
@@ -465,6 +466,36 @@ show_tabs_changed_cb (GSettings *settings,
update_tabs_visibility (nb, FALSE);
}
+static guint
+get_last_pinned_tab_pos (GtkNotebook *notebook)
+{
+ gint pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
+ gint i;
+ gint found = -1;
+
+ for (i = 0; i < pages; i++) {
+ GtkWidget *child = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), i);
+
+ if (ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), EPHY_EMBED (child)))
+ found = i;
+ }
+
+ return found;
+}
+
+static void
+page_reordered_cb (GtkNotebook *notebook,
+ GtkWidget *child,
+ guint page_num,
+ gpointer user_data)
+{
+ guint last_pinned_tab_pos = get_last_pinned_tab_pos (notebook);
+
+ /* Ensure that pinned tabs will always stay at the beginning of tab bar */
+ if (last_pinned_tab_pos != -1 && page_num <= last_pinned_tab_pos)
+ gtk_notebook_reorder_child (notebook, child, last_pinned_tab_pos);
+}
+
static void
ephy_notebook_init (EphyNotebook *notebook)
{
@@ -484,6 +515,8 @@ ephy_notebook_init (EphyNotebook *notebook)
g_signal_connect_after (notebook, "switch-page",
G_CALLBACK (ephy_notebook_switch_page_cb),
NULL);
+ g_signal_connect (notebook, "page-reordered",
+ (GCallback)page_reordered_cb, NULL);
/* Set up drag-and-drop target */
g_signal_connect (notebook, "drag-data-received",
@@ -922,3 +955,36 @@ ephy_notebook_set_adaptive_mode (EphyNotebook *notebook,
notebook->adaptive_mode = adaptive_mode;
update_tabs_visibility (notebook, FALSE);
}
+
+void
+ephy_notebook_tab_set_pinned (EphyNotebook *notebook,
+ GtkWidget *embed,
+ gboolean is_pinned)
+{
+ GtkWidget *tab_label;
+ gboolean expanded;
+
+ if (is_pinned) {
+ gtk_notebook_reorder_child (GTK_NOTEBOOK (notebook), embed, 0);
+ expanded = FALSE;
+ } else {
+ expanded = g_settings_get_boolean (EPHY_SETTINGS_UI, EPHY_PREFS_UI_EXPAND_TABS_BAR);
+ page_reordered_cb (GTK_NOTEBOOK (notebook), embed, 0, NULL);
+ }
+
+ gtk_container_child_set (GTK_CONTAINER (notebook), embed, "tab-expand", expanded, NULL);
+
+ gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (notebook), embed, !is_pinned);
+
+ tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), embed);
+ ephy_tab_label_set_pin (tab_label, is_pinned);
+}
+
+gboolean
+ephy_notebook_tab_is_pinned (EphyNotebook *notebook,
+ EphyEmbed *embed)
+{
+ GtkWidget *tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), GTK_WIDGET (embed));
+
+ return ephy_tab_label_get_pin (tab_label);
+}
diff --git a/src/ephy-notebook.h b/src/ephy-notebook.h
index 39fe6a72d..a54b50f83 100644
--- a/src/ephy-notebook.h
+++ b/src/ephy-notebook.h
@@ -51,4 +51,9 @@ GMenu *ephy_notebook_get_pages_menu (EphyNotebook *notebook);
void ephy_notebook_set_adaptive_mode (EphyNotebook *notebook,
EphyAdaptiveMode adaptive_mode);
+void ephy_notebook_tab_set_pinned (EphyNotebook *notebook,
+ GtkWidget *embed,
+ gboolean is_pinned);
+gboolean ephy_notebook_tab_is_pinned (EphyNotebook *notebook,
+ EphyEmbed *embed);
G_END_DECLS
diff --git a/src/ephy-session.c b/src/ephy-session.c
index ed8fb3502..49212b6b1 100644
--- a/src/ephy-session.c
+++ b/src/ephy-session.c
@@ -545,12 +545,14 @@ typedef struct {
char *title;
gboolean loading;
gboolean crashed;
+ gboolean pinned;
WebKitWebViewSessionState *state;
} SessionTab;
static SessionTab *
session_tab_new (EphyEmbed *embed,
- EphySession *session)
+ EphySession *session,
+ GtkNotebook *notebook)
{
SessionTab *session_tab;
const char *address;
@@ -579,6 +581,7 @@ session_tab_new (EphyEmbed *embed,
session_tab->crashed = (error_page == EPHY_WEB_VIEW_ERROR_PAGE_CRASH ||
error_page == EPHY_WEB_VIEW_ERROR_PROCESS_CRASH);
session_tab->state = webkit_web_view_get_session_state (WEBKIT_WEB_VIEW (web_view));
+ session_tab->pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed);
return session_tab;
}
@@ -620,17 +623,17 @@ session_window_new (EphyWindow *window,
session_window = g_new0 (SessionWindow, 1);
get_window_geometry (GTK_WINDOW (window), &session_window->geometry);
session_window->role = g_strdup (gtk_window_get_role (GTK_WINDOW (window)));
+ notebook = GTK_NOTEBOOK (ephy_window_get_notebook (window));
for (l = tabs; l != NULL; l = l->next) {
SessionTab *tab;
- tab = session_tab_new (EPHY_EMBED (l->data), session);
+ tab = session_tab_new (EPHY_EMBED (l->data), session, notebook);
session_window->tabs = g_list_prepend (session_window->tabs, tab);
}
g_list_free (tabs);
session_window->tabs = g_list_reverse (session_window->tabs);
- notebook = GTK_NOTEBOOK (ephy_window_get_notebook (window));
session_window->active_tab = gtk_notebook_get_current_page (notebook);
return session_window;
@@ -712,6 +715,14 @@ write_tab (xmlTextWriterPtr writer,
return ret;
}
+ if (tab->pinned) {
+ ret = xmlTextWriterWriteAttribute (writer,
+ (const xmlChar *)"pinned",
+ (const xmlChar *)"true");
+ if (ret < 0)
+ return ret;
+ }
+
if (tab->crashed) {
ret = xmlTextWriterWriteAttribute (writer,
(const xmlChar *)"crashed",
@@ -1125,14 +1136,18 @@ session_parse_embed (SessionParserContext *context,
const gchar **names,
const gchar **values)
{
+ GtkWidget *notebook;
const char *url = NULL;
const char *title = NULL;
const char *history = NULL;
gboolean was_loading = FALSE;
gboolean crashed = FALSE;
gboolean is_blank_page = FALSE;
+ gboolean is_pin = FALSE;
guint i;
+ notebook = ephy_window_get_notebook (context->window);
+
for (i = 0; names[i]; i++) {
if (strcmp (names[i], "url") == 0) {
url = values[i];
@@ -1146,6 +1161,8 @@ session_parse_embed (SessionParserContext *context,
crashed = strcmp (values[i], "true") == 0;
} else if (strcmp (names[i], "history") == 0) {
history = values[i];
+ } else if (strcmp (names[i], "pinned") == 0) {
+ is_pin = strcmp (values[i], "true") == 0;
}
}
@@ -1179,6 +1196,8 @@ session_parse_embed (SessionParserContext *context,
context->window, NULL, flags,
0);
+ ephy_notebook_tab_set_pinned (EPHY_NOTEBOOK (notebook), GTK_WIDGET (embed), is_pin);
+
web_view = ephy_embed_get_web_view (embed);
if (history) {
guchar *data;
diff --git a/src/ephy-tab-label.c b/src/ephy-tab-label.c
index eff6b01d9..bbc11f429 100644
--- a/src/ephy-tab-label.c
+++ b/src/ephy-tab-label.c
@@ -33,6 +33,8 @@ struct _EphyTabLabel {
GtkWidget *label;
GtkWidget *close_button;
GtkWidget *audio_button;
+
+ gboolean pinned;
};
enum {
@@ -144,6 +146,11 @@ style_updated_cb (GtkWidget *widget,
EphyTabLabel *self = EPHY_TAB_LABEL (widget);
int char_width, h, w;
+ if (self->pinned) {
+ gtk_widget_set_size_request (widget, -1, -1);
+ return;
+ }
+
context = gtk_widget_get_pango_context (widget);
style = gtk_widget_get_style_context (widget);
gtk_style_context_get (style, gtk_style_context_get_state (style), "font", &font_desc, NULL);
@@ -230,3 +237,30 @@ ephy_tab_label_get_text (GtkWidget *widget)
return gtk_label_get_text (GTK_LABEL (self->label));
}
+
+static void
+update_label (EphyTabLabel *self)
+{
+ gtk_widget_set_visible (self->close_button, !self->pinned);
+ gtk_widget_set_visible (self->label, !self->pinned);
+ gtk_widget_set_halign (GTK_WIDGET (self), self->pinned ? GTK_ALIGN_CENTER : GTK_ALIGN_FILL);
+ g_signal_emit_by_name (self, "style-updated", G_TYPE_NONE);
+}
+
+void
+ephy_tab_label_set_pin (GtkWidget *widget,
+ gboolean pinned)
+{
+ EphyTabLabel *self = EPHY_TAB_LABEL (widget);
+
+ self->pinned = pinned;
+ update_label (self);
+}
+
+gboolean
+ephy_tab_label_get_pin (GtkWidget *widget)
+{
+ EphyTabLabel *self = EPHY_TAB_LABEL (widget);
+
+ return self->pinned;
+}
diff --git a/src/ephy-tab-label.h b/src/ephy-tab-label.h
index 86cb7f63b..8e299050a 100644
--- a/src/ephy-tab-label.h
+++ b/src/ephy-tab-label.h
@@ -32,5 +32,8 @@ G_DECLARE_FINAL_TYPE (EphyTabLabel, ephy_tab_label, EPHY, TAB_LABEL, GtkBox);
GtkWidget *ephy_tab_label_new (void);
const gchar *ephy_tab_label_get_text (GtkWidget *self);
+void ephy_tab_label_set_pin (GtkWidget *self,
+ gboolean pin);
+gboolean ephy_tab_label_get_pin (GtkWidget *self);
G_END_DECLS
diff --git a/src/ephy-window.c b/src/ephy-window.c
index ca161a4ff..b694fc382 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -128,7 +128,8 @@ const struct {
{ "tab.move-left", { "<shift><Primary>Page_Up", "<shift><Primary>Page_Up", NULL } },
{ "tab.move-right", { "<shift><Primary>Page_Down", "<shift><Primary>Page_Down", NULL } },
{ "tab.duplicate", { NULL } },
- { "tab.close", { "<Primary>W", NULL } }
+ { "tab.close", { "<Primary>W", NULL } },
+ { "tab.pin", { NULL } }
}, accels_navigation_ltr [] = {
{ "toolbar.navigation-back", { "<alt>Left", "<alt>KP_Left", "<alt>KP_4", "Back", NULL } },
{ "toolbar.navigation-forward", { "<alt>Right", "<alt>KP_Right", "<alt>KP_6", "Forward", NULL } }
@@ -853,6 +854,8 @@ static const GActionEntry tab_entries [] = {
{ "reload", window_cmd_tabs_reload },
{ "reopen", window_cmd_tabs_reopen_closed_tab },
{ "reload-all", window_cmd_tabs_reload_all_tabs },
+ { "pin", window_cmd_tabs_pin },
+ { "unpin", window_cmd_tabs_unpin },
};
static const GActionEntry toolbar_entries [] = {
@@ -2518,6 +2521,7 @@ show_notebook_popup_menu (GtkNotebook *notebook,
if (event != NULL) {
int n_pages;
int page_num;
+ gboolean pinned;
tab = GTK_WIDGET (window->active_embed);
n_pages = gtk_notebook_get_n_pages (notebook);
@@ -2540,6 +2544,19 @@ show_notebook_popup_menu (GtkNotebook *notebook,
"reload-all");
g_simple_action_set_enabled (G_SIMPLE_ACTION (action), n_pages > 1);
+ pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), EPHY_EMBED (tab));
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "pin");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !pinned);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "unpin");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), pinned);
+
+ action = g_action_map_lookup_action (G_ACTION_MAP (action_group),
+ "close-tab");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), !pinned);
+
gtk_menu_popup_at_pointer (GTK_MENU (menu), (GdkEvent *)event);
} else {
tab = GTK_WIDGET (window->active_embed);
diff --git a/src/resources/gtk/notebook-context-menu.ui b/src/resources/gtk/notebook-context-menu.ui
index f01310cd5..050374bfa 100644
--- a/src/resources/gtk/notebook-context-menu.ui
+++ b/src/resources/gtk/notebook-context-menu.ui
@@ -16,6 +16,16 @@
<attribute name="action">tab.duplicate</attribute>
</item>
</section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">P_in Tab</attribute>
+ <attribute name="action">tab.pin</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Unpi_n Tab</attribute>
+ <attribute name="action">tab.unpin</attribute>
+ </item>
+ </section>
<section>
<item>
<attribute name="label" translatable="yes">Reo_pen Closed Tab</attribute>
diff --git a/src/window-commands.c b/src/window-commands.c
index bc5bb99fd..95bda9585 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -2474,6 +2474,7 @@ window_cmd_tabs_close (GSimpleAction *action,
EphyWindow *window = user_data;
GtkWidget *notebook;
EphyEmbed *embed;
+ gboolean pinned;
notebook = ephy_window_get_notebook (window);
@@ -2486,7 +2487,10 @@ window_cmd_tabs_close (GSimpleAction *action,
embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
g_assert (embed != NULL);
- g_signal_emit_by_name (notebook, "tab-close-request", embed);
+ pinned = ephy_notebook_tab_is_pinned (EPHY_NOTEBOOK (notebook), embed);
+
+ if (!pinned)
+ g_signal_emit_by_name (notebook, "tab-close-request", embed);
}
void
@@ -2753,3 +2757,37 @@ window_cmd_new_tab_from_clipboard (GSimpleAction *action,
(GtkClipboardTextReceivedFunc)clipboard_text_received_cb,
g_object_ref (ephy_window));
}
+
+void
+window_cmd_tabs_pin (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ EphyWindow *window = EPHY_WINDOW (user_data);
+ EphyEmbed *embed;
+ EphyNotebook *notebook;
+
+ embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ g_assert (embed != NULL);
+
+ notebook = EPHY_NOTEBOOK (ephy_window_get_notebook (window));
+
+ ephy_notebook_tab_set_pinned (notebook, GTK_WIDGET (embed), TRUE);
+}
+
+void
+window_cmd_tabs_unpin (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ EphyWindow *window = EPHY_WINDOW (user_data);
+ EphyEmbed *embed;
+ EphyNotebook *notebook;
+
+ embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+ g_assert (embed != NULL);
+
+ notebook = EPHY_NOTEBOOK (ephy_window_get_notebook (window));
+
+ ephy_notebook_tab_set_pinned (notebook, GTK_WIDGET (embed), FALSE);
+}
diff --git a/src/window-commands.h b/src/window-commands.h
index b60495ab8..3f2f6cbff 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -221,5 +221,11 @@ void window_cmd_homepage_new_tab (GSimpleAction *action,
void window_cmd_new_tab_from_clipboard (GSimpleAction *action,
GVariant *parameter,
gpointer user_data);
+void window_cmd_tabs_pin (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data);
+void window_cmd_tabs_unpin (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]