diff options
author | Stevan Andjelkovic <stevan@student.chalmers.se> | 2011-07-12 20:39:17 +0000 |
---|---|---|
committer | Stevan Andjelkovic <stevan@student.chalmers.se> | 2011-07-12 20:39:17 +0000 |
commit | 9f7f01195ffbebc2044bc9a5f35ae9ad600504e3 (patch) | |
tree | 11ea749e297fe039cdca228e256687e26dccc349 | |
parent | a2e413805d0325ea6564261d1996cba60de64432 (diff) | |
download | xombrero-9f7f01195ffbebc2044bc9a5f35ae9ad600504e3.tar.gz |
Added :buffers command, which displays open tabs and enables selection via
the keyboard. ok marco@
-rw-r--r-- | xxxterm.1 | 11 | ||||
-rw-r--r-- | xxxterm.c | 242 |
2 files changed, 188 insertions, 65 deletions
diff --git a/xxxterm.1 b/xxxterm.1 index bc62aa1..e0677b8 100644 --- a/xxxterm.1 +++ b/xxxterm.1 @@ -380,6 +380,9 @@ The commands and their descriptions are listed below. .Bl -tag -width Ds -offset indent .It Cm about , version Show the "About" page. +.It Cm buffers , ls , tabs +Displays the currently open tabs and lets the user switch tab by typing +the tab number or using the mouse. .It Cm ca Display CA certificates. .It Cm cert , cert show @@ -501,7 +504,7 @@ Hide status bar. Show status bar. .It Cm tabclose , tabc Close current tab. -.It Cm tabhide , tabh +.It Cm tabhide Hide tabs. .It Cm tabnew , tabedit , tabe URL Create new tab and optionally open provided URL. @@ -509,7 +512,7 @@ Create new tab and optionally open provided URL. Go to the next tab. .It Cm tabprevious , tabp Go to the previous tab. -.It Cm tabshow , tabs +.It Cm tabshow Show tabs. .It Cm toplevel , toplevel toggle Toggle the top level domain name cookie and JS session whitelist. @@ -764,8 +767,8 @@ Only a user with identical UID and GID can use this option. .It Cm enable_localstorage Enable html5 Local Storage. .It Cm enable_spell_checking -Enables spell checking. Preferred languages can be set using -.Cm spell_check_languages +Enables spell checking. Preferred languages can be set using +.Cm spell_check_languages option. .It Cm fancy_bar Enables a backward, forward, and stop button to the toolbar. diff --git a/xxxterm.c b/xxxterm.c index b5a2a15..2423b69 100644 --- a/xxxterm.c +++ b/xxxterm.c @@ -177,6 +177,7 @@ struct tab { GtkWidget *browser_win; GtkWidget *statusbar; GtkWidget *cmd; + GtkWidget *buffers; GtkWidget *oops; GtkWidget *backward; GtkWidget *forward; @@ -770,6 +771,7 @@ int icon_size_map(int); GtkListStore *completion_model; void completion_add(struct tab *); void completion_add_uri(const gchar *); +GtkListStore *buffers_store; void xxx_dir(char *); void @@ -920,22 +922,99 @@ set_status(struct tab *t, gchar *s, int status) } void -hide_oops(struct tab *t) +hide_cmd(struct tab *t) +{ + gtk_widget_hide(t->cmd); +} + +void +show_cmd(struct tab *t) { gtk_widget_hide(t->oops); + gtk_widget_show(t->cmd); } void -hide_cmd(struct tab *t) +hide_buffers(struct tab *t) { - gtk_widget_hide(t->cmd); + gtk_widget_hide(t->buffers); + gtk_list_store_clear(buffers_store); +} + +enum { + COL_ID = 0, + COL_TITLE, + NUM_COLS +}; + +int +sort_tabs_by_page_num(struct tab ***stabs) +{ + int num_tabs = 0; + struct tab *t; + + TAILQ_FOREACH(t, &tabs, entry) + num_tabs++; + + *stabs = g_malloc0(num_tabs * sizeof(struct tab *)); + + TAILQ_FOREACH(t, &tabs, entry) + (*stabs)[gtk_notebook_page_num(notebook, t->vbox)] = t; + + return (num_tabs); } void -show_cmd(struct tab *t) +buffers_make_list(void) +{ + int i, num_tabs; + GtkTreeIter iter; + struct tab **stabs = NULL; + + num_tabs = sort_tabs_by_page_num(&stabs); + + for (i = 0; i < num_tabs; i++) + if (stabs[i]) { + gtk_list_store_append(buffers_store, &iter); + gtk_list_store_set(buffers_store, &iter, + COL_ID, i + 1, /* Enumerate the tabs starting from 1 + * rather than 0. */ + COL_TITLE, webkit_web_view_get_title(stabs[i]->wv), + -1); + } + + g_free(stabs); +} + +void +show_buffers(struct tab *t) +{ + buffers_make_list(); + gtk_widget_show(t->buffers); + gtk_widget_grab_focus(GTK_WIDGET(t->buffers)); +} + +void +toggle_buffers(struct tab *t) +{ + if (gtk_widget_get_visible(t->buffers)) + hide_buffers(t); + else + show_buffers(t); +} + +int +buffers(struct tab *t, struct karg *args) +{ + show_buffers(t); + + return (0); +} + +void +hide_oops(struct tab *t) { gtk_widget_hide(t->oops); - gtk_widget_show(t->cmd); } void @@ -2190,10 +2269,8 @@ save_tabs(struct tab *t, struct karg *a) { char file[PATH_MAX]; FILE *f; - struct tab *ti; - const gchar *uri; - int len = 0, i; - const gchar **arr = NULL; + int num_tabs = 0, i; + struct tab **stabs = NULL; if (a == NULL) return (1); @@ -2211,22 +2288,15 @@ save_tabs(struct tab *t, struct karg *a) /* save session name */ fprintf(f, "%s%s\n", XT_SAVE_SESSION_ID, named_session); - /* save tabs, in the order they are arranged in the notebook */ - TAILQ_FOREACH(ti, &tabs, entry) - len++; - - arr = g_malloc0(len * sizeof(gchar *)); + /* Save tabs, in the order they are arranged in the notebook. */ + num_tabs = sort_tabs_by_page_num(&stabs); - TAILQ_FOREACH(ti, &tabs, entry) { - if ((uri = get_uri(ti->wv)) != NULL) - arr[gtk_notebook_page_num(notebook, ti->vbox)] = uri; - } + for (i = 0; i < num_tabs; i++) + if (stabs[i] && get_uri(stabs[i]->wv) != NULL) + fprintf(f, "%s\n", get_uri(stabs[i]->wv)); - for (i = 0; i < len; i++) - if (arr[i]) - fprintf(f, "%s\n", arr[i]); + g_free(stabs); - g_free(arr); /* try and make sure this gets to disk NOW. XXX Backup first? */ if (fflush(f) != 0 || fsync(fileno(f)) != 0) { show_oops(t, "May not have managed to save session: %s", @@ -5087,6 +5157,9 @@ struct cmd { { "tabrewind", 0, movetab, XT_TAB_FIRST, 0 }, { "tabshow", 0, tabaction, XT_TAB_SHOW, 0 }, { "tabundoclose", 0, tabaction, XT_TAB_UNDO_CLOSE, 0 }, + { "buffers", 0, buffers, 0, 0 }, + { "ls", 0, buffers, 0, 0 }, + { "tabs", 0, buffers, 0, 0 }, /* command aliases (handy when -S flag is used) */ { "promptopen", 0, command, XT_CMD_OPEN, 0 }, @@ -5976,7 +6049,7 @@ notify_title_cb(WebKitWebView* wview, GParamSpec* pspec, struct tab *t) const gchar *set = NULL, *title = NULL; title = webkit_web_view_get_title(wview); - set = title ? title: get_uri(wview); + set = title ? title : get_uri(wview); if (set) { gtk_label_set_text(GTK_LABEL(t->label), set); gtk_window_set_title(GTK_WINDOW(main_window), set); @@ -6498,7 +6571,7 @@ anum: if (CLEAN(e->state) == 0 && isdigit(s[0])) { cmd_prefix = 10 * cmd_prefix + atoi(s); } - } + } return (handle_keypress(t, e, 0)); } @@ -6508,6 +6581,14 @@ wv_keypress_cb(GtkEntry *w, GdkEventKey *e, struct tab *t) { hide_oops(t); + /* Hide buffers, if they are visible, with escape. */ + if (gtk_widget_get_visible(GTK_WIDGET(t->buffers)) && + CLEAN(e->state) == 0 && e->keyval == GDK_Escape) { + gtk_widget_grab_focus(GTK_WIDGET(t->wv)); + hide_buffers(t); + return (XT_CB_HANDLED); + } + return (XT_CB_PASSTHROUGH); } @@ -7208,6 +7289,48 @@ create_toolbar(struct tab *t) return (toolbar); } +GtkWidget * +create_buffers(struct tab *t) +{ + GtkCellRenderer *renderer; + GtkWidget *view; + + view = gtk_tree_view_new(); + + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes + (GTK_TREE_VIEW(view), -1, "Id", renderer, "text", COL_ID, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes + (GTK_TREE_VIEW(view), -1, "Title", renderer, "text", COL_TITLE, NULL); + + gtk_tree_view_set_model + (GTK_TREE_VIEW(view), GTK_TREE_MODEL(buffers_store)); + + return view; +} + +void +row_activated_cb(GtkTreeView *view, GtkTreePath *path, + GtkTreeViewColumn *col, struct tab *t) +{ + GtkTreeIter iter; + guint id; + + gtk_widget_grab_focus(GTK_WIDGET(t->wv)); + + if (gtk_tree_model_get_iter(GTK_TREE_MODEL(buffers_store), &iter, path)) { + gtk_tree_model_get + (GTK_TREE_MODEL(buffers_store), &iter, COL_ID, &id, -1); + gtk_notebook_set_current_page(notebook, id - 1); + } + + hide_buffers(t); +} + void recalc_tabs(void) { @@ -7291,9 +7414,11 @@ delete_tab(struct tab *t) TAILQ_REMOVE(&tabs, t, entry); - /* halt all webkit activity */ + /* Halt all webkit activity. */ abort_favicon_download(t); webkit_web_view_stop_loading(t->wv); + + /* Save the tab, so we can undo the close. */ undo_close_tab_save(t); if (browser_mode == XT_BM_KIOSK) { @@ -7447,6 +7572,10 @@ create_new_tab(char *title, struct undo *u, int focus, int position) gtk_widget_modify_font(GTK_WIDGET(t->statusbar), statusbar_font); gtk_box_pack_end(GTK_BOX(t->vbox), t->statusbar, FALSE, FALSE, 0); + /* buffer list */ + t->buffers = create_buffers(t); + gtk_box_pack_end(GTK_BOX(t->vbox), t->buffers, FALSE, FALSE, 0); + /* xtp meaning is normal by default */ t->xtp_meaning = XT_XTP_TAB_MEANING_NORMAL; @@ -7492,6 +7621,11 @@ create_new_tab(char *title, struct undo *u, int focus, int position) "signal::button_press_event", G_CALLBACK(wv_button_cb), t, (char *)NULL); + g_signal_connect(t->buffers, + "row-activated", G_CALLBACK(row_activated_cb), t); + g_object_connect(G_OBJECT(t->buffers), + "signal::key-press-event", G_CALLBACK(wv_keypress_cb), t, NULL); + g_object_connect(G_OBJECT(t->wv), "signal::key-press-event", G_CALLBACK(wv_keypress_cb), t, "signal-after::key-press-event", G_CALLBACK(wv_keypress_after_cb), t, @@ -7524,6 +7658,7 @@ create_new_tab(char *title, struct undo *u, int focus, int position) /* hide stuff */ hide_cmd(t); hide_oops(t); + hide_buffers(t); url_set_visibility(); statusbar_set_visibility(); @@ -7605,52 +7740,33 @@ notebook_pagereordered_cb(GtkNotebook *nb, GtkWidget *nbp, guint pn, recalc_tabs(); } -void -menuitem_response(struct tab *t) +struct tab * +get_current_tab(void) { - gtk_notebook_set_current_page(notebook, t->tab_id); + struct tab *t; + + TAILQ_FOREACH(t, &tabs, entry) { + if (t->tab_id == gtk_notebook_get_current_page(notebook)) + return (t); + } + + warnx("%s: no current tab", __func__); + + return (NULL); } gboolean arrow_cb(GtkWidget *w, GdkEventButton *event, gpointer user_data) { - GtkWidget *menu, *menu_items; - GdkEventButton *bevent; - const gchar *uri; - struct tab *ti; + struct tab *t; if (event->type == GDK_BUTTON_PRESS) { - bevent = (GdkEventButton *) event; - menu = gtk_menu_new(); - - TAILQ_FOREACH(ti, &tabs, entry) { - if ((uri = get_uri(ti->wv)) == NULL) - /* XXX make sure there is something to print */ - /* XXX add gui pages in here to look purdy */ - uri = "(untitled)"; - menu_items = gtk_menu_item_new_with_label(uri); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_items); - gtk_widget_show(menu_items); - - g_signal_connect_swapped((menu_items), - "activate", G_CALLBACK(menuitem_response), - (gpointer)ti); + if ((t = get_current_tab()) != NULL) { + toggle_buffers(t); + return (TRUE); } - - gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, - bevent->button, bevent->time); - - /* unref object so it'll free itself when popped down */ -#if !GTK_CHECK_VERSION(3, 0, 0) - /* XXX does not need unref with gtk+3? */ - g_object_ref_sink(menu); - g_object_unref(menu); -#endif - - return (TRUE /* eat event */); } - - return (FALSE /* propagate */); + return (FALSE); } int @@ -8515,6 +8631,10 @@ main(int argc, char *argv[]) /* uri completion */ completion_model = gtk_list_store_new(1, G_TYPE_STRING); + /* buffers */ + buffers_store = gtk_list_store_new + (NUM_COLS, G_TYPE_UINT, G_TYPE_STRING); + /* go graphical */ create_canvas(); |