// Simple browser my attempt at an even less-sucking browser than surf. //original code is from alot of places, gtkforums.com, gtkwebkit.org provided //alot of nice API examples :), and of course, surf (though i was careful not to steal any code because of the damned MIT/X license) //uzbl also helped inspire me. along with a previous surf fork named inferno. #include #include #include typedef struct tab { GtkWidget *scroll; GtkWidget *label; gchar *main_title; gint load_progress; guint status_context_id; WebKitWebView *view; WebKitWebSettings *settings; } tab; static struct { GtkWidget *win; GtkWidget *bar; GtkWidget *search; GtkWidget *vbox; GtkWidget *notebook; GtkWidget *status; } w; #define get_tab(x, page_idx ) (struct tab*)g_object_get_qdata(G_OBJECT( gtk_notebook_get_nth_page( (GtkNotebook*)w.notebook, page_idx ) ), term_data_id); static GQuark term_data_id = 0; static void activate_uri_entry_cb(GtkWidget* entry, gpointer data); static void link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data); static void title_change_cb(WebKitWebView *v, WebKitWebFrame *f, const char *title, tab *t); static void progress_change_cb (WebKitWebView* page, gint progress, gpointer data); static void load_commit_cb (WebKitWebView* page, WebKitWebFrame* frame, gpointer data); static void destroy_cb (GtkWidget* widget, gpointer data); static void go_cb(gboolean b); static void new_tab(); static void close_tab(); static void config(); gboolean key_press_cb(GtkWidget *widget, GdkEventKey *event); static void activate_uri_entry_cb (GtkWidget* entry, gpointer data) { const gchar* uri = gtk_entry_get_text (GTK_ENTRY (w.bar)); struct tab *t = get_tab(NULL, gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook))); webkit_web_view_open (t->view, uri); gtk_widget_grab_focus(GTK_WIDGET(t->view)); } static void close_tab() { struct tab *t = get_tab(NULL, gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook))); gtk_notebook_remove_page(GTK_NOTEBOOK(w.notebook), gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook))); g_free(t); if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(w.notebook)) == 1) { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(w.notebook), FALSE); gtk_widget_grab_focus(gtk_notebook_get_nth_page(GTK_NOTEBOOK(w.notebook), gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook)))); } if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(w.notebook)) == 0) { gtk_main_quit(); } } static void link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) { /* gchar *linkhover; if (link) update_title(NULL, link); */ } static void title_change_cb(WebKitWebView *v, WebKitWebFrame *f, const char *title, tab *t) { gtk_window_set_title(GTK_WINDOW(w.win), title); gtk_label_set_label(GTK_LABEL(t->label), title); } static void progress_change_cb (WebKitWebView* p, gint progress, gpointer data) { /*nothing needed yet*/ } static void load_commit_cb (WebKitWebView* p, WebKitWebFrame* frame, gpointer data) { const gchar* uri = webkit_web_frame_get_uri(frame); //gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook)); gtk_entry_set_text (GTK_ENTRY (w.bar), uri); } static void destroy_cb (GtkWidget* widget, gpointer data) { gtk_main_quit (); } static void go_cb (gboolean b) { struct tab *t = get_tab(NULL, gtk_notebook_get_current_page(GTK_NOTEBOOK(w.notebook))); if (b) { webkit_web_view_go_forward(t->view); } else { webkit_web_view_go_back(t->view); } } static void new_tab() { /*seperate function so it will be easier to setup the webkit crap*/ tab *t; t = g_new0(tab, 1); t->scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(t->scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); t->view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); gtk_container_add(GTK_CONTAINER(t->scroll), GTK_WIDGET(t->view)); t->label = gtk_label_new("new tab"); int index = gtk_notebook_append_page(GTK_NOTEBOOK(w.notebook), t->scroll, t->label); gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(w.notebook), t->scroll, TRUE); if ( gtk_notebook_get_n_pages(GTK_NOTEBOOK(w.notebook)) == 1) { } if (index == 0) { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(w.notebook), FALSE); } else { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(w.notebook), TRUE); } /*callbacks*/ g_signal_connect (G_OBJECT (t->view), "title-changed", G_CALLBACK (title_change_cb), t); g_signal_connect (G_OBJECT (t->view), "load-progress-changed", G_CALLBACK (progress_change_cb), t->view); g_signal_connect (G_OBJECT (t->view), "load-committed", G_CALLBACK (load_commit_cb), t->view); g_signal_connect (G_OBJECT (t->view), "hovering-over-link", G_CALLBACK (link_hover_cb), t->view); /*settings*/ g_object_set_qdata_full(G_OBJECT(gtk_notebook_get_nth_page((GtkNotebook*)w.notebook, index)), term_data_id, t, NULL); t->settings = webkit_web_settings_new (); g_object_set (G_OBJECT(t->settings), "enable-java-applet", FALSE, NULL); g_object_set (G_OBJECT(t->settings), "print-backgrounds", FALSE, NULL); webkit_web_view_set_settings (WEBKIT_WEB_VIEW(t->view), t->settings); gtk_widget_show_all(w.win); gtk_notebook_set_current_page(GTK_NOTEBOOK(w.notebook), index); } static void config() { term_data_id = g_quark_from_static_string("sb"); /*sb is orginized with a vbox. much the simplest way to orginize things*/ w.vbox = gtk_vbox_new(FALSE, 0); w.notebook = gtk_notebook_new(); w.bar = gtk_entry_new (); gtk_entry_set_has_frame(GTK_ENTRY(w.bar), FALSE); gtk_notebook_set_scrollable(GTK_NOTEBOOK(w.notebook), TRUE); g_signal_connect (G_OBJECT (w.bar), "activate", G_CALLBACK (activate_uri_entry_cb), NULL); gtk_box_pack_start(GTK_BOX (w.vbox), w.bar, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(w.vbox), w.notebook, TRUE, TRUE, 0); /* status bar*/ //w.status = gtk_statusbar_new(); //gtk_box_pack_start(GTK_BOX(w.vbox), w.status, FALSE, FALSE, 0); w.win = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(w.win), 800, 800); g_signal_connect (G_OBJECT (w.win), "destroy", G_CALLBACK (destroy_cb), NULL); g_signal_connect(w.win, "key-press-event", G_CALLBACK(key_press_cb), NULL); gtk_container_add (GTK_CONTAINER (w.win), w.vbox); new_tab(); gtk_widget_show_all (w.win); } gboolean key_press_cb (GtkWidget *widget, GdkEventKey *event) { if (event->state == GDK_CONTROL_MASK) { if (gdk_keyval_to_lower(event->keyval) == GDK_f) { gtk_widget_grab_focus(GTK_WIDGET(w.bar)); return TRUE; } if (gdk_keyval_to_lower(event->keyval) == GDK_l) { gtk_widget_grab_focus(GTK_WIDGET(w.bar)); return TRUE; } if (gdk_keyval_to_lower(event->keyval) == GDK_j) { go_cb(FALSE); return TRUE; } if (gdk_keyval_to_lower(event->keyval) == GDK_k) { go_cb(TRUE); return TRUE; } if (gdk_keyval_to_lower(event->keyval) == GDK_t) { new_tab(); return TRUE; } if (gdk_keyval_to_lower(event->keyval) == GDK_w) { close_tab(); return TRUE; } //if (gdk_keyval_to_lower(event->keyval) == GDK_bracketright) { webkit_web_view_set_zoom_level(t->view, (webkit_web_view_get_zoom_level(t->view) + .05)); return TRUE; } //if (gdk_keyval_to_lower(event->keyval) == GDK_bracketleft) { webkit_web_view_set_zoom_level(t->view, (webkit_web_view_get_zoom_level(t->view) - .05)); return TRUE; } else { return FALSE; } } if (gtk_widget_has_focus(w.bar) && gdk_keyval_to_lower(event->keyval) == GDK_Escape) { gtk_widget_grab_focus(GTK_WIDGET(w.notebook)); return TRUE; } return FALSE; } int main (int argc, char* argv[]) { gtk_init (&argc, &argv); config(); //gchar* w->starting_uri = (gchar*) (argc > 1 ? argv[1] : "http://www.google.com/"); gtk_main(); return 0; }