1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. 3 * Copyright (C) 2007 Alp Toker <alp (at) atoker.com> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <gtk/gtk.h> 28 #include <webkit/webkit.h> 29 30 static GtkWidget* main_window; 31 static GtkWidget* uri_entry; 32 static GtkStatusbar* main_statusbar; 33 static WebKitWebView* web_view; 34 static gchar* main_title; 35 static gdouble load_progress; 36 static guint status_context_id; 37 38 static void 39 activate_uri_entry_cb (GtkWidget* entry, gpointer data) 40 { 41 const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry)); 42 g_assert (uri); 43 webkit_web_view_load_uri (web_view, uri); 44 } 45 46 static void 47 update_title (GtkWindow* window) 48 { 49 GString* string = g_string_new (main_title); 50 g_string_append (string, " - WebKit Launcher"); 51 if (load_progress < 100) 52 g_string_append_printf (string, " (%f%%)", load_progress); 53 gchar* title = g_string_free (string, FALSE); 54 gtk_window_set_title (window, title); 55 g_free (title); 56 } 57 58 static void 59 link_hover_cb (WebKitWebView* page, const gchar* title, const gchar* link, gpointer data) 60 { 61 /* underflow is allowed */ 62 gtk_statusbar_pop (main_statusbar, status_context_id); 63 if (link) 64 gtk_statusbar_push (main_statusbar, status_context_id, link); 65 } 66 67 static void 68 notify_title_cb (WebKitWebView* web_view, GParamSpec* pspec, gpointer data) 69 { 70 if (main_title) 71 g_free (main_title); 72 main_title = g_strdup (webkit_web_view_get_title(web_view)); 73 update_title (GTK_WINDOW (main_window)); 74 } 75 76 static void 77 notify_load_status_cb (WebKitWebView* web_view, GParamSpec* pspec, gpointer data) 78 { 79 if (webkit_web_view_get_load_status (web_view) == WEBKIT_LOAD_COMMITTED) { 80 WebKitWebFrame* frame = webkit_web_view_get_main_frame (web_view); 81 const gchar* uri = webkit_web_frame_get_uri (frame); 82 if (uri) 83 gtk_entry_set_text (GTK_ENTRY (uri_entry), uri); 84 } 85 } 86 87 static void 88 notify_progress_cb (WebKitWebView* web_view, GParamSpec* pspec, gpointer data) 89 { 90 load_progress = webkit_web_view_get_progress (web_view) * 100; 91 update_title (GTK_WINDOW (main_window)); 92 } 93 94 static void 95 destroy_cb (GtkWidget* widget, gpointer data) 96 { 97 gtk_main_quit (); 98 } 99 100 static void 101 go_back_cb (GtkWidget* widget, gpointer data) 102 { 103 webkit_web_view_go_back (web_view); 104 } 105 106 static void 107 go_forward_cb (GtkWidget* widget, gpointer data) 108 { 109 webkit_web_view_go_forward (web_view); 110 } 111 112 static GtkWidget* 113 create_browser () 114 { 115 GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL); 116 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 117 118 web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); 119 gtk_container_add (GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view)); 120 121 g_signal_connect (web_view, "notify::title", G_CALLBACK (notify_title_cb), web_view); 122 g_signal_connect (web_view, "notify::load-status", G_CALLBACK (notify_load_status_cb), web_view); 123 g_signal_connect (web_view, "notify::progress", G_CALLBACK (notify_progress_cb), web_view); 124 g_signal_connect (web_view, "hovering-over-link", G_CALLBACK (link_hover_cb), web_view); 125 126 return scrolled_window; 127 } 128 129 static GtkWidget* 130 create_statusbar () 131 { 132 main_statusbar = GTK_STATUSBAR (gtk_statusbar_new ()); 133 status_context_id = gtk_statusbar_get_context_id (main_statusbar, "Link Hover"); 134 135 return (GtkWidget*)main_statusbar; 136 } 137 138 static GtkWidget* 139 create_toolbar () 140 { 141 GtkWidget* toolbar = gtk_toolbar_new (); 142 143 #if GTK_CHECK_VERSION(2,15,0) 144 gtk_orientable_set_orientation (GTK_ORIENTABLE (toolbar), GTK_ORIENTATION_HORIZONTAL); 145 #else 146 gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL); 147 #endif 148 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ); 149 150 GtkToolItem* item; 151 152 /* the back button */ 153 item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK); 154 g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (go_back_cb), NULL); 155 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); 156 157 /* The forward button */ 158 item = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD); 159 g_signal_connect (G_OBJECT (item), "clicked", G_CALLBACK (go_forward_cb), NULL); 160 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); 161 162 /* The URL entry */ 163 item = gtk_tool_item_new (); 164 gtk_tool_item_set_expand (item, TRUE); 165 uri_entry = gtk_entry_new (); 166 gtk_container_add (GTK_CONTAINER (item), uri_entry); 167 g_signal_connect (G_OBJECT (uri_entry), "activate", G_CALLBACK (activate_uri_entry_cb), NULL); 168 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); 169 170 /* The go button */ 171 item = gtk_tool_button_new_from_stock (GTK_STOCK_OK); 172 g_signal_connect_swapped (G_OBJECT (item), "clicked", G_CALLBACK (activate_uri_entry_cb), (gpointer)uri_entry); 173 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, -1); 174 175 return toolbar; 176 } 177 178 static GtkWidget* 179 create_window () 180 { 181 GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 182 gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); 183 gtk_widget_set_name (window, "GtkLauncher"); 184 g_signal_connect (window, "destroy", G_CALLBACK (destroy_cb), NULL); 185 186 return window; 187 } 188 189 int 190 main (int argc, char* argv[]) 191 { 192 gtk_init (&argc, &argv); 193 if (!g_thread_supported ()) 194 g_thread_init (NULL); 195 196 GtkWidget* vbox = gtk_vbox_new (FALSE, 0); 197 gtk_box_pack_start (GTK_BOX (vbox), create_toolbar (), FALSE, FALSE, 0); 198 gtk_box_pack_start (GTK_BOX (vbox), create_browser (), TRUE, TRUE, 0); 199 gtk_box_pack_start (GTK_BOX (vbox), create_statusbar (), FALSE, FALSE, 0); 200 201 main_window = create_window (); 202 gtk_container_add (GTK_CONTAINER (main_window), vbox); 203 204 gchar* uri = (gchar*) (argc > 1 ? argv[1] : "http://www.google.com/"); 205 webkit_web_view_load_uri (web_view, uri); 206 207 gtk_widget_grab_focus (GTK_WIDGET (web_view)); 208 gtk_widget_show_all (main_window); 209 gtk_main (); 210 211 return 0; 212 } 213