diff --git a/midori/Makefile.am b/midori/Makefile.am index ffe49e56..3c327a3f 100644 --- a/midori/Makefile.am +++ b/midori/Makefile.am @@ -28,7 +28,8 @@ midori_SOURCES = \ midori-panel.c midori-panel.h \ midori-addons.c midori-addons.h \ midori-console.c midori-console.h \ - midori-webview.c midori-webview.h \ + midori-view.c midori-view.h \ + midori-source.c midori-source.h \ midori-websettings.c midori-websettings.h \ midori-preferences.c midori-preferences.h \ midori-searchentry.c midori-searchentry.h \ diff --git a/midori/main.c b/midori/main.c index de898e2d..fac85f03 100644 --- a/midori/main.c +++ b/midori/main.c @@ -13,6 +13,7 @@ #include #endif +#include "midori-view.h" #include "midori-app.h" #include "midori-websettings.h" #include "midori-browser.h" @@ -367,25 +368,76 @@ _simple_xml_element (const gchar* name, } static gchar* -katze_xbel_array_to_xml (KatzeArray* array, - GError** error) +katze_item_to_data (KatzeItem* item) +{ + gchar* markup; + + g_return_val_if_fail (KATZE_IS_ITEM (item), NULL); + + markup = NULL; + if (KATZE_IS_ARRAY (item)) + { + GString* _markup = g_string_new (NULL); + guint n = katze_array_get_length (KATZE_ARRAY (item)); + guint i; + for (i = 0; i < n; i++) + { + KatzeItem* _item = katze_array_get_nth_item (KATZE_ARRAY (item), i); + gchar* item_markup = katze_item_to_data (_item); + g_string_append (_markup, item_markup); + g_free (item_markup); + } + /* gchar* folded = item->folded ? NULL : g_strdup_printf (" folded=\"no\""); */ + gchar* title = _simple_xml_element ("title", katze_item_get_name (item)); + gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item)); + markup = g_strdup_printf ("\n%s%s%s\n", + "" /* folded ? folded : "" */, + title, desc, + g_string_free (_markup, FALSE)); + /* g_free (folded); */ + g_free (title); + g_free (desc); + } + else if (katze_item_get_uri (item)) + { + gchar* href_escaped = g_markup_escape_text (katze_item_get_uri (item), -1); + gchar* href = g_strdup_printf (" href=\"%s\"", href_escaped); + g_free (href_escaped); + gchar* title = _simple_xml_element ("title", katze_item_get_name (item)); + gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item)); + markup = g_strdup_printf ("\n%s%s%s\n", + href, + title, desc, + ""); + g_free (href); + g_free (title); + g_free (desc); + } + else + markup = g_strdup ("\n"); + return markup; +} + +static gchar* +katze_array_to_xml (KatzeArray* array, + GError** error) { GString* inner_markup; guint i, n; - KatzeXbelItem* item; + KatzeItem* item; gchar* item_xml; gchar* title; gchar* desc; gchar* outer_markup; - g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_XBEL_ITEM), NULL); + g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), NULL); inner_markup = g_string_new (NULL); n = katze_array_get_length (array); for (i = 0; i < n; i++) { item = katze_array_get_nth_item (array, i); - item_xml = katze_xbel_item_to_data (item); + item_xml = katze_item_to_data (item); g_string_append (inner_markup, item_xml); g_free (item_xml); } @@ -415,10 +467,10 @@ katze_array_to_file (KatzeArray* array, gchar* data; FILE* fp; - g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_XBEL_ITEM), FALSE); + g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), FALSE); g_return_val_if_fail (filename, FALSE); - if (!(data = katze_xbel_array_to_xml (array, error))) + if (!(data = katze_array_to_xml (array, error))) return FALSE; if (!(fp = fopen (filename, "w"))) { @@ -468,6 +520,7 @@ int main (int argc, char** argv) { + guint socket_id; gboolean version; gchar** uris; MidoriApp* app; @@ -475,12 +528,16 @@ main (int argc, GError* error; GOptionEntry entries[] = { - { "version", 'v', 0, G_OPTION_ARG_NONE, &version, + { "id", 'i', 0, G_OPTION_ARG_INT, &socket_id, + N_("Internal identifier"), NULL }, + { "version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Display program version"), NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &uris, N_("URIs"), NULL }, { NULL } }; + GtkWidget* view; + GtkWidget* plug; MidoriStartup load_on_startup; gchar* homepage; KatzeArray* search_engines; @@ -498,6 +555,7 @@ main (int argc, g_set_application_name (_("Midori")); /* Parse cli options */ + socket_id = 0; version = FALSE; uris = NULL; error = NULL; @@ -509,6 +567,22 @@ main (int argc, return 1; } + stock_items_init (); + + if (socket_id) + { + /* If an ID was specified we create a view in a plug. + This allows us to open views in separate processes. */ + view = g_object_new (MIDORI_TYPE_VIEW, "socket-id", socket_id, NULL); + gtk_widget_show (view); + plug = gtk_plug_new (socket_id); + gtk_container_add (GTK_CONTAINER (plug), view); + g_signal_connect (plug, "destroy", G_CALLBACK (gtk_main_quit), NULL); + gtk_widget_show (plug); + gtk_main (); + return 0; + } + if (version) { g_print ( @@ -539,6 +613,8 @@ main (int argc, return 1; } + sokoke_remember_argv0 (argv[0]); + app = midori_app_new (); if (midori_app_instance_is_running (app)) { @@ -691,14 +767,19 @@ main (int argc, } g_free (config_path); - stock_items_init (); - - KatzeArray* trash = katze_array_new (KATZE_TYPE_XBEL_ITEM); + KatzeArray* trash = katze_array_new (KATZE_TYPE_ITEM); guint n = katze_xbel_folder_get_n_items (xbel_trash); for (i = 0; i < n; i++) { - KatzeXbelItem* item = katze_xbel_folder_get_nth_item (xbel_trash, i); - katze_array_add_item (trash, item); + KatzeXbelItem* xbel_item = katze_xbel_folder_get_nth_item (xbel_trash, i); + if (!katze_xbel_item_is_separator (xbel_item)) + { + KatzeItem* item = g_object_new (KATZE_TYPE_ITEM, + "name", katze_xbel_item_get_title (xbel_item), + "uri", katze_xbel_bookmark_get_href (xbel_item), + NULL); + katze_array_add_item (trash, item); + } } katze_xbel_item_unref (xbel_trash); g_signal_connect_after (trash, "add-item", @@ -719,7 +800,7 @@ main (int argc, midori_app_add_browser (app, browser); gtk_widget_show (GTK_WIDGET (browser)); - KatzeArray* session = midori_browser_get_proxy_xbel_array (browser); + KatzeArray* session = midori_browser_get_proxy_array (browser); n = katze_xbel_folder_get_n_items (_session); for (i = 0; i < n; i++) { diff --git a/midori/midori-browser.c b/midori/midori-browser.c index 9828b507..91c2a9bb 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -15,7 +15,8 @@ #include "midori-browser.h" -#include "midori-webview.h" +#include "midori-view.h" +#include "midori-source.h" #include "midori-preferences.h" #include "midori-panel.h" #include "midori-addons.h" @@ -34,10 +35,6 @@ #endif #include #include -#if HAVE_GTKSOURCEVIEW -#include -#include -#endif #include struct _MidoriBrowser @@ -76,10 +73,8 @@ struct _MidoriBrowser gchar* statusbar_text; MidoriWebSettings* settings; KatzeXbelItem* bookmarks; - GList* tab_titles; - GList* close_buttons; - KatzeArray* proxy_xbel_array; + KatzeArray* proxy_array; KatzeArray* trash; KatzeArray* search_engines; }; @@ -105,8 +100,6 @@ enum enum { WINDOW_OBJECT_CLEARED, - STATUSBAR_TEXT_CHANGED, - ELEMENT_MOTION, NEW_WINDOW, ADD_TAB, @@ -163,56 +156,15 @@ _action_set_active (MidoriBrowser* browser, gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active); } -static const gchar* -_midori_browser_get_tab_uri (MidoriBrowser* browser, - GtkWidget* widget) -{ - const gchar* uri; - - if (MIDORI_IS_WEB_VIEW (widget)) - return midori_web_view_get_display_uri (MIDORI_WEB_VIEW (widget)); - - uri = g_object_get_data (G_OBJECT (widget), "browser-tab-uri"); - return uri ? uri : "file://"; -} - -/* Note: The return value is valid only - until the next call to this function */ -static const gchar* -_midori_browser_get_tab_title (MidoriBrowser* browser, - GtkWidget* widget) -{ - const gchar* uri; - static gchar* title = NULL; - - if (MIDORI_IS_WEB_VIEW (widget)) - return midori_web_view_get_display_title (MIDORI_WEB_VIEW (widget)); - - uri = g_object_get_data (G_OBJECT (widget), "browser-tab-uri"); - if (g_str_has_prefix (uri, "view-source:")) - { - g_free (title); - title = g_strconcat (_("Source"), ": ", uri, NULL); - return title; - } - return "untitled"; -} - static void _midori_browser_open_uri (MidoriBrowser* browser, const gchar* uri) { - GtkWidget* web_view; - gint n; + GtkWidget* view; - web_view = midori_browser_get_current_web_view (browser); - if (web_view) - webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), uri); - else - { - n = midori_browser_add_uri (browser, uri); - midori_browser_set_current_page (browser, n); - } + view = midori_browser_get_current_tab (browser); + if (view) + midori_view_set_uri (MIDORI_VIEW (view), uri); } static void @@ -238,35 +190,41 @@ _midori_browser_update_actions (MidoriBrowser* browser) static void _midori_browser_update_interface (MidoriBrowser* browser) { + GtkWidget* view; gboolean loading; - GtkWidget* widget; - GtkWidget* web_view; + gboolean can_reload; GtkAction* action; - widget = midori_browser_get_current_tab (browser); - web_view = widget && MIDORI_IS_WEB_VIEW (widget) ? widget : NULL; - loading = web_view != NULL - && midori_web_view_get_load_status (MIDORI_WEB_VIEW (web_view)) + view = midori_browser_get_current_tab (browser); + loading = midori_view_get_load_status (MIDORI_VIEW (view)) != MIDORI_LOAD_FINISHED; + can_reload = midori_view_can_reload (MIDORI_VIEW (view)); - _action_set_sensitive (browser, "Reload", web_view != NULL && !loading); - _action_set_sensitive (browser, "Stop", web_view != NULL && loading); - _action_set_sensitive (browser, "Back", web_view != NULL - && webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (web_view))); - _action_set_sensitive (browser, "Forward", web_view != NULL - && webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (web_view))); + _action_set_sensitive (browser, "Reload", can_reload && !loading); + _action_set_sensitive (browser, "Stop", can_reload && loading); + _action_set_sensitive (browser, "Back", + midori_view_can_go_back (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "Forward", + midori_view_can_go_forward (MIDORI_VIEW (view))); - _action_set_sensitive (browser, "Print", web_view != NULL); - _action_set_sensitive (browser, "ZoomIn", web_view != NULL); - _action_set_sensitive (browser, "ZoomOut", web_view != NULL); - _action_set_sensitive (browser, "ZoomNormal", web_view != NULL - && webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (web_view)) != 1.0); - #if HAVE_GIO - _action_set_sensitive (browser, "SourceView", web_view != NULL); - #endif - _action_set_sensitive (browser, "FindNext", web_view != NULL); - _action_set_sensitive (browser, "FindPrevious", web_view != NULL); - /* _action_set_sensitive (browser, "FindQuick", web_view != NULL); */ + _action_set_sensitive (browser, "Print", + midori_view_can_print (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "ZoomIn", + midori_view_can_zoom_in (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "ZoomOut", + midori_view_can_zoom_out (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "ZoomNormal", + midori_view_get_zoom_level (MIDORI_VIEW (view)) != 1.0); + _action_set_sensitive (browser, "SourceView", + midori_view_can_view_source (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "Find", + midori_view_can_find (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "FindNext", + midori_view_can_find (MIDORI_VIEW (view))); + _action_set_sensitive (browser, "FindPrevious", + midori_view_can_find (MIDORI_VIEW (view))); + /* _action_set_sensitive (browser, "FindQuick", + midori_view_can_find (MIDORI_VIEW (view))); */ action = gtk_action_group_get_action (browser->action_group, "ReloadStop"); if (!loading) @@ -275,7 +233,7 @@ _midori_browser_update_interface (MidoriBrowser* browser) g_object_set (action, "stock-id", GTK_STOCK_REFRESH, "tooltip", _("Reload the current page"), - "sensitive", web_view != NULL, NULL); + "sensitive", can_reload, NULL); gtk_widget_hide (browser->progressbar); if (!GTK_WIDGET_VISIBLE (browser->statusbar)) if (!sokoke_object_get_boolean (browser->settings, @@ -294,13 +252,13 @@ _midori_browser_update_interface (MidoriBrowser* browser) if (!GTK_WIDGET_VISIBLE (browser->navigationbar)) gtk_widget_show (browser->navigationbar); g_object_set (_action_by_name (browser, "Location"), "progress", - midori_web_view_get_progress (MIDORI_WEB_VIEW (web_view)), NULL); + midori_view_get_progress (MIDORI_VIEW (view)), NULL); } } katze_throbber_set_animated (KATZE_THROBBER (browser->throbber), loading); /* FIXME: This won't work due to a bug in GtkIconEntry */ - /* if (web_view && midori_web_view_get_news_feeds (MIDORI_WEB_VIEW (web_view))) + /* if (view && midori_view_get_news_feeds (MIDORI_VIEW (view))) gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY ( gtk_bin_get_child (GTK_BIN (browser->location))), GTK_ICON_ENTRY_SECONDARY, STOCK_NEWS_FEED); @@ -310,26 +268,6 @@ _midori_browser_update_interface (MidoriBrowser* browser) GTK_ICON_ENTRY_SECONDARY, NULL);*/ } -static GtkWidget* -_midori_browser_scrolled_for_child (MidoriBrowser* browser, - GtkWidget* child) -{ - GtkWidget* scrolled = gtk_widget_get_parent (child); - if (GTK_IS_VIEWPORT (scrolled)) - scrolled = gtk_widget_get_parent (scrolled); - return scrolled; -} - -static GtkWidget* -_midori_browser_child_for_scrolled (MidoriBrowser* browser, - GtkWidget* scrolled) -{ - GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled)); - if (GTK_IS_VIEWPORT (child)) - child = gtk_bin_get_child (GTK_BIN (child)); - return child; -} - static void _midori_browser_set_statusbar_text (MidoriBrowser* browser, const gchar* text) @@ -351,16 +289,16 @@ _midori_browser_set_current_page_smartly (MidoriBrowser* browser, static void _midori_browser_update_progress (MidoriBrowser* browser, - MidoriWebView* web_view) + MidoriView* view) { MidoriLocationAction* action; gdouble progress; gchar* message; action = MIDORI_LOCATION_ACTION (_action_by_name (browser, "Location")); - progress = midori_web_view_get_progress (web_view); + progress = midori_view_get_progress (view); /* When we are finished, we don't want to *see* progress anymore */ - if (midori_web_view_get_load_status (web_view) == MIDORI_LOAD_FINISHED) + if (midori_view_get_load_status (view) == MIDORI_LOAD_FINISHED) progress = 0.0; if (progress > 0.0) { @@ -383,35 +321,55 @@ _midori_browser_update_progress (MidoriBrowser* browser, } static void -midori_web_view_window_object_cleared_cb (GtkWidget* web_view, - WebKitWebFrame* web_frame, - JSGlobalContextRef js_context, - JSObjectRef js_window, - MidoriBrowser* browser) +_midori_browser_activate_action (MidoriBrowser* browser, + const gchar* name) { - g_signal_emit (browser, signals[WINDOW_OBJECT_CLEARED], 0, - web_frame, js_context, js_window); + GtkAction* action = _action_by_name (browser, name); + if (action) + gtk_action_activate (action); + else + g_warning (_("Unexpected action '%s'."), name); } static void -midori_web_view_notify_load_status_cb (GtkWidget* web_view, - GParamSpec* pspec, - MidoriBrowser* browser) +midori_view_notify_icon_cb (MidoriView* view, + GParamSpec* pspec, + MidoriBrowser* browser) { const gchar* uri; GtkAction* action; - uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); + uri = midori_view_get_display_uri (MIDORI_VIEW (view)); + action = _action_by_name (browser, "Location"); + midori_location_action_set_icon_for_uri ( + MIDORI_LOCATION_ACTION (action), midori_view_get_icon (view), uri); +} + +static void +midori_view_notify_load_status_cb (GtkWidget* view, + GParamSpec* pspec, + MidoriBrowser* browser) +{ + const gchar* uri; + GtkAction* action; + + uri = midori_view_get_display_uri (MIDORI_VIEW (view)); action = _action_by_name (browser, "Location"); - if (midori_web_view_get_load_status (MIDORI_WEB_VIEW (web_view)) + if (midori_view_get_load_status (MIDORI_VIEW (view)) == MIDORI_LOAD_COMMITTED) midori_location_action_add_uri ( MIDORI_LOCATION_ACTION (action), uri); - - if (web_view == midori_browser_get_current_web_view (browser)) + else if (midori_view_get_load_status (MIDORI_VIEW (view)) + == MIDORI_LOAD_FINISHED) { - if (midori_web_view_get_load_status (MIDORI_WEB_VIEW (web_view)) + /* g_signal_emit (browser, signals[WINDOW_OBJECT_CLEARED], 0, + web_frame, js_context, js_window); */ + } + + if (view == midori_browser_get_current_tab (browser)) + { + if (midori_view_get_load_status (MIDORI_VIEW (view)) == MIDORI_LOAD_COMMITTED) { midori_location_action_set_uri ( @@ -427,79 +385,15 @@ midori_web_view_notify_load_status_cb (GtkWidget* web_view, } static void -midori_web_view_notify_progress_cb (GtkWidget* web_view, - GParamSpec* pspec, - MidoriBrowser* browser) +midori_view_notify_progress_cb (GtkWidget* view, + GParamSpec* pspec, + MidoriBrowser* browser) { - if (web_view == midori_browser_get_current_web_view (browser)) - _midori_browser_update_progress (browser, MIDORI_WEB_VIEW (web_view)); -} - -static void -midori_web_view_notify_title_cb (GtkWidget* web_view, - GParamSpec* pspec, - MidoriBrowser* browser) -{ - const gchar* uri; - const gchar* title; - GtkAction* action; - gchar* window_title; - - uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - title = midori_web_view_get_display_title (MIDORI_WEB_VIEW (web_view)); - action = _action_by_name (browser, "Location"); - midori_location_action_set_title_for_uri ( - MIDORI_LOCATION_ACTION (action), title, uri); - - if (web_view == midori_browser_get_current_web_view (browser)) - { - window_title = g_strconcat (title, " - ", - g_get_application_name (), NULL); - gtk_window_set_title (GTK_WINDOW (browser), window_title); - g_free (window_title); - } -} - -static void -midori_web_view_notify_zoom_level_cb (GtkWidget* web_view, - GParamSpec* pspec, - MidoriBrowser* browser) -{ - if (web_view == midori_browser_get_current_web_view (browser)) - _action_set_sensitive (browser, "ZoomNormal", - webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (web_view)) != 1.0); -} - -static void -midori_web_view_statusbar_text_changed_cb (MidoriWebView* web_view, - const gchar* text, - MidoriBrowser* browser) -{ - _midori_browser_set_statusbar_text (browser, text); -} - -static void -midori_web_view_element_motion_cb (MidoriWebView* web_View, - const gchar* link_uri, - MidoriBrowser* browser) -{ - _midori_browser_set_statusbar_text (browser, link_uri); -} - -static void -midori_web_view_icon_ready_cb (MidoriWebView* web_view, - GdkPixbuf* icon, - MidoriBrowser* browser) -{ - const gchar* uri; - GtkAction* action; - - uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - action = _action_by_name (browser, "Location"); - midori_location_action_set_icon_for_uri ( - MIDORI_LOCATION_ACTION (action), icon, uri); + if (view == midori_browser_get_current_tab (browser)) + _midori_browser_update_progress (browser, MIDORI_VIEW (view)); } +/* static void midori_web_view_news_feed_ready_cb (MidoriWebView* web_view, const gchar* href, @@ -511,80 +405,53 @@ midori_web_view_news_feed_ready_cb (MidoriWebView* web_view, midori_location_action_set_secondary_icon (MIDORI_LOCATION_ACTION ( _action_by_name (browser, "Location")), STOCK_NEWS_FEED); } +*/ -static gboolean -midori_web_view_console_message_cb (GtkWidget* web_view, - const gchar* message, - guint line, - const gchar* source_id, - MidoriBrowser* browser) +static void +midori_view_notify_title_cb (GtkWidget* view, + GParamSpec* pspec, + MidoriBrowser* browser) { - midori_console_add (MIDORI_CONSOLE (browser->panel_console), - message, line, source_id); - return TRUE; + const gchar* uri; + const gchar* title; + GtkAction* action; + gchar* window_title; + + uri = midori_view_get_display_uri (MIDORI_VIEW (view)); + title = midori_view_get_display_title (MIDORI_VIEW (view)); + action = _action_by_name (browser, "Location"); + midori_location_action_set_title_for_uri ( + MIDORI_LOCATION_ACTION (action), title, uri); + + if (view == midori_browser_get_current_tab (browser)) + { + window_title = g_strconcat (title, " - ", + g_get_application_name (), NULL); + gtk_window_set_title (GTK_WINDOW (browser), window_title); + g_free (window_title); + } } -static gboolean -midori_web_view_button_press_event_cb (MidoriWebView* web_view, - GdkEventButton* event, - MidoriBrowser* browser) +static void +midori_view_notify_zoom_level_cb (GtkWidget* view, + GParamSpec* pspec, + MidoriBrowser* browser) { - GdkModifierType state = (GdkModifierType)0; - gint x, y; - const gchar* link_uri; - guint n; - gboolean background; + if (view == midori_browser_get_current_tab (browser)) + _action_set_sensitive (browser, "ZoomNormal", + midori_view_get_zoom_level (MIDORI_VIEW (view)) != 1.0); +} - gdk_window_get_pointer (NULL, &x, &y, &state); - link_uri = midori_web_view_get_link_uri (web_view); +static void +midori_view_notify_statusbar_text_cb (MidoriView* view, + GParamSpec* pspec, + MidoriBrowser* browser) +{ + gchar* text; - switch (event->button) - { - case 1: - if (!link_uri) - return FALSE; - if (state & GDK_SHIFT_MASK) - { - /* Open link in new window */ - g_signal_emit (browser, signals[NEW_WINDOW], 0, link_uri); - return TRUE; - } - else if (state & GDK_MOD1_MASK) - { - /* Open link in new tab */ - n = midori_browser_add_uri (browser, link_uri); - background = sokoke_object_get_boolean (browser->settings, - "open-tabs-in-the-background"); - if (state & GDK_CONTROL_MASK) - background = !background; - if (!background) - midori_browser_set_current_page (browser, n); - return TRUE; - } - break; - case 2: - if (link_uri) - { - /* Open link in new tab */ - n = midori_browser_add_uri (browser, link_uri); - background = sokoke_object_get_boolean (browser->settings, - "open-tabs-in-the-background"); - if (state & GDK_CONTROL_MASK) - background = !background; - if (!background) - midori_browser_set_current_page (browser, n); - return TRUE; - } - else if (state & GDK_CONTROL_MASK) - { - webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), 1.0); - return FALSE; /* Allow Ctrl + Middle click */ - } - break; - case 3: - return FALSE; - } - return FALSE; + g_object_get (view, "statusbar-text", &text, NULL); + _midori_browser_set_statusbar_text (browser, text); + g_free (text); } static void @@ -607,12 +474,12 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, if (new_bookmark) { - GtkWidget* widget = midori_browser_get_current_tab (browser); + GtkWidget* view = midori_browser_get_current_tab (browser); bookmark = katze_xbel_bookmark_new (); katze_xbel_item_set_title (bookmark, - _midori_browser_get_tab_title (browser, widget)); + midori_view_get_display_title (MIDORI_VIEW (view))); katze_xbel_bookmark_set_href (bookmark, - _midori_browser_get_tab_uri (browser, widget)); + midori_view_get_display_uri (MIDORI_VIEW (view))); } GtkWidget* hbox = gtk_hbox_new (FALSE, 8); @@ -707,74 +574,19 @@ midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser, } static void -midori_web_view_bookmark_add_cb (GtkWidget* menuitem, - GtkWidget* web_view) +midori_view_add_bookmark_cb (GtkWidget* menuitem, + const gchar* uri, + GtkWidget* view) { - const gchar* uri; KatzeXbelItem* xbel_item; MidoriBrowser* browser; - uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); xbel_item = katze_xbel_bookmark_new (); katze_xbel_bookmark_set_href (xbel_item, uri); browser = (MidoriBrowser*)gtk_widget_get_toplevel (menuitem); midori_browser_edit_bookmark_dialog_new (browser, xbel_item); } -static void -midori_web_view_populate_popup_cb (GtkWidget* web_view, - GtkWidget* menu, - MidoriBrowser* browser) -{ - gboolean has_selection; - const gchar* uri; - GtkAction* action; - GtkWidget* menuitem; - - if (MIDORI_IS_WEB_VIEW (web_view) - && midori_web_view_has_selection (MIDORI_WEB_VIEW (web_view))) - has_selection = TRUE; - else - has_selection = FALSE; - - uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); - if (uri) - { - action = _action_by_name (browser, "BookmarkAdd"); - menuitem = sokoke_action_create_popup_menu_item (action); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_bookmark_add_cb), web_view); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - } - - if (has_selection) - { - /* TODO: view selection source */ - } - - if (!uri && !has_selection) - { - action = _action_by_name (browser, "UndoTabClose"); - menuitem = sokoke_action_create_popup_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - menuitem = gtk_separator_menu_item_new (); - gtk_widget_show (menuitem); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "BookmarkAdd"); - menuitem = sokoke_action_create_popup_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "SaveAs"); - menuitem = sokoke_action_create_popup_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "SourceView"); - menuitem = sokoke_action_create_popup_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - action = _action_by_name (browser, "Print"); - menuitem = sokoke_action_create_popup_menu_item (action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - } -} - static gboolean midori_browser_tab_leave_notify_event_cb (GtkWidget* widget, GdkEventCrossing* event, @@ -785,18 +597,37 @@ midori_browser_tab_leave_notify_event_cb (GtkWidget* widget, } static void -midori_web_view_new_tab_cb (GtkWidget* web_view, - const gchar* uri, - MidoriBrowser* browser) +midori_view_activate_action_cb (GtkWidget* view, + const gchar* action, + MidoriBrowser* browser) +{ + _midori_browser_activate_action (browser, action); +} + +static void +midori_view_console_message_cb (GtkWidget* view, + const gchar* message, + gint line, + const gchar* source_id, + MidoriBrowser* browser) +{ + midori_console_add (MIDORI_CONSOLE (browser->panel_console), + message, line, source_id); +} + +static void +midori_view_new_tab_cb (GtkWidget* view, + const gchar* uri, + MidoriBrowser* browser) { gint n = midori_browser_add_uri (browser, uri); _midori_browser_set_current_page_smartly (browser, n); } static void -midori_web_view_new_window_cb (GtkWidget* web_view, - const gchar* uri, - MidoriBrowser* browser) +midori_view_new_window_cb (GtkWidget* view, + const gchar* uri, + MidoriBrowser* browser) { g_signal_emit (browser, signals[NEW_WINDOW], 0, uri); } @@ -805,18 +636,17 @@ static gboolean midori_browser_tab_destroy_cb (GtkWidget* widget, MidoriBrowser* browser) { - KatzeXbelItem* xbel_item; + KatzeItem* item; const gchar* uri; - if (browser->proxy_xbel_array && MIDORI_IS_WEB_VIEW (widget)) + if (browser->proxy_array && MIDORI_IS_VIEW (widget)) { - xbel_item = midori_web_view_get_proxy_xbel_item ( - MIDORI_WEB_VIEW (widget)); - uri = katze_xbel_bookmark_get_href (xbel_item); + item = midori_view_get_proxy_item (MIDORI_VIEW (widget)); + uri = katze_item_get_uri (item); if (browser->trash && uri && *uri) - katze_array_add_item (browser->trash, xbel_item); - katze_array_remove_item (browser->proxy_xbel_array, xbel_item); - katze_xbel_item_unref (xbel_item); + katze_array_add_item (browser->trash, item); + katze_array_remove_item (browser->proxy_array, item); + g_object_unref (item); } _midori_browser_update_actions (browser); @@ -844,243 +674,88 @@ midori_browser_window_menu_item_activate_cb (GtkWidget* menuitem, midori_browser_set_current_tab (browser, widget); } -static void -_update_label_size (GtkWidget* label, - gint size) -{ - gint width, height; - - if (size > -1) - { - sokoke_widget_get_text_size (label, "M", &width, &height); - gtk_widget_set_size_request (label, width * size, -1); - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); - } - else - { - gtk_widget_set_size_request (label, -1, -1); - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); - } -} - -static gboolean -midori_browser_tab_label_button_release_event (GtkWidget* tab_label, - GdkEventButton* event, - GtkWidget* widget) -{ - if (event->button == 2) - { - /* Close the widget on middle click */ - gtk_widget_destroy (widget); - return TRUE; - } - - return FALSE; -} - -static void -midori_browser_tab_icon_style_set (GtkWidget* tab_icon, - GtkStyle* previous_style) -{ - GtkSettings* gtk_settings; - gint width, height; - - gtk_settings = gtk_widget_get_settings (tab_icon); - gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_MENU, - &width, &height); - gtk_widget_set_size_request (tab_icon, width + 2, height + 2); -} - -static void -midori_browser_tab_close_clicked (GtkWidget* tab_close, - GtkWidget* widget) -{ - gtk_widget_destroy (widget); -} - static void _midori_browser_add_tab (MidoriBrowser* browser, - GtkWidget* widget) + GtkWidget* view) { - GtkWidget* scrolled; - GtkWidget* child; - GObjectClass* gobject_class; - GdkPixbuf* icon; - GtkWidget* tab_icon; - const gchar* title; - GtkWidget* tab_title; + GtkWidget* tab_label; GtkWidget* menuitem; - KatzeXbelItem* xbel_item; - GtkWidget* event_box; - GtkWidget* hbox; - GtkWidget* close_button; - GtkRcStyle* rcstyle; - GtkWidget* image; + KatzeItem* item; guint n; - scrolled = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), + GTK_WIDGET_SET_FLAGS (view, GTK_CAN_FOCUS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_ETCHED_IN); - gobject_class = G_OBJECT_GET_CLASS (widget); - if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal) - child = widget; - else + + tab_label = midori_view_get_proxy_tab_label (MIDORI_VIEW (view)); + menuitem = midori_view_get_proxy_menu_item (MIDORI_VIEW (view)); + + if (browser->proxy_array) { - child = gtk_viewport_new (NULL, NULL); - gtk_widget_show (child); - gtk_container_add (GTK_CONTAINER (child), widget); + item = midori_view_get_proxy_item (MIDORI_VIEW (view)); + g_object_ref (item); + katze_array_add_item (browser->proxy_array, item); } - gtk_container_add (GTK_CONTAINER (scrolled), child); - gtk_widget_show (scrolled); - if (MIDORI_IS_WEB_VIEW (widget)) - { - tab_icon = midori_web_view_get_proxy_tab_icon (MIDORI_WEB_VIEW (widget)); - tab_title = midori_web_view_get_proxy_tab_title (MIDORI_WEB_VIEW (widget)); - menuitem = midori_web_view_get_proxy_menu_item (MIDORI_WEB_VIEW (widget)); + g_object_connect (view, + "signal::notify::icon", + midori_view_notify_icon_cb, browser, + "signal::notify::load-status", + midori_view_notify_load_status_cb, browser, + "signal::notify::progress", + midori_view_notify_progress_cb, browser, + /* "signal::news-feed-ready", + midori_view_news_feed_ready_cb, browser, */ + "signal::notify::title", + midori_view_notify_title_cb, browser, + "signal::notify::zoom-level", + midori_view_notify_zoom_level_cb, browser, + "signal::notify::statusbar-text", + midori_view_notify_statusbar_text_cb, browser, + "signal::activate-action", + midori_view_activate_action_cb, browser, + "signal::console-message", + midori_view_console_message_cb, browser, + "signal::new-tab", + midori_view_new_tab_cb, browser, + "signal::new-window", + midori_view_new_window_cb, browser, + "signal::add-bookmark", + midori_view_add_bookmark_cb, browser, + NULL); - if (browser->proxy_xbel_array) - { - xbel_item = midori_web_view_get_proxy_xbel_item ( - MIDORI_WEB_VIEW (widget)); - katze_xbel_item_ref (xbel_item); - katze_array_add_item (browser->proxy_xbel_array, xbel_item); - } - - g_object_connect (widget, - "signal::window-object-cleared", - midori_web_view_window_object_cleared_cb, browser, - "signal::notify::progress", - midori_web_view_notify_progress_cb, browser, - "signal::notify::mload-status", - midori_web_view_notify_load_status_cb, browser, - "signal::icon-ready", - midori_web_view_icon_ready_cb, browser, - "signal::news-feed-ready", - midori_web_view_news_feed_ready_cb, browser, - "signal::notify::title", - midori_web_view_notify_title_cb, browser, - "signal::notify::zoom-level", - midori_web_view_notify_zoom_level_cb, browser, - "signal::status-bar-text-changed", - midori_web_view_statusbar_text_changed_cb, browser, - "signal::element-motion", - midori_web_view_element_motion_cb, browser, - "signal::console-message", - midori_web_view_console_message_cb, browser, - "signal::new-tab", - midori_web_view_new_tab_cb, browser, - "signal::new-window", - midori_web_view_new_window_cb, browser, - "signal::button-press-event", - midori_web_view_button_press_event_cb, browser, - "signal::populate-popup", - midori_web_view_populate_popup_cb, browser, - NULL); - } - else - { - if (GTK_IS_TEXT_VIEW (widget)) - icon = gtk_widget_render_icon (widget, GTK_STOCK_EDIT, - GTK_ICON_SIZE_MENU, NULL); - else - icon = gtk_widget_render_icon (widget, GTK_STOCK_FILE, - GTK_ICON_SIZE_MENU, NULL); - tab_icon = katze_throbber_new (); - katze_throbber_set_static_pixbuf (KATZE_THROBBER (tab_icon), icon); - title = _midori_browser_get_tab_title (browser, widget); - tab_title = gtk_label_new (title); - menuitem = sokoke_image_menu_item_new_ellipsized (title); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), - gtk_image_new_from_pixbuf (icon)); - g_object_unref (icon); - - if (browser->proxy_xbel_array) - { - xbel_item = katze_xbel_bookmark_new (); - katze_xbel_item_set_title (xbel_item, title); - katze_xbel_bookmark_set_href (xbel_item, - _midori_browser_get_tab_uri (browser, widget)); - katze_array_add_item (browser->proxy_xbel_array, xbel_item); - } - } - g_object_set_data (G_OBJECT (widget), "browser-tab-icon", tab_icon); - browser->tab_titles = g_list_prepend (browser->tab_titles, tab_title); - - g_signal_connect (tab_icon, "style-set", - G_CALLBACK (midori_browser_tab_icon_style_set), NULL); - g_signal_connect (widget, "leave-notify-event", + g_signal_connect (view, "leave-notify-event", G_CALLBACK (midori_browser_tab_leave_notify_event_cb), browser); - event_box = gtk_event_box_new (); - gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE); - hbox = gtk_hbox_new (FALSE, 1); - gtk_container_border_width (GTK_CONTAINER (hbox), 2); - gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox)); - gtk_misc_set_alignment (GTK_MISC (tab_icon), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (hbox), tab_icon, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (tab_title), 0.0, 0.5); - /* TODO: make the tab initially look "unvisited" until it's focused */ - gtk_box_pack_start (GTK_BOX (hbox), tab_title, FALSE, TRUE, 0); - _update_label_size (tab_title, - sokoke_object_get_int (browser->settings, "tab-label-size")); - - close_button = gtk_button_new (); - gtk_button_set_relief (GTK_BUTTON (close_button), GTK_RELIEF_NONE); - gtk_button_set_focus_on_click (GTK_BUTTON (close_button), FALSE); - rcstyle = gtk_rc_style_new (); - rcstyle->xthickness = rcstyle->ythickness = 0; - gtk_widget_modify_style (close_button, rcstyle); - g_object_unref (rcstyle); - image = katze_throbber_new (); - katze_throbber_set_static_stock_id (KATZE_THROBBER (image), GTK_STOCK_CLOSE); - gtk_button_set_image (GTK_BUTTON (close_button), image); - gtk_misc_set_alignment (GTK_MISC (image), 0.0, 0.0); - gtk_box_pack_end (GTK_BOX (hbox), close_button, FALSE, FALSE, 0); - gtk_widget_show_all (GTK_WIDGET (event_box)); - if (!sokoke_object_get_boolean (browser->settings, "close-buttons-on-tabs")) - gtk_widget_hide (close_button); - browser->close_buttons = g_list_prepend (browser->close_buttons, close_button); - - g_signal_connect (event_box, "button-release-event", - G_CALLBACK (midori_browser_tab_label_button_release_event), widget); - g_signal_connect (close_button, "style-set", - G_CALLBACK (midori_browser_tab_icon_style_set), NULL); - g_signal_connect (close_button, "clicked", - G_CALLBACK (midori_browser_tab_close_clicked), widget); - if (sokoke_object_get_boolean (browser->settings, "open-tabs-next-to-current")) { n = gtk_notebook_get_current_page (GTK_NOTEBOOK (browser->notebook)); - gtk_notebook_insert_page (GTK_NOTEBOOK (browser->notebook), scrolled, - event_box, n + 1); + gtk_notebook_insert_page (GTK_NOTEBOOK (browser->notebook), view, + tab_label, n + 1); } else - gtk_notebook_append_page (GTK_NOTEBOOK (browser->notebook), scrolled, - event_box); + gtk_notebook_append_page (GTK_NOTEBOOK (browser->notebook), view, + tab_label); #if GTK_CHECK_VERSION(2, 10, 0) gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (browser->notebook), - scrolled, TRUE); + view, TRUE); gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (browser->notebook), - scrolled, TRUE); + view, TRUE); #endif gtk_widget_show (menuitem); g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_browser_window_menu_item_activate_cb), scrolled); + G_CALLBACK (midori_browser_window_menu_item_activate_cb), view); gtk_menu_shell_append (GTK_MENU_SHELL (browser->menu_window), menuitem); /* We want the tab to be removed if the widget is destroyed */ - g_signal_connect_swapped (widget, "destroy", + g_signal_connect_swapped (view, "destroy", G_CALLBACK (gtk_widget_destroy), menuitem); - g_signal_connect_swapped (widget, "destroy", - G_CALLBACK (gtk_widget_destroy), scrolled); - g_signal_connect (widget, "destroy", + g_signal_connect (view, "destroy", G_CALLBACK (midori_browser_tab_destroy_cb), browser); _midori_browser_update_actions (browser); @@ -1088,20 +763,9 @@ _midori_browser_add_tab (MidoriBrowser* browser, static void _midori_browser_remove_tab (MidoriBrowser* browser, - GtkWidget* widget) + GtkWidget* view) { - gtk_widget_destroy (widget); -} - -static void -_midori_browser_activate_action (MidoriBrowser* browser, - const gchar* name) -{ - GtkAction* action = _action_by_name (browser, name); - if (action) - gtk_action_activate (action); - else - g_warning (_("Unexpected action '%s'."), name); + gtk_widget_destroy (view); } static void @@ -1165,17 +829,6 @@ midori_browser_class_init (MidoriBrowserClass* class) G_TYPE_POINTER, G_TYPE_POINTER); - signals[ELEMENT_MOTION] = g_signal_new ( - "element-motion", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriBrowserClass, element_motion), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - signals[NEW_WINDOW] = g_signal_new ( "new-window", G_TYPE_FROM_CLASS (class), @@ -1415,9 +1068,9 @@ _action_open_activate (GtkAction* action, gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN); gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser)); - /* base the start folder on the current web view's uri if it is local */ - GtkWidget* widget = midori_browser_get_current_tab (browser); - if ((uri = (gchar*)_midori_browser_get_tab_uri (browser, widget))) + /* base the start folder on the current view's uri if it is local */ + GtkWidget* view = midori_browser_get_current_tab (browser); + if ((uri = (gchar*)midori_view_get_display_uri (MIDORI_VIEW (view)))) { gchar* filename = g_filename_from_uri (uri, NULL, NULL); if (filename) @@ -1469,9 +1122,9 @@ static void _action_print_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_tab (browser); - if (web_view) - webkit_web_view_execute_script (WEBKIT_WEB_VIEW (web_view), "print ();"); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_print (MIDORI_VIEW (view)); } static void @@ -1489,12 +1142,12 @@ _action_edit_activate (GtkAction* action, gboolean can_cut = FALSE, can_copy = FALSE, can_paste = FALSE; gboolean has_selection, can_select_all = FALSE; - if (WEBKIT_IS_WEB_VIEW (widget)) + if (MIDORI_IS_VIEW (widget)) { - WebKitWebView* web_view = WEBKIT_WEB_VIEW (widget); - can_cut = webkit_web_view_can_cut_clipboard (web_view); - can_copy = webkit_web_view_can_copy_clipboard (web_view); - can_paste = webkit_web_view_can_paste_clipboard (web_view); + MidoriView* view = MIDORI_VIEW (widget); + can_cut = midori_view_can_cut_clipboard (view); + can_copy = midori_view_can_copy_clipboard (view); + can_paste = midori_view_can_paste_clipboard (view); can_select_all = TRUE; } else if (GTK_IS_EDITABLE (widget)) @@ -1725,10 +1378,12 @@ static void midori_browser_menu_trash_item_activate_cb (GtkWidget* menuitem, MidoriBrowser* browser) { + KatzeItem* item; + gint n; + /* Create a new web view with an uri which has been closed before */ - KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem), - "KatzeXbelItem"); - gint n = midori_browser_add_xbel_item (browser, item); + item = g_object_get_data (G_OBJECT (menuitem), "KatzeItem"); + n = midori_browser_add_item (browser, item); midori_browser_set_current_page (browser, n); katze_array_remove_item (browser->trash, item); _midori_browser_update_actions (browser); @@ -1740,7 +1395,7 @@ midori_browser_menu_trash_activate_cb (GtkWidget* widget, { GtkWidget* menu; guint i, n; - KatzeXbelItem* item; + KatzeItem* item; const gchar* title; const gchar* uri; GtkWidget* menuitem; @@ -1752,14 +1407,14 @@ midori_browser_menu_trash_activate_cb (GtkWidget* widget, for (i = 0; i < n; i++) { item = katze_array_get_nth_item (browser->trash, i); - title = katze_xbel_item_get_title (item); - uri = katze_xbel_bookmark_get_href (item); + title = katze_item_get_name (item); + uri = katze_item_get_uri (item); menuitem = sokoke_image_menu_item_new_ellipsized (title ? title : uri); /* FIXME: Get the real icon */ icon = gtk_image_new_from_stock (GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); - g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item); + g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item); g_signal_connect (menuitem, "activate", G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser); gtk_widget_show (menuitem); @@ -1830,19 +1485,23 @@ _action_reload_stop_activate (GtkAction* action, MidoriBrowser* browser) { gchar* stock_id; + GtkWidget* view; + GdkModifierType state = (GdkModifierType)0; + gint x, y; + gboolean from_cache; + g_object_get (action, "stock-id", &stock_id, NULL); - GtkWidget* web_view = midori_browser_get_current_web_view (browser); + view = midori_browser_get_current_tab (browser); + /* Refresh or stop, depending on the stock id */ if (!strcmp (stock_id, GTK_STOCK_REFRESH)) { - /*GdkModifierType state = (GdkModifierType)0; - gint x, y; gdk_window_get_pointer (NULL, &x, &y, &state); - gboolean from_cache = state & GDK_SHIFT_MASK;*/ - webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view)); + from_cache = state & GDK_SHIFT_MASK; + midori_view_reload (MIDORI_VIEW (view), !from_cache); } else - webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view)); + midori_view_stop_loading (MIDORI_VIEW (view)); g_free (stock_id); } @@ -1850,139 +1509,50 @@ static void _action_zoom_in_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view) - webkit_web_view_zoom_in (WEBKIT_WEB_VIEW (web_view)); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_set_zoom_level (MIDORI_VIEW (view), + midori_view_get_zoom_level (MIDORI_VIEW (view)) + 0.25f); } static void _action_zoom_out_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view) - webkit_web_view_zoom_out (WEBKIT_WEB_VIEW (web_view)); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_set_zoom_level (MIDORI_VIEW (view), + midori_view_get_zoom_level (MIDORI_VIEW (view)) - 0.25f); } static void _action_zoom_normal_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - if (web_view) - webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), 1.0); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_set_zoom_level (MIDORI_VIEW (view), 1.0f); } static void _action_source_view_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view; - const gchar* uri; - #if HAVE_GIO - GFile* file; - gchar* tag; - #if HAVE_GTKSOURCEVIEW - GFileInfo* info; - const gchar* content_type; - #endif - #endif - gchar* contents; - gchar* contents_utf8; - #if HAVE_GTKSOURCEVIEW - GtkSourceBuffer* buffer; - #if HAVE_GIO - GtkSourceLanguageManager* language_manager; - GtkSourceLanguage* language; - #endif - #else - GtkTextBuffer* buffer; - #endif - GtkWidget* text_view; + GtkWidget* view; + GtkWidget* source_view; + gchar* uri; gint n; - if (!(web_view = midori_browser_get_current_web_view (browser))) + if (!(view = midori_browser_get_current_tab (browser))) return; - uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view)); - - contents = NULL; - - #if HAVE_GIO - file = g_file_new_for_uri (uri); - tag = NULL; - #if HAVE_GTKSOURCEVIEW - content_type = NULL; - #endif - if (g_file_load_contents (file, NULL, &contents, NULL, &tag, NULL)) - { - #if HAVE_GTKSOURCEVIEW - info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, NULL, NULL); - content_type = g_file_info_get_content_type (info); - #endif - g_object_unref (file); - } - if (contents && !g_utf8_validate (contents, -1, NULL)) - { - contents_utf8 = g_convert (contents, -1, "UTF-8", "ISO-8859-1", - NULL, NULL, NULL); - g_free (contents); - } - else - #endif - contents_utf8 = contents; - - #if HAVE_GTKSOURCEVIEW - buffer = gtk_source_buffer_new (NULL); - gtk_source_buffer_set_highlight_syntax (buffer, TRUE); - #if HAVE_GIO - if (content_type) - { - language_manager = gtk_source_language_manager_get_default (); - if (!strcmp (content_type, "text/html")) - { - language = gtk_source_language_manager_get_language ( - language_manager, "html"); - gtk_source_buffer_set_language (buffer, language); - } - else if (!strcmp (content_type, "text/css")) - { - language = gtk_source_language_manager_get_language ( - language_manager, "css"); - gtk_source_buffer_set_language (buffer, language); - } - else if (!strcmp (content_type, "text/javascript")) - { - language = gtk_source_language_manager_get_language ( - language_manager, "js"); - gtk_source_buffer_set_language (buffer, language); - } - } - #endif - #else - buffer = gtk_text_buffer_new (NULL); - #endif - if (contents_utf8) - gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), contents_utf8, -1); - #if HAVE_GTKSOURCEVIEW - text_view = gtk_source_view_new_with_buffer (buffer); - gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (text_view), TRUE); - #else - text_view = gtk_text_view_new_with_buffer (buffer); - #endif - gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE); - g_object_set_data (G_OBJECT (text_view), "browser-tab-uri", - g_strconcat ("view-source:", uri, NULL)); - gtk_widget_show (text_view); - n = midori_browser_add_tab (browser, text_view); + uri = g_strdup_printf ("view-source:%s", + midori_view_get_display_uri (MIDORI_VIEW (view))); + source_view = midori_view_new_with_uri (uri); + g_free (uri); + gtk_widget_show (source_view); + n = midori_browser_add_tab (browser, source_view); midori_browser_set_current_page (browser, n); - - g_object_unref (buffer); - g_free (contents_utf8); - #if HAVE_GIO - g_free (tag); - #endif } static void @@ -2000,16 +1570,18 @@ static void _action_back_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view)); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_go_back (MIDORI_VIEW (view)); } static void _action_forward_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* web_view = midori_browser_get_current_web_view (browser); - webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view)); + GtkWidget* view = midori_browser_get_current_tab (browser); + if (view) + midori_view_go_forward (MIDORI_VIEW (view)); } static void @@ -2060,8 +1632,7 @@ _action_location_reset_uri (GtkAction* action, { const gchar* uri; - uri = _midori_browser_get_tab_uri (browser, - midori_browser_get_current_tab (browser)); + uri = midori_browser_get_current_uri (browser); midori_location_action_set_uri (MIDORI_LOCATION_ACTION (action), uri); } @@ -2109,7 +1680,7 @@ _action_location_secondary_icon_released (GtkAction* action, GtkWidget* widget, MidoriBrowser* browser) { - MidoriWebView* web_view; + MidoriView* view; KatzeArray* news_feeds; GtkWidget* menu; guint n, i; @@ -2118,10 +1689,10 @@ _action_location_secondary_icon_released (GtkAction* action, const gchar* title; GtkWidget* menuitem; - web_view = (MidoriWebView*)midori_browser_get_current_web_view (browser); - if (web_view) + view = (MidoriView*)midori_browser_get_current_tab (browser); + if (view) { - news_feeds = midori_web_view_get_news_feeds (web_view); + news_feeds = NULL /* midori_view_get_news_feeds (view) */; n = news_feeds ? katze_array_get_length (news_feeds) : 0; if (n) { @@ -2565,15 +2136,19 @@ static void _action_open_in_panel_activate (GtkAction* action, MidoriBrowser* browser) { - GtkWidget* widget = midori_browser_get_current_tab (browser); - const gchar* uri = _midori_browser_get_tab_uri (browser, widget); + GtkWidget* view; + const gchar* uri; + gint n; + + view = midori_browser_get_current_tab (browser); + uri = midori_view_get_display_uri (MIDORI_VIEW (view)); /* FIXME: Don't assign the uri here, update it properly while navigating */ g_object_set (browser->settings, "last-pageholder-uri", uri, NULL); - gint n = midori_panel_page_num (MIDORI_PANEL (browser->panel), - browser->panel_pageholder); + n = midori_panel_page_num (MIDORI_PANEL (browser->panel), + browser->panel_pageholder); midori_panel_set_current_page (MIDORI_PANEL (browser->panel), n); gtk_widget_show (browser->panel); - g_object_set (browser->panel_pageholder, "uri", uri, NULL); + midori_view_set_uri (MIDORI_VIEW (browser->panel_pageholder), uri); } @@ -2600,18 +2175,18 @@ gtk_notebook_switch_page_cb (GtkWidget* notebook, guint page_num, MidoriBrowser* browser) { - GtkWidget* widget; + GtkWidget* view; const gchar* uri; GtkAction* action; const gchar* title; gchar* window_title; - widget = midori_browser_get_current_tab (browser); - uri = _midori_browser_get_tab_uri (browser, widget); + view = midori_browser_get_current_tab (browser); + uri = midori_view_get_display_uri (MIDORI_VIEW (view)); action = _action_by_name (browser, "Location"); midori_location_action_set_uri (MIDORI_LOCATION_ACTION (action), uri); - title = _midori_browser_get_tab_title (browser, widget); + title = midori_view_get_display_title (MIDORI_VIEW (view)); window_title = g_strconcat (title, " - ", g_get_application_name (), NULL); gtk_window_set_title (GTK_WINDOW (browser), window_title); @@ -2621,8 +2196,7 @@ gtk_notebook_switch_page_cb (GtkWidget* notebook, _midori_browser_set_statusbar_text (browser, NULL); _midori_browser_update_interface (browser); - if (MIDORI_IS_WEB_VIEW (widget)) - _midori_browser_update_progress (browser, MIDORI_WEB_VIEW (widget)); + _midori_browser_update_progress (browser, MIDORI_VIEW (view)); } static void @@ -2639,8 +2213,8 @@ _action_bookmark_open_activate (GtkAction* action, { gtk_tree_model_get (model, &iter, 0, &item, -1); if (katze_xbel_item_is_bookmark (item)) - g_object_set (midori_browser_get_current_web_view (browser), - "uri", katze_xbel_bookmark_get_href (item), NULL); + _midori_browser_open_uri (browser, + katze_xbel_bookmark_get_href (item)); } } @@ -2711,13 +2285,13 @@ _action_undo_tab_close_activate (GtkAction* action, MidoriBrowser* browser) { guint last; - KatzeXbelItem* item; + KatzeItem* item; guint n; /* Reopen the most recent trash item */ last = katze_array_get_length (browser->trash) - 1; item = katze_array_get_nth_item (browser->trash, last); - n = midori_browser_add_xbel_item (browser, item); + n = midori_browser_add_item (browser, item); midori_browser_set_current_page (browser, n); katze_array_remove_item (browser->trash, item); _midori_browser_update_actions (browser); @@ -3474,7 +3048,7 @@ midori_browser_init (MidoriBrowser* browser) STOCK_BOOKMARKS, _("Bookmarks")); /* Transfers */ - GtkWidget* panel = midori_web_view_new (); + GtkWidget* panel = midori_view_new (); gtk_widget_show (panel); midori_panel_append_page (MIDORI_PANEL (browser->panel), panel, NULL, @@ -3490,16 +3064,14 @@ midori_browser_init (MidoriBrowser* browser) STOCK_CONSOLE, _("Console")); /* History */ - panel = midori_web_view_new (); + panel = midori_view_new (); gtk_widget_show (panel); midori_panel_append_page (MIDORI_PANEL (browser->panel), panel, NULL, STOCK_HISTORY, _("History")); /* Pageholder */ - browser->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", "", - NULL); + browser->panel_pageholder = midori_view_new (); gtk_widget_show (browser->panel_pageholder); midori_panel_append_page (MIDORI_PANEL (browser->panel), browser->panel_pageholder, NULL, @@ -3531,7 +3103,7 @@ midori_browser_init (MidoriBrowser* browser) panel, toolbar, STOCK_EXTENSIONS, _("Extensions")); - /* Notebook, containing all web_views */ + /* Notebook, containing all views */ browser->notebook = gtk_notebook_new (); /* Remove the inner border between scrollbars and the window border */ rcstyle = gtk_rc_style_new (); @@ -3635,9 +3207,6 @@ midori_browser_init (MidoriBrowser* browser) _action_set_sensitive (browser, "ZoomIn", FALSE); _action_set_sensitive (browser, "ZoomOut", FALSE); #endif - - browser->tab_titles = NULL; - browser->close_buttons = NULL; } static void @@ -3646,8 +3215,8 @@ midori_browser_dispose (GObject* object) MidoriBrowser* browser = MIDORI_BROWSER (object); /* We are done, the session mustn't change anymore */ - if (browser->proxy_xbel_array) - katze_object_assign (browser->proxy_xbel_array, NULL); + if (browser->proxy_array) + katze_object_assign (browser->proxy_array, NULL); G_OBJECT_CLASS (midori_browser_parent_class)->dispose (object); } @@ -3658,8 +3227,6 @@ midori_browser_finalize (GObject* object) MidoriBrowser* browser = MIDORI_BROWSER (object); g_free (browser->statusbar_text); - g_list_free (browser->tab_titles); - g_list_free (browser->close_buttons); if (browser->settings) g_object_unref (browser->settings); @@ -3719,8 +3286,6 @@ _midori_browser_update_settings (MidoriBrowser* browser) gint tab_label_size; gboolean close_buttons_on_tabs; - guint i, n; - g_object_get (browser->settings, "remember-last-window-size", &remember_last_window_size, "last-window-width", &last_window_width, @@ -3770,7 +3335,8 @@ _midori_browser_update_settings (MidoriBrowser* browser) gtk_paned_set_position (GTK_PANED (gtk_widget_get_parent (browser->panel)), last_panel_position); midori_panel_set_current_page (MIDORI_PANEL (browser->panel), last_panel_page); - g_object_set (browser->panel_pageholder, "uri", last_pageholder_uri, NULL); + midori_view_set_uri (MIDORI_VIEW (browser->panel_pageholder), + last_pageholder_uri); _action_set_active (browser, "Navigationbar", show_navigationbar); _action_set_active (browser, "Bookmarkbar", show_bookmarkbar); @@ -3782,16 +3348,6 @@ _midori_browser_update_settings (MidoriBrowser* browser) sokoke_widget_set_visible (browser->search, show_web_search); sokoke_widget_set_visible (browser->button_trash, show_trash); - /* We assume that tab_titles has the same length as close_buttons */ - n = g_list_length (browser->tab_titles); - for (i = 0; i < n; i++) - { - _update_label_size (g_list_nth_data (browser->tab_titles, i), - tab_label_size); - sokoke_widget_set_visible (g_list_nth_data (browser->close_buttons, i), - close_buttons_on_tabs); - } - g_free (last_pageholder_uri); } @@ -3802,8 +3358,6 @@ midori_browser_settings_notify (MidoriWebSettings* web_settings, { const gchar* name; GValue value = {0, }; - guint i; - guint n; name = g_intern_string (pspec->name); g_value_init (&value, pspec->value_type); @@ -3823,20 +3377,6 @@ midori_browser_settings_notify (MidoriWebSettings* web_settings, else if (name == g_intern_string ("show-trash")) sokoke_widget_set_visible (browser->button_trash, g_value_get_boolean (&value)); - else if (name == g_intern_string ("tab-label-size")) - { - n = g_list_length (browser->tab_titles); - for (i = 0; i < n; i++) - _update_label_size (g_list_nth_data (browser->tab_titles, i), - g_value_get_int (&value)); - } - else if (name == g_intern_string ("close-buttons-on-tabs")) - { - n = g_list_length (browser->close_buttons); - for (i = 0; i < n; i++) - sokoke_widget_set_visible (g_list_nth_data (browser->close_buttons, i), - g_value_get_boolean (&value)); - } else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings), name)) g_warning (_("Unexpected setting '%s'"), name); @@ -3946,11 +3486,8 @@ midori_browser_set_property (GObject* object, _midori_browser_update_settings (browser); g_signal_connect (browser->settings, "notify", G_CALLBACK (midori_browser_settings_notify), browser); - /* FIXME: Assigning settings must be conditional, if web view or not */ - /* FIXME: Assign settings only if the same settings object was used */ gtk_container_foreach (GTK_CONTAINER (browser->notebook), - (GtkCallback) midori_web_view_set_settings, - browser->settings); + (GtkCallback) midori_view_set_settings, browser->settings); break; case PROP_BOOKMARKS: ; /* FIXME: Disconnect handlers */ @@ -4056,63 +3593,100 @@ midori_browser_new (void) /** * midori_browser_add_tab: * @browser: a #MidoriBrowser - * @widget: a tab + * @widget: a view * - * Appends an arbitrary widget in the form of a new tab and creates an + * Appends a view in the form of a new tab and creates an * according item in the Window menu. * * Return value: the index of the new tab, or -1 in case of an error **/ gint midori_browser_add_tab (MidoriBrowser* browser, - GtkWidget* widget) + GtkWidget* view) { - GtkWidget* scrolled; - - g_signal_emit (browser, signals[ADD_TAB], 0, widget); - scrolled = _midori_browser_scrolled_for_child (browser, widget); - return gtk_notebook_page_num (GTK_NOTEBOOK (browser->notebook), scrolled); + g_signal_emit (browser, signals[ADD_TAB], 0, view); + return gtk_notebook_page_num (GTK_NOTEBOOK (browser->notebook), view); } /** * midori_browser_remove_tab: * @browser: a #MidoriBrowser - * @widget: a tab + * @widget: a view * - * Removes an existing tab from the browser, including an associated menu item. + * Removes an existing view from the browser, + * including an associated menu item. **/ void midori_browser_remove_tab (MidoriBrowser* browser, - GtkWidget* widget) + GtkWidget* view) { - g_signal_emit (browser, signals[REMOVE_TAB], 0, widget); + g_signal_emit (browser, signals[REMOVE_TAB], 0, view); } /** - * midori_browser_add_xbel_item: + * midori_browser_add_item: * @browser: a #MidoriBrowser - * @xbel_item: a bookmark + * @xbel_item: an XBEL item * - * Appends a #KatzeXbelItem in the form of a new tab. + * Appends a new view as described by @item. + * + * Note: Currently this will always be a #MidoriWebView. + * + * Return value: the index of the new view, or -1 in case of an error + **/ +gint +midori_browser_add_xbel_item (MidoriBrowser* browser, + KatzeXbelItem* item) +{ + const gchar* uri; + const gchar* title; + GtkWidget* view; + + g_return_val_if_fail (katze_xbel_item_is_bookmark (item), -1); + + uri = katze_xbel_bookmark_get_href (item); + title = katze_xbel_item_get_title (item); + view = g_object_new (MIDORI_TYPE_VIEW, + "title", title, + "settings", browser->settings, + NULL); + midori_view_set_uri (MIDORI_VIEW (view), uri); + gtk_widget_show (view); + + return midori_browser_add_tab (browser, view); +} + +/** + * midori_browser_add_item: + * @browser: a #MidoriBrowser + * @item: an item + * + * Appends a new view as described by @item. + * + * Note: Currently this will always be a #MidoriWebView. * * Return value: the index of the new tab, or -1 in case of an error **/ gint -midori_browser_add_xbel_item (MidoriBrowser* browser, - KatzeXbelItem* xbel_item) +midori_browser_add_item (MidoriBrowser* browser, + KatzeItem* item) { - g_return_val_if_fail (katze_xbel_item_is_bookmark (xbel_item), -1); + const gchar* uri; + const gchar* title; + GtkWidget* view; - const gchar* uri = katze_xbel_bookmark_get_href (xbel_item); - const gchar* title = katze_xbel_item_get_title (xbel_item); - GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", uri, - "title", title, - "settings", browser->settings, - NULL); - gtk_widget_show (web_view); + g_return_val_if_fail (KATZE_IS_ITEM (item), -1); - return midori_browser_add_tab (browser, web_view); + uri = katze_item_get_uri (item); + title = katze_item_get_name (item); + view = g_object_new (MIDORI_TYPE_VIEW, + "title", title, + "settings", browser->settings, + NULL); + midori_view_set_uri (MIDORI_VIEW (view), uri); + gtk_widget_show (view); + + return midori_browser_add_tab (browser, view); } /** @@ -4120,23 +3694,25 @@ midori_browser_add_xbel_item (MidoriBrowser* browser, * @browser: a #MidoriBrowser * @uri: an URI * - * Appends an uri in the form of a new tab. + * Appends an uri in the form of a new view. * - * Return value: the index of the new tab, or -1 + * Note: Currently this will always be a #MidoriView. + * + * Return value: the index of the new view, or -1 **/ gint midori_browser_add_uri (MidoriBrowser* browser, const gchar* uri) { - GtkWidget* web_view; + GtkWidget* view; - web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - "uri", uri, - "settings", browser->settings, - NULL); - gtk_widget_show (web_view); + view = g_object_new (MIDORI_TYPE_VIEW, + "settings", browser->settings, + NULL); + midori_view_set_uri (MIDORI_VIEW (view), uri); + gtk_widget_show (view); - return midori_browser_add_tab (browser, web_view); + return midori_browser_add_tab (browser, view); } /** @@ -4157,21 +3733,21 @@ midori_browser_activate_action (MidoriBrowser* browser, * midori_browser_get_current_uri: * @browser: a #MidoriBrowser * - * Determines the URI loaded in the current page. + * Determines the URI loaded in the current view. * - * If there is no page present at all, %NULL is returned. + * If there is no view present at all, %NULL is returned. * * Return value: the current URI, or %NULL **/ const gchar* midori_browser_get_current_uri (MidoriBrowser* browser) { - GtkWidget* widget; + GtkWidget* view; g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - widget = midori_browser_get_current_web_view (browser); - return _midori_browser_get_tab_uri (browser, widget); + view = midori_browser_get_current_tab (browser); + return midori_view_get_display_uri (MIDORI_VIEW (view)); } /** @@ -4187,13 +3763,14 @@ void midori_browser_set_current_page (MidoriBrowser* browser, gint n) { + GtkWidget* view; + gtk_notebook_set_current_page (GTK_NOTEBOOK (browser->notebook), n); - GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (browser->notebook), n); - GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled); - if (widget && !strcmp (_midori_browser_get_tab_uri (browser, widget), "")) + view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (browser->notebook), n); + if (view && midori_view_is_blank (MIDORI_VIEW (view))) gtk_action_activate (_action_by_name (browser, "Location")); else - gtk_widget_grab_focus (widget); + gtk_widget_grab_focus (view); } /** @@ -4217,23 +3794,27 @@ midori_browser_get_current_page (MidoriBrowser* browser) /** * midori_browser_set_current_tab: * @browser: a #MidoriBrowser - * @widget: a #GtkWidget + * @view: a #GtkWidget * - * Switches to the page containing @widget. + * Switches to the page containing @view. * * The widget will also grab the focus automatically. **/ void midori_browser_set_current_tab (MidoriBrowser* browser, - GtkWidget* widget) + GtkWidget* view) { - GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget); - gint n = gtk_notebook_page_num (GTK_NOTEBOOK (browser->notebook), scrolled); + gint n; + + g_return_if_fail (MIDORI_IS_BROWSER (browser)); + g_return_if_fail (GTK_IS_WIDGET (view)); + + n = gtk_notebook_page_num (GTK_NOTEBOOK (browser->notebook), view); gtk_notebook_set_current_page (GTK_NOTEBOOK (browser->notebook), n); - if (widget && !strcmp (_midori_browser_get_tab_uri (browser, widget), "")) + if (view && midori_view_is_blank (MIDORI_VIEW (view))) gtk_action_activate (_action_by_name (browser, "Location")); else - gtk_widget_grab_focus (widget); + gtk_widget_grab_focus (view); } /** @@ -4244,57 +3825,37 @@ midori_browser_set_current_tab (MidoriBrowser* browser, * * If there is no tab present at all, %NULL is returned. * + * See also midori_browser_get_current_page(). + * * Return value: the selected tab, or %NULL **/ GtkWidget* midori_browser_get_current_tab (MidoriBrowser* browser) { + gint n; + g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (browser->notebook)); + n = gtk_notebook_get_current_page (GTK_NOTEBOOK (browser->notebook)); if (n >= 0) { - GtkWidget* widget = _midori_browser_child_for_scrolled (browser, - gtk_notebook_get_nth_page (GTK_NOTEBOOK (browser->notebook), n)); - return widget; + return gtk_notebook_get_nth_page (GTK_NOTEBOOK (browser->notebook), n); } else return NULL; } /** - * midori_browser_get_current_web_view: + * midori_browser_get_proxy_array: * @browser: a #MidoriBrowser * - * Determines the currently selected web view. - * - * If there is no web view selected or if there is no tab present - * at all, %NULL is returned. - * - * See also midori_browser_get_current_page - * - * Return value: the selected web view, or %NULL - **/ -GtkWidget* -midori_browser_get_current_web_view (MidoriBrowser* browser) -{ - g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - - GtkWidget* web_view = midori_browser_get_current_tab (browser); - return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL; -} - -/** - * midori_browser_get_proxy_xbel_array: - * @browser: a #MidoriBrowser - * - * Retrieves a proxy xbel array representing the respective proxy xbel items - * of the present web views that can be used for session management. + * Retrieves a proxy array representing the respective proxy items + * of the present views that can be used for session management. * * The folder is created on the first call and will be updated to reflect * changes to all items automatically. * - * Note that this implicitly creates proxy xbel items of all web views. + * Note that this implicitly creates proxy items of all views. * * Note: Calling this function doesn't add a reference and the browser * may release its reference at some point. @@ -4302,16 +3863,16 @@ midori_browser_get_current_web_view (MidoriBrowser* browser) * Return value: the proxy #KatzeArray **/ KatzeArray* -midori_browser_get_proxy_xbel_array (MidoriBrowser* browser) +midori_browser_get_proxy_array (MidoriBrowser* browser) { g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL); - if (!browser->proxy_xbel_array) + if (!browser->proxy_array) { - browser->proxy_xbel_array = katze_array_new (KATZE_TYPE_XBEL_ITEM); - /* FIXME: Fill in xbel items of all present web views */ + browser->proxy_array = katze_array_new (KATZE_TYPE_ITEM); + /* FIXME: Fill in items of all present views */ } - return browser->proxy_xbel_array; + return browser->proxy_array; } /** diff --git a/midori/midori-browser.h b/midori/midori-browser.h index 42bff3f5..1a79087f 100644 --- a/midori/midori-browser.h +++ b/midori/midori-browser.h @@ -56,10 +56,10 @@ struct _MidoriBrowserClass void (*add_tab) (MidoriBrowser* browser, - GtkWidget* widget); + GtkWidget* view); void (*remove_tab) (MidoriBrowser* browser, - GtkWidget* widget); + GtkWidget* view); void (*activate_action) (MidoriBrowser* browser, const gchar* name); @@ -85,6 +85,10 @@ gint midori_browser_add_xbel_item (MidoriBrowser* browser, KatzeXbelItem* xbel_item); +gint +midori_browser_add_item (MidoriBrowser* browser, + KatzeItem* item); + gint midori_browser_add_uri (MidoriBrowser* browser, const gchar* uri); @@ -110,11 +114,8 @@ midori_browser_set_current_tab (MidoriBrowser* browser, GtkWidget* midori_browser_get_current_tab (MidoriBrowser* browser); -GtkWidget* -midori_browser_get_current_web_view (MidoriBrowser* browser); - KatzeArray* -midori_browser_get_proxy_xbel_array (MidoriBrowser* browser); +midori_browser_get_proxy_array (MidoriBrowser* browser); void midori_browser_quit (MidoriBrowser* browser); diff --git a/midori/midori-panel.c b/midori/midori-panel.c index 2e71895d..10e51b6b 100644 --- a/midori/midori-panel.c +++ b/midori/midori-panel.c @@ -373,6 +373,10 @@ midori_panel_append_page (MidoriPanel* panel, g_return_val_if_fail (stock_id != NULL, -1); g_return_val_if_fail (label != NULL, -1); + if (GTK_IS_SCROLLED_WINDOW (child)) + scrolled = child; + else + { scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, @@ -389,6 +393,7 @@ midori_panel_append_page (MidoriPanel* panel, gtk_container_add (GTK_CONTAINER (widget), child); } gtk_container_add (GTK_CONTAINER (scrolled), widget); + } gtk_container_add (GTK_CONTAINER (panel->notebook), scrolled); if (!toolbar) diff --git a/midori/midori-source.c b/midori/midori-source.c new file mode 100644 index 00000000..ce3131bb --- /dev/null +++ b/midori/midori-source.c @@ -0,0 +1,191 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#if HAVE_CONFIG_H + #include +#endif + +#include "midori-source.h" + +#include +#if HAVE_GIO + #include +#endif +#include +#if HAVE_GTKSOURCEVIEW + #include + #include + + #define MidoriSourceView GtkSourceView + #define MidoriSourceViewClass GtkSourceViewClass + #define MIDORI_TYPE_SOURCE_VIEW GTK_TYPE_SOURCE_VIEW +#else + #define MidoriSourceView GtkTextView + #define MidoriSourceViewClass GtkTextViewClass + #define MIDORI_TYPE_SOURCE_VIEW GTK_TYPE_TEXT_VIEW +#endif + +struct _MidoriSource +{ + MidoriSourceView parent_instance; +}; + +struct _MidoriSourceClass +{ + MidoriSourceViewClass parent_class; +}; + +G_DEFINE_TYPE (MidoriSource, midori_source, MIDORI_TYPE_SOURCE_VIEW); + +static void +midori_source_finalize (GObject* object); + +static void +midori_source_class_init (MidoriSourceClass* class) +{ + GObjectClass* gobject_class; + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_source_finalize; +} + +static void +midori_source_init (MidoriSource* source) +{ + #if HAVE_GTKSOURCEVIEW + GtkSourceBuffer* buffer; + #else + GtkTextBuffer* buffer; + #endif + + #if HAVE_GTKSOURCEVIEW + buffer = gtk_source_buffer_new (NULL); + gtk_source_buffer_set_highlight_syntax (buffer, TRUE); + gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (source), TRUE); + #else + buffer = gtk_text_buffer_new (NULL); + #endif + gtk_text_view_set_buffer (GTK_TEXT_VIEW (source), GTK_TEXT_BUFFER (buffer)); + gtk_text_view_set_editable (GTK_TEXT_VIEW (source), FALSE); +} + +static void +midori_source_finalize (GObject* object) +{ + G_OBJECT_CLASS (midori_source_parent_class)->finalize (object); +} + +/** + * midori_source_new: + * @uri: a view-source: URI + * + * Creates a new source widget. + * + * Return value: a new #MidoriSource + **/ +GtkWidget* +midori_source_new (const gchar* uri) +{ + MidoriSource* source = g_object_new (MIDORI_TYPE_SOURCE, + /*"uri", uri,*/ + NULL); + midori_source_set_uri (source, uri); + + return GTK_WIDGET (source); +} + +void +midori_source_set_uri (MidoriSource* source, + const gchar* uri) +{ + #if HAVE_GIO + GFile* file; + gchar* tag; + #if HAVE_GTKSOURCEVIEW + GFileInfo* info; + const gchar* content_type; + #endif + #endif + gchar* contents; + gchar* contents_utf8; + GtkTextBuffer* buffer; + #if HAVE_GTKSOURCEVIEW + #if HAVE_GIO + GtkSourceLanguageManager* language_manager; + GtkSourceLanguage* language; + #endif + #endif + + g_return_if_fail (MIDORI_IS_SOURCE (source)); + + contents = NULL; + + #if HAVE_GIO + file = g_file_new_for_uri (uri); + tag = NULL; + #if HAVE_GTKSOURCEVIEW + content_type = NULL; + #endif + if (g_file_load_contents (file, NULL, &contents, NULL, &tag, NULL)) + { + #if HAVE_GTKSOURCEVIEW + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + content_type = g_file_info_get_content_type (info); + #endif + g_object_unref (file); + } + if (contents && !g_utf8_validate (contents, -1, NULL)) + { + contents_utf8 = g_convert (contents, -1, "UTF-8", "ISO-8859-1", + NULL, NULL, NULL); + g_free (contents); + } + else + #endif + contents_utf8 = contents; + + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (source)); + #if HAVE_GTKSOURCEVIEW + #if HAVE_GIO + if (content_type) + { + language_manager = gtk_source_language_manager_get_default (); + if (!strcmp (content_type, "text/html")) + { + language = gtk_source_language_manager_get_language ( + language_manager, "html"); + gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer), language); + } + else if (!strcmp (content_type, "text/css")) + { + language = gtk_source_language_manager_get_language ( + language_manager, "css"); + gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer), language); + } + else if (!strcmp (content_type, "text/javascript")) + { + language = gtk_source_language_manager_get_language ( + language_manager, "js"); + gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer), language); + } + } + #endif + #endif + if (contents_utf8) + gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), contents_utf8, -1); + + g_object_unref (buffer); + g_free (contents_utf8); + #if HAVE_GIO + g_free (tag); + #endif +} diff --git a/midori/midori-source.h b/midori/midori-source.h new file mode 100644 index 00000000..e7b18783 --- /dev/null +++ b/midori/midori-source.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_SOURCE_H__ +#define __MIDORI_SOURCE_H__ + +#include + +G_BEGIN_DECLS + +#define MIDORI_TYPE_SOURCE \ + (midori_source_get_type ()) +#define MIDORI_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_SOURCE, MidoriSource)) +#define MIDORI_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_SOURCE, MidoriSourceClass)) +#define MIDORI_IS_SOURCE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_SOURCE)) +#define MIDORI_IS_SOURCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_SOURCE)) +#define MIDORI_SOURCE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_SOURCE, MidoriSourceClass)) + +typedef struct _MidoriSource MidoriSource; +typedef struct _MidoriSourceClass MidoriSourceClass; + +GType +midori_source_get_type (void); + +GtkWidget* +midori_source_new (const gchar* uri); + +void +midori_source_set_uri (MidoriSource* source, + const gchar* uri); + +G_END_DECLS + +#endif /* __MIDORI_SOURCE_H__ */ diff --git a/midori/midori-view.c b/midori/midori-view.c new file mode 100644 index 00000000..14986c9b --- /dev/null +++ b/midori/midori-view.c @@ -0,0 +1,2451 @@ +/* + Copyright (C) 2007-2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#if HAVE_CONFIG_H + #include +#endif + +#include "midori-view.h" +#include "midori-source.h" + +#include "midori-stock.h" + +#include "compat.h" +#include "sokoke.h" +#include "gjs.h" + +#include +#include +#if HAVE_GIO + #include +#endif +#include +#include + +/* This is unstable API, so we need to declare it */ +gchar* +webkit_web_view_get_selected_text (WebKitWebView* web_view); + +struct _MidoriView +{ + GtkScrolledWindow parent_instance; + + gint socket_id; + GIOChannel* input; + FILE* output; + + gchar* command_cache; + gchar* premature_uri; + gchar* uri; + gchar* title; + GdkPixbuf* icon; + gdouble progress; + MidoriLoadStatus load_status; + gchar* statusbar_text; + gchar* link_uri; + gboolean has_selection; + gchar* selected_text; + gboolean can_cut_clipboard; + gboolean can_copy_clipboard; + gboolean can_paste_clipboard; + gfloat zoom_level; + MidoriWebSettings* settings; + GtkWidget* web_view; + gboolean window_object_cleared; + + gchar* download_manager; + gint tab_label_size; + gboolean close_buttons_on_tabs; + + GtkWidget* menu_item; + GtkWidget* tab_label; + GtkWidget* tab_icon; + GtkWidget* tab_title; + GtkWidget* tab_close; + KatzeItem* item; +}; + +struct _MidoriViewClass +{ + GtkScrolledWindowClass parent_class; +}; + +G_DEFINE_TYPE (MidoriView, midori_view, GTK_TYPE_SCROLLED_WINDOW) + +GType +midori_load_status_get_type (void) +{ + static GType type = 0; + if (!type) + { + static const GEnumValue values[] = { + { MIDORI_LOAD_PROVISIONAL, "MIDORI_LOAD_PROVISIONAL", N_("Load Provisional") }, + { MIDORI_LOAD_COMMITTED, "MIDORI_LOAD_COMMITTED", N_("Load Committed") }, + { MIDORI_LOAD_FINISHED, "MIDORI_LOAD_FINISHED", N_("Load Finished") }, + { 0, NULL, NULL } + }; + type = g_enum_register_static ("MidoriLoadStatus", values); + } + return type; +} + +enum +{ + PROP_0, + + PROP_SOCKET_ID, + PROP_URI, + PROP_TITLE, + PROP_ICON, + PROP_LOAD_STATUS, + PROP_PROGRESS, + PROP_ZOOM_LEVEL, + PROP_STATUSBAR_TEXT, + PROP_SETTINGS +}; + +enum { + ACTIVATE_ACTION, + CONSOLE_MESSAGE, + NEW_TAB, + NEW_WINDOW, + ADD_BOOKMARK, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void +midori_view_finalize (GObject* object); + +static void +midori_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec); + +static void +midori_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec); + +static void +midori_cclosure_marshal_VOID__STRING_INT_STRING (GClosure* closure, + GValue* return_value, + guint n_param_values, + const GValue* param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void(*GMarshalFunc_VOID__STRING_INT_STRING) (gpointer data1, + gpointer arg_1, + gint arg_2, + gpointer arg_3, + gpointer data2); + register GMarshalFunc_VOID__STRING_INT_STRING callback; + register GCClosure* cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_INT_STRING) (marshal_data + ? marshal_data : cc->callback); + callback (data1, + (gchar*)g_value_get_string (param_values + 1), + g_value_get_int (param_values + 2), + (gchar*)g_value_get_string (param_values + 3), + data2); +} + +static void +midori_view_class_init (MidoriViewClass* class) +{ + GObjectClass* gobject_class; + GParamFlags flags; + + signals[ACTIVATE_ACTION] = g_signal_new ( + "activate-action", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[CONSOLE_MESSAGE] = g_signal_new ( + "console-message", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + midori_cclosure_marshal_VOID__STRING_INT_STRING, + G_TYPE_NONE, 3, + G_TYPE_STRING, + G_TYPE_INT, + G_TYPE_STRING); + + signals[NEW_TAB] = g_signal_new ( + "new-tab", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[NEW_WINDOW] = g_signal_new ( + "new-window", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[ADD_BOOKMARK] = g_signal_new ( + "add-bookmark", + G_TYPE_FROM_CLASS (class), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + 0, + 0, + NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = midori_view_finalize; + gobject_class->set_property = midori_view_set_property; + gobject_class->get_property = midori_view_get_property; + + flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; + + g_object_class_install_property (gobject_class, + PROP_SOCKET_ID, + g_param_spec_uint ( + "socket-id", + _("Socket ID"), + _("The ID of a socket"), + 0, + G_MAXUINT, + 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (gobject_class, + PROP_URI, + g_param_spec_string ( + "uri", + _("Uri"), + _("The URI of the currently loaded page"), + "about:blank", + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_TITLE, + g_param_spec_string ( + "title", + _("Title"), + _("The title of the currently loaded page"), + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_ICON, + g_param_spec_object ( + "icon", + _("Icon"), + _("The icon of the view"), + GDK_TYPE_PIXBUF, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_LOAD_STATUS, + g_param_spec_enum ( + "load-status", + _("Load Status"), + _("The current loading status"), + MIDORI_TYPE_LOAD_STATUS, + MIDORI_LOAD_FINISHED, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_PROGRESS, + g_param_spec_double ( + "progress", + _("Progress"), + _("The current loading progress"), + 0.0, 1.0, 0.0, + G_PARAM_READABLE)); + + g_object_class_install_property (gobject_class, + PROP_ZOOM_LEVEL, + g_param_spec_float ( + "zoom-level", + _("Zoom Level"), + _("The current zoom level"), + G_MINFLOAT, + G_MAXFLOAT, + 1.0f, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_STATUSBAR_TEXT, + g_param_spec_string ( + "statusbar-text", + _("Statusbar Text"), + _("The text that is displayed in the statusbar"), + "", + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_SETTINGS, + g_param_spec_object ( + "settings", + _("Settings"), + _("The associated settings"), + MIDORI_TYPE_WEB_SETTINGS, + G_PARAM_READWRITE)); +} + +#define midori_view_is_socket(view) !view->socket_id +#define midori_view_is_plug(view) view->socket_id > 0 + +#if 0 + #define midori_debug g_debug +#else + #define midori_debug(...) ; +#endif + +/** + * int_to_str + * @in: an integer + * + * Converts an integer to a string. + * + * The returned string is valid until + * the next call to this function. + * + * Return value: a string + **/ +static const gchar* +int_to_str (gint in) +{ + static gchar* out = NULL; + g_free (out); + out = g_strdup_printf ("%d", in); + return out; +} + +/** + * float_to_str + * @in: a float + * + * Converts a float to a string. + * + * The returned string is valid until + * the next call to this function. + * + * Return value: a string + **/ +static const gchar* +float_to_str (gfloat in) +{ + static gchar* out = NULL; + g_free (out); + out = g_strdup_printf ("%f", in); + return out; +} + + +static void +send_command (MidoriView* view, + const gchar* command, + const gchar* argument) +{ + gchar* data; + gchar* cache; + + if (argument) + data = g_strdup_printf ("%s %s", command, argument); + else + data = g_strdup (command); + + if (!view->output) + { + /* The output is not ready, so we cache for now */ + cache = g_strdup_printf ("%s\n%s", + view->command_cache ? view->command_cache : "", data); + katze_assign (view->command_cache, cache); + midori_debug ("!view->output, caching command: %s", command); + return; + } + + fwrite (data, strlen (data) + 1, 1, view->output); + fflush (view->output); + + g_free (data); +} + +static void +midori_view_notify_uri_cb (MidoriView* view, + GParamSpec pspec) +{ + if (midori_view_is_socket (view) && view->item) + katze_item_set_uri (view->item, view->uri); + + if (midori_view_is_plug (view)) + /* We must not send a NULL string here */ + send_command (view, "uri", view->uri ? view->uri : ""); +} + +static void +midori_view_notify_icon_cb (MidoriView* view, + GParamSpec pspec) +{ + if (view->tab_icon) + katze_throbber_set_static_pixbuf (KATZE_THROBBER (view->tab_icon), + view->icon); + if (view->menu_item) + gtk_image_menu_item_set_image ( + GTK_IMAGE_MENU_ITEM (view->menu_item), + gtk_image_new_from_pixbuf (view->icon)); +} + +#if HAVE_GIO +void +loadable_icon_finish_cb (GdkPixbuf* icon, + GAsyncResult* res, + MidoriView* view) +{ + GdkPixbuf* pixbuf; + GInputStream* stream; + GError* error; + GdkPixbuf* pixbuf_scaled; + gint icon_width, icon_height; + + pixbuf = NULL; + stream = g_loadable_icon_load_finish (G_LOADABLE_ICON (icon), + res, NULL, NULL); + if (stream) + { + error = NULL; + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, &error); + if (error) + midori_debug ("Icon couldn't be loaded: %s", error->message); + g_object_unref (stream); + } + if (!pixbuf) + pixbuf = gtk_widget_render_icon (GTK_WIDGET (view), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); + + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); + pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, + GDK_INTERP_BILINEAR); + g_object_unref (pixbuf); + katze_object_assign (view->icon, pixbuf_scaled); + g_object_notify (G_OBJECT (view), "icon"); +} + +void +file_info_finish_cb (GFile* icon_file, + GAsyncResult* res, + MidoriView* view) +{ + GFileInfo* info; + const gchar* content_type; + GIcon* icon; + GFile* parent; + GFile* file; + GdkPixbuf* pixbuf; + gint icon_width, icon_height; + GdkPixbuf* pixbuf_scaled; + + info = g_file_query_info_finish (G_FILE (icon_file), res, NULL); + if (info) + { + content_type = g_file_info_get_content_type (info); + if (g_str_has_prefix (content_type, "image/")) + { + icon = g_file_icon_new (icon_file); + g_loadable_icon_load_async (G_LOADABLE_ICON (icon), + 0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, view); + return; + } + } + + file = g_file_get_parent (icon_file); + parent = g_file_get_parent (file); + /* We need to check if file equals the parent due to a GIO bug */ + if (parent && !g_file_equal (file, parent)) + { + icon_file = g_file_get_child (parent, "favicon.ico"); + g_file_query_info_async (icon_file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, 0, NULL, + (GAsyncReadyCallback)file_info_finish_cb, view); + return; + } + + pixbuf = gtk_widget_render_icon (GTK_WIDGET (view), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); + pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, + GDK_INTERP_BILINEAR); + g_object_unref (pixbuf); + + view->icon = pixbuf_scaled; + g_object_notify (G_OBJECT (view), "icon"); +} +#endif + +static void +_midori_web_view_load_icon (MidoriView* view) +{ + #if HAVE_GIO + GFile* file; + GFile* icon_file; + #endif + GdkPixbuf* pixbuf; + gint icon_width, icon_height; + GdkPixbuf* pixbuf_scaled; + + #if HAVE_GIO + if (view->uri) + { + file = g_file_new_for_uri (view->uri); + icon_file = g_file_get_child (file, "favicon.ico"); + g_file_query_info_async (icon_file, + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, + G_FILE_QUERY_INFO_NONE, 0, NULL, + (GAsyncReadyCallback)file_info_finish_cb, view); + return; + } + #endif + + pixbuf = gtk_widget_render_icon (GTK_WIDGET (view), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); + pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, + GDK_INTERP_BILINEAR); + g_object_unref (pixbuf); + + view->icon = pixbuf_scaled; + g_object_notify (G_OBJECT (view), "icon"); +} + +static void +midori_view_notify_load_status_cb (MidoriView* view, + GParamSpec pspec) +{ + g_object_get (G_OBJECT (view), "load-status", &view->load_status, NULL); + + if (midori_view_is_socket (view)) + { + if (view->tab_icon) + katze_throbber_set_animated (KATZE_THROBBER (view->tab_icon), + view->load_status != MIDORI_LOAD_FINISHED); + } + + if (midori_view_is_plug (view)) + send_command (view, "load-status", int_to_str (view->load_status)); + + if (!midori_view_is_plug (view)) + if (view->load_status == MIDORI_LOAD_COMMITTED) + _midori_web_view_load_icon (view); +} + +static void +midori_view_notify_progress_cb (MidoriView* view, + GParamSpec pspec) +{ + g_object_get (G_OBJECT (view), "progress", &view->progress, NULL); + + if (midori_view_is_plug (view)) + send_command (view, "progress", float_to_str (view->progress)); +} + +static void +midori_view_action_cb (MidoriView* view, + const gchar* action) +{ + if (midori_view_is_socket (view)) + return; + + send_command (view, "activate-action", action); +} + +static void +midori_view_console_message_cb (MidoriView* view, + const gchar* message, + gint line, + const gchar* source_id) +{ + gchar* argument; + + if (midori_view_is_socket (view)) + return; + + argument = g_strdup_printf ("%s %d %s", message, line, source_id); + send_command (view, "console-message", argument); + g_free (argument); +} + +static void +midori_view_new_tab_cb (MidoriView* view, + const gchar* uri) +{ + if (midori_view_is_socket (view)) + return; + + send_command (view, "new-tab", uri); +} + +static void +midori_view_new_window_cb (MidoriView* view, + const gchar* uri) +{ + if (midori_view_is_socket (view)) + return; + + send_command (view, "new-window", uri); +} + +static void +midori_view_add_bookmark_cb (MidoriView* view, + const gchar* uri) +{ + if (midori_view_is_socket (view)) + return; + + send_command (view, "add-bookmark", uri); +} + +static void +receive_status (MidoriView* view, + const gchar* command) +{ + if (!strncmp (command, "uri ", 4)) + { + katze_assign (view->uri, g_strdup (&command[4])); + g_object_notify (G_OBJECT (view), "uri"); + } + else if (!strncmp (command, "title ", 6)) + { + g_object_set (view, "title", &command[6], NULL); + } + else if (!strncmp (command, "load-status ", 12)) + { + view->load_status = (MidoriLoadStatus)atoi (&command[12]); + g_object_notify (G_OBJECT (view), "load-status"); + } + else if (!strncmp (command, "progress ", 9)) + { + view->progress = atof (&command[9]); + g_object_notify (G_OBJECT (view), "progress"); + } + else if (!strncmp (command, "zoom-level ", 11)) + { + view->zoom_level = atof (&command[11]); + g_object_notify (G_OBJECT (view), "zoom-level"); + } + else if (!strncmp (command, "statusbar-text ", 15)) + { + g_object_set (view, "statusbar-text", &command[15], NULL); + } + else if (!strncmp (command, "activate-action ", 16)) + { + g_signal_emit (view, signals[ACTIVATE_ACTION], 0, &command[16]); + } + else if (!strncmp (command, "console-message ", 16)) + { + /* FIXME: Implement */ + } + else if (!strncmp (command, "new-tab ", 8)) + { + g_signal_emit (view, signals[NEW_TAB], 0, &command[8]); + } + else if (!strncmp (command, "new-window ", 11)) + { + g_signal_emit (view, signals[NEW_WINDOW], 0, &command[11]); + } + else if (!strncmp (command, "add-bookmark ", 13)) + { + g_signal_emit (view, signals[ADD_BOOKMARK], 0, &command[13]); + } + else if (!strncmp (command, "clipboard ", 10)) + { + view->can_cut_clipboard = atof (&command[10]); + view->can_copy_clipboard = atof (&command[12]); + view->can_paste_clipboard = atof (&command[14]); + midori_debug ("clipboards: %s => %d, %d, %d", + &command[10], + atoi (&command[10]), atoi (&command[12]), atoi (&command[14])); + } + else if (g_str_has_prefix (command, "**")) + { + g_print ("%s\n", command); + } + else + { + midori_debug ("receive_status: unknown command '%s'", command); + } +} + +static void +receive_command (MidoriView* view, + const gchar* command) +{ + if (!strncmp (command, "set-uri ", 8)) + midori_view_set_uri (view, &command[8]); + else if (!strncmp (command, "set-zoom-level ", 15)) + midori_view_set_zoom_level (view, atof (&command[15]) / 10); + else if (!strncmp (command, "reload ", 7)) + midori_view_reload (view, atoi (&command[7])); + else if (!strncmp (command, "stop-loading", 12)) + midori_view_stop_loading (view); + else if (!strncmp (command, "go-back", 7)) + midori_view_go_back (view); + else if (!strncmp (command, "go-forward", 10)) + midori_view_go_forward (view); + else if (!strncmp (command, "print", 5)) + midori_view_print (view); + else if (!strncmp (command, "download-manager ", 17)) + { + katze_assign (view->download_manager, g_strdup (&command[17])); + } + else if (g_str_has_prefix (command, "**")) + g_print ("%s\n", command); + else + midori_debug ("receive_command: unknown command '%s'", command); +} + +static gboolean +io_input_watch_cb (GIOChannel* source, + GIOCondition condition, + MidoriView* view) +{ + gchar* buffer; + GError* error; + + error = NULL; + switch (condition) + { + case G_IO_PRI: + case G_IO_IN: + if (g_io_channel_read_line (source, + &buffer, NULL, NULL, &error) == G_IO_STATUS_NORMAL) + { + if (view->socket_id) + receive_command (view, buffer); + else + receive_status (view, buffer); + g_free (buffer); + } + else + { + g_warning ("Communication error: %s", error->message); + g_error_free (error); + } + break; + case G_IO_ERR: + case G_IO_NVAL: + g_warning ("Invalid operation"); + return FALSE; + case G_IO_HUP: + midori_debug ("Tab closed"); + return FALSE; + default: + g_warning ("Unexpected condition"); + return FALSE; + } + + return TRUE; +} + +static void +webkit_web_view_load_started_cb (WebKitWebView* web_view, + WebKitWebFrame* web_frame, + MidoriView* view) +{ + view->window_object_cleared = FALSE; + + view->load_status = MIDORI_LOAD_PROVISIONAL; + g_object_notify (G_OBJECT (view), "load-status"); + + view->progress = 0.0; + g_object_notify (G_OBJECT (view), "progress"); +} + +static void +webkit_web_view_window_object_cleared_cb (WebKitWebView* web_view, + WebKitWebFrame* web_frame, + JSGlobalContextRef js_context, + JSObjectRef js_window, + MidoriView* view) +{ + view->window_object_cleared = TRUE; +} + +static void +webkit_web_view_load_committed_cb (WebKitWebView* web_view, + WebKitWebFrame* web_frame, + MidoriView* view) +{ + const gchar* uri; + GdkPixbuf* icon; + + uri = webkit_web_frame_get_uri (web_frame); + katze_assign (view->uri, g_strdup (uri)); + g_object_notify (G_OBJECT (view), "uri"); + g_object_set (view, "title", NULL, NULL); + + icon = gtk_widget_render_icon (GTK_WIDGET (view), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); + katze_object_assign (view->icon, icon); + g_object_notify (G_OBJECT (view), "icon"); + + view->load_status = MIDORI_LOAD_COMMITTED; + g_object_notify (G_OBJECT (view), "load-status"); +} + +static void +webkit_web_view_progress_changed_cb (WebKitWebView* web_view, + gint progress, + MidoriView* view) +{ + view->progress = progress ? progress / 100.0 : 0.0; + g_object_notify (G_OBJECT (view), "progress"); +} + +/* +static void +gjs_value_links_foreach_cb (GjsValue* link, + MidoriView* view) +{ + const gchar* type; +#if HAVE_GIO + const gchar* rel; + GFile* icon_file; + GIcon* icon; +#endif + + if (gjs_value_is_object (link) && gjs_value_has_attribute (link, "href")) + { + if (gjs_value_has_attribute (link, "type")) + { + type = gjs_value_get_attribute_string (link, "type"); + if (!strcmp (type, "application/rss+xml") + || !strcmp (type, "application/x.atom+xml") + || !strcmp (type, "application/atom+xml")) + { + katze_array_add_item (view->news_feeds, link); + g_signal_emit_by_name (view, "news-feed-ready", + gjs_value_get_attribute_string (link, "href"), type, + gjs_value_has_attribute (link, "title") + ? gjs_value_get_attribute_string (link, "title") : NULL); + } + } +#if HAVE_GIO + if (gjs_value_has_attribute (link, "rel")) + { + rel = gjs_value_get_attribute_string (link, "rel"); + if (!strcmp (rel, "icon") || !strcmp (rel, "shortcut icon")) + { + icon_file = g_file_new_for_uri ( + gjs_value_get_attribute_string (link, "href")); + icon = g_file_icon_new (icon_file); + g_loadable_icon_load_async (G_LOADABLE_ICON (icon), + 0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, view); + } + } +#endif + } +} +*/ + +static void +webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame, + gboolean success, + MidoriView* view) +{ + gchar* data; + JSContextRef js_context; + JSValueRef js_window; + /* GjsValue* value; + GjsValue* document; + GjsValue* links; */ + + if (!success) + { + midori_debug ("'%s' not found.", view->uri); + data = g_strdup_printf ("error:404 %s ", view->uri ? view->uri : ""); + midori_view_set_uri (view, data); + g_free (data); + return; + } + + /* If WebKit didn't emit the signal due to a bug, we will */ + if (!view->window_object_cleared) + { + js_context = webkit_web_frame_get_global_context (web_frame); + js_window = JSContextGetGlobalObject (js_context); + g_signal_emit_by_name (view->web_view, "window-object-cleared", + web_frame, js_context, js_window); + } + + /* value = gjs_value_new (webkit_web_frame_get_global_context (web_frame), NULL); + document = gjs_value_get_by_name (value, "document"); + links = gjs_value_get_elements_by_tag_name (document, "link"); + katze_array_clear (web_view->news_feeds); + gjs_value_foreach (links, (GjsCallback)gjs_value_links_foreach_cb, web_view); + g_object_unref (links); + g_object_unref (document); + g_object_unref (value); */ + + view->load_status = MIDORI_LOAD_FINISHED; + g_object_notify (G_OBJECT (view), "load-status"); +} + +static void +webkit_web_view_load_finished_cb (WebKitWebView* web_view, + WebKitWebFrame* web_frame, + MidoriView* view) +{ + view->progress = 1.0; + g_object_notify (G_OBJECT (view), "progress"); +} + +static void +webkit_web_view_title_changed_cb (WebKitWebView* web_view, + WebKitWebFrame* web_frame, + const gchar* title, + MidoriView* view) +{ + g_object_set (view, "title", title, NULL); +} + +static void +webkit_web_view_statusbar_text_changed_cb (WebKitWebView* web_view, + const gchar* text, + MidoriView* view) +{ + g_object_set (G_OBJECT (view), "statusbar-text", text, NULL); +} + +static void +webkit_web_view_hovering_over_link_cb (WebKitWebView* web_view, + const gchar* tooltip, + const gchar* link_uri, + MidoriView* view) +{ + katze_assign (view->link_uri, g_strdup (link_uri)); + g_object_set (G_OBJECT (view), "statusbar-text", link_uri, NULL); +} + +static gboolean +gtk_widget_button_press_event_cb (WebKitWebView* web_view, + GdkEventButton* event, + MidoriView* view) +{ + GdkModifierType state; + gint x, y; + GtkClipboard* clipboard; + gchar* uri; + gchar* new_uri; + const gchar* link_uri; + + gdk_window_get_pointer (NULL, &x, &y, &state); + link_uri = midori_view_get_link_uri (MIDORI_VIEW (view)); + + switch (event->button) + { + case 1: + if (!link_uri) + return FALSE; + if (state & GDK_SHIFT_MASK) + { + /* Open link in new window */ + g_signal_emit_by_name (view, "new-window", link_uri); + return TRUE; + } + else if (state & GDK_MOD1_MASK) + { + /* Open link in new tab */ + g_signal_emit_by_name (view, "new-tab", link_uri); + /* FIXME: Open in the background as appropriate */ + /* background = sokoke_object_get_boolean (browser->settings, + "open-tabs-in-the-background"); + if (state & GDK_CONTROL_MASK) + background = !background; + if (background) + open_tab_in_the_background */ + return TRUE; + } + break; + case 2: + if (link_uri) + { + /* Open link in new tab */ + g_signal_emit_by_name (view, "new-tab", link_uri); + /* FIXME: Open in the background as appropriate */ + /* background = sokoke_object_get_boolean (browser->settings, + "open-tabs-in-the-background"); + if (state & GDK_CONTROL_MASK) + background = !background; + if (background) + open_tab_in_the_background */ + return TRUE; + } + else if (state & GDK_CONTROL_MASK) + { + midori_view_set_zoom_level (MIDORI_VIEW (view), 1.0); + return FALSE; /* Allow Ctrl + Middle click */ + } + else if (TRUE /*middle-click-opens-selection*/) + { + state = (GdkModifierType) event->state; + clipboard = gtk_clipboard_get_for_display ( + gtk_widget_get_display (GTK_WIDGET (view)), + GDK_SELECTION_PRIMARY); + uri = gtk_clipboard_wait_for_text (clipboard); + if (uri && strchr (uri, '.') && !strchr (uri, ' ')) + { + new_uri = sokoke_magic_uri (uri, NULL); + if (state & GDK_CONTROL_MASK) + g_signal_emit_by_name (view, "new-tab", new_uri); + else + { + midori_view_set_uri (MIDORI_VIEW (view), new_uri); + gtk_widget_grab_focus (GTK_WIDGET (view)); + } + g_free (new_uri); + g_free (uri); + return TRUE; + } + } + break; + } + + return FALSE; +} + +static gboolean +gtk_widget_button_release_event_cb (WebKitWebView* web_view, + GdkEventButton* event, + MidoriView* view) +{ + GtkClipboard* clipboard; + gchar* text; + + /* Emulate the primary clipboard, which WebKit doesn't support */ + text = webkit_web_view_get_selected_text (WEBKIT_WEB_VIEW (web_view)); + clipboard = gtk_clipboard_get_for_display ( + gtk_widget_get_display (GTK_WIDGET (web_view)), GDK_SELECTION_PRIMARY); + gtk_clipboard_set_text (clipboard, text, -1); + g_free (text); + return FALSE; +} + +static gboolean +gtk_widget_scroll_event_cb (WebKitWebView* web_view, + GdkEventScroll* event, + MidoriView* view) +{ + GdkModifierType state = (GdkModifierType)0; + gint x, y; + + gdk_window_get_pointer (NULL, &x, &y, &state); + if (state & GDK_CONTROL_MASK) + { + if (event->direction == GDK_SCROLL_DOWN) + webkit_web_view_zoom_out (WEBKIT_WEB_VIEW (web_view)); + else if(event->direction == GDK_SCROLL_UP) + webkit_web_view_zoom_in (WEBKIT_WEB_VIEW (web_view)); + return TRUE; + } + else + return FALSE; +} + +static void +midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget, + MidoriView* view) +{ + g_signal_emit (view, signals[NEW_TAB], 0, view->link_uri); +} + +static void +midori_web_view_menu_new_window_activate_cb (GtkWidget* widget, + MidoriView* view) +{ + g_signal_emit (view, signals[NEW_WINDOW], 0, view->link_uri); +} + +static void +midori_web_view_menu_download_activate_cb (GtkWidget* widget, + MidoriView* view) +{ + sokoke_spawn_program (view->download_manager, view->link_uri); +} + +static void +midori_web_view_menu_add_bookmark_activate_cb (GtkWidget* widget, + MidoriView* view) +{ + g_signal_emit (view, signals[ADD_BOOKMARK], 0, view->link_uri); +} + +static void +midori_web_view_menu_action_activate_cb (GtkWidget* widget, + MidoriView* view) +{ + const gchar* action = g_object_get_data (G_OBJECT (widget), "action"); + g_signal_emit_by_name (view, "activate-action", action); +} + +static void +webkit_web_view_populate_popup_cb (WebKitWebView* web_view, + GtkWidget* menu, + MidoriView* view) +{ + GtkWidget* menuitem; + GtkWidget* icon; + gchar* stock_id; + GdkScreen* screen; + GtkIconTheme* icon_theme; + GList* items; + + /* We do not want to modify the Edit menu. + The only reliable indicator is inspecting the first item. */ + items = gtk_container_get_children (GTK_CONTAINER (menu)); + menuitem = (GtkWidget*)g_list_nth_data (items, 0); + if (GTK_IS_IMAGE_MENU_ITEM (menuitem)) + { + icon = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem)); + gtk_image_get_stock (GTK_IMAGE (icon), &stock_id, NULL); + if (!strcmp (stock_id, GTK_STOCK_CUT)) + return; + } + + if (view->link_uri) + { + menuitem = gtk_image_menu_item_new_with_mnemonic ( + _("Open Link in New _Tab")); + screen = gtk_widget_get_screen (GTK_WIDGET (view)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + if (gtk_icon_theme_has_icon (icon_theme, STOCK_TAB_NEW)) + { + icon = gtk_image_new_from_stock (STOCK_TAB_NEW, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + } + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 1); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), view); + gtk_widget_show (menuitem); + /* hack to implement New Window */ + items = gtk_container_get_children (GTK_CONTAINER (menu)); + menuitem = (GtkWidget*)g_list_nth_data (items, 2); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_new_window_activate_cb), view); + menuitem = (GtkWidget*)g_list_nth_data (items, 3); + /* hack to disable non-functional Download File */ + gtk_widget_set_sensitive (menuitem, FALSE); + g_list_free (items); + if (view->download_manager && *view->download_manager) + { + menuitem = gtk_image_menu_item_new_with_mnemonic ( + _("Download Link with Download _Manager")); + icon = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 4); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_download_activate_cb), view); + gtk_widget_show (menuitem); + } + menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 5); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_add_bookmark_activate_cb), view); + gtk_widget_show (menuitem); + } + + if (!view->link_uri && midori_view_has_selection (view)) + { + if (strchr (view->selected_text, '.') + && !strchr (view->selected_text, ' ')) + { + menuitem = gtk_image_menu_item_new_with_mnemonic ( + _("Open URL in New _Tab")); + icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1); + g_object_set_data (G_OBJECT (menuitem), "uri", view->selected_text); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), view); + gtk_widget_show (menuitem); + } + /* FIXME: view selection source */ + } + + if (!view->link_uri && !midori_view_has_selection (view)) + { + /* FIXME: Make this sensitive only when there is a tab to undo */ + menuitem = gtk_image_menu_item_new_with_mnemonic (_("Undo Close Tab")); + icon = gtk_image_new_from_stock (GTK_STOCK_UNDELETE, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "action", "UndoTabClose"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_action_activate_cb), view); + gtk_widget_show (menuitem); + menuitem = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + gtk_widget_show (menuitem); + menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "action", "BookmarkAdd"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_action_activate_cb), view); + gtk_widget_show (menuitem); + menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "action", "SaveAs"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_action_activate_cb), view); + gtk_widget_show (menuitem); + /* FIXME: Make this sensitive once it's implemented */ + gtk_widget_set_sensitive (menuitem, FALSE); + menuitem = gtk_image_menu_item_new_with_mnemonic (_("View _Source")); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "action", "SourceView"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_action_activate_cb), view); + gtk_widget_show (menuitem); + #if !HAVE_GIO + gtk_widget_set_sensitive (menuitem, FALSE); + #endif + menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); + g_object_set_data (G_OBJECT (menuitem), "action", "Print"); + g_signal_connect (menuitem, "activate", + G_CALLBACK (midori_web_view_menu_action_activate_cb), view); + gtk_widget_show (menuitem); + } +} + +static void +webkit_web_view_console_message_cb (GtkWidget* web_view, + const gchar* message, + guint line, + const gchar* source_id, + MidoriView* view) +{ + g_signal_emit_by_name (view, "console-message", message, line, source_id); +} + +static gboolean +gtk_widget_focus_out_event_cb (GtkWidget* web_view, + GdkEventFocus* event, + MidoriView* view) +{ + gchar* data; + + data = g_strdup_printf ("%d %d %d", + midori_view_can_cut_clipboard (view), + midori_view_can_copy_clipboard (view), + midori_view_can_paste_clipboard (view)); + send_command (view, "clipboard", data); + g_free (data); + + return FALSE; +} + +static void +midori_view_realize (MidoriView* view) +{ + WebKitWebFrame* web_frame; + + view->web_view = webkit_web_view_new (); + /* Adjustments are not created automatically */ + g_object_set (view, "hadjustment", NULL, "vadjustment", NULL, NULL); + + /* FIXME: Strictly we should send a command to query + the policy or send it as an argument */ + /* The socket view is not supposed to scroll at all */ + if (midori_view_is_socket (view)) + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), + GTK_POLICY_NEVER, GTK_POLICY_NEVER); + /* The plug view should use the policy of the socket */ + if (midori_view_is_plug (view)) + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + gtk_widget_show (view->web_view); + + web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view)); + + g_object_connect (view->web_view, + "signal::load-started", + webkit_web_view_load_started_cb, view, + "signal::window-object-cleared", + webkit_web_view_window_object_cleared_cb, view, + "signal::load-committed", + webkit_web_view_load_committed_cb, view, + "signal::load-progress-changed", + webkit_web_view_progress_changed_cb, view, + "signal::load-finished", + webkit_web_view_load_finished_cb, view, + "signal::title-changed", + webkit_web_view_title_changed_cb, view, + "signal::status-bar-text-changed", + webkit_web_view_statusbar_text_changed_cb, view, + "signal::hovering-over-link", + webkit_web_view_hovering_over_link_cb, view, + "signal::button-press-event", + gtk_widget_button_press_event_cb, view, + "signal::button-release-event", + gtk_widget_button_release_event_cb, view, + "signal::scroll-event", + gtk_widget_scroll_event_cb, view, + "signal::populate-popup", + webkit_web_view_populate_popup_cb, view, + "signal::console-message", + webkit_web_view_console_message_cb, view, + "signal::focus-out-event", + gtk_widget_focus_out_event_cb, view, + NULL); + g_object_connect (web_frame, + "signal::load-done", + webkit_web_frame_load_done_cb, view, + NULL); + + gtk_container_add (GTK_CONTAINER (view), view->web_view); + if (view->premature_uri) + { + midori_debug ("Loading premature uri '%s' now", view->premature_uri); + midori_view_set_uri (view, view->premature_uri); + } + katze_assign (view->premature_uri, NULL); +} + +static void +gtk_socket_realize_cb (GtkWidget* socket, + MidoriView* view) +{ + gchar* socket_id; + GError* error; + gboolean success; + gint stdin; + gint stdout; + gchar* argv[] = { NULL, "--id", NULL, NULL }; + + /* Sockets are not supported on all platforms, + so fallback to working without any socket or plug. */ + if (!gtk_socket_get_id (GTK_SOCKET (socket))) + { + gtk_widget_destroy (socket); + midori_view_realize (view); + return; + } + + socket_id = g_strdup_printf ("%d", gtk_socket_get_id (GTK_SOCKET (socket))); + argv[0] = (gchar*)sokoke_remember_argv0 (NULL); + argv[2] = socket_id; + error = NULL; + success = g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, + NULL, NULL, NULL, + &stdin, &stdout, NULL, &error); + g_free (socket_id); + + if (!success) + { + /* Fallback to operating without a socket */ + view->socket_id = 0; + midori_view_realize (view); + + g_error_free (error); + return; + } + + view->output = fdopen (stdin, "w"); + view->input = g_io_channel_unix_new (stdout); + g_io_channel_set_close_on_unref (view->input, TRUE); + g_io_add_watch (view->input, + G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc)io_input_watch_cb, view); + + if (view->command_cache) + { + /* Send cached commands if any */ + fwrite (view->command_cache, + strlen (view->command_cache) + 1, 1, view->output); + katze_assign (view->command_cache, NULL); + fflush (view->output); + } +} + +static gboolean +gtk_socket_plug_removed_cb (GtkWidget* socket, + MidoriView* view) +{ + if (view->output) + { + fclose (view->output); + view->output = NULL; + } + + if (view->input) + { + g_io_channel_unref (view->input); + view->input = NULL; + } + + midori_debug ("'%s' died.", view->uri); + send_command (view, "set-uri error:died", view->uri ? view->uri : ""); + if (GTK_WIDGET_REALIZED (view)) + gtk_socket_realize_cb (socket, view); + + return TRUE; +} + +static void +midori_view_realize_cb (MidoriView* view) +{ + GtkWidget* plug; + GtkWidget* socket; + + if (midori_view_is_plug (view)) + { + plug = gtk_plug_new (view->socket_id); + midori_view_realize (view); + gtk_widget_show (plug); + + view->input = g_io_channel_unix_new (0); /* 0 is stdin */ + g_io_channel_set_close_on_unref (view->input, TRUE); + g_io_add_watch (view->input, + G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP, + (GIOFunc)io_input_watch_cb, view); + view->output = fdopen (1, "w"); /* 1 is stdout */ + } + else if (midori_view_is_socket (view)) + { + socket = gtk_socket_new (); + g_signal_connect (socket, "realize", + G_CALLBACK (gtk_socket_realize_cb), view); + g_signal_connect (socket, "plug-removed", + G_CALLBACK (gtk_socket_plug_removed_cb), view); + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (view), + GTK_WIDGET (socket)); + gtk_widget_show (socket); + } +} + +static void +midori_view_init (MidoriView* view) +{ + view->command_cache = NULL; + view->premature_uri = NULL; + view->uri = NULL; + view->title = NULL; + view->icon = gtk_widget_render_icon (GTK_WIDGET (view), GTK_STOCK_FILE, + GTK_ICON_SIZE_MENU, NULL); + view->progress = 0.0; + view->load_status = MIDORI_LOAD_FINISHED; + view->statusbar_text = NULL; + view->link_uri = NULL; + view->selected_text = NULL; + view->settings = NULL; + view->item = NULL; + + view->download_manager = NULL; + + g_object_connect (view, + "signal::notify::uri", + midori_view_notify_uri_cb, NULL, + "signal::notify::icon", + midori_view_notify_icon_cb, NULL, + "signal::notify::load-status", + midori_view_notify_load_status_cb, NULL, + "signal::notify::progress", + midori_view_notify_progress_cb, NULL, + "signal::realize", + midori_view_realize_cb, NULL, + "signal::activate-action", + midori_view_action_cb, NULL, + "signal::console-message", + midori_view_console_message_cb, NULL, + "signal::new-tab", + midori_view_new_tab_cb, NULL, + "signal::new-window", + midori_view_new_window_cb, NULL, + "signal::add-bookmark", + midori_view_add_bookmark_cb, NULL, + NULL); +} + +static void +midori_view_finalize (GObject* object) +{ + MidoriView* view; + /* WebKitWebFrame* web_frame; */ + + view = MIDORI_VIEW (object); + + g_free (view->command_cache); + g_free (view->premature_uri); + g_free (view->uri); + g_free (view->title); + if (view->icon) + g_object_unref (view->icon); + g_free (view->statusbar_text); + g_free (view->link_uri); + g_free (view->selected_text); + if (view->settings) + g_object_unref (view->settings); + if (view->item) + g_object_unref (view->item); + + g_free (view->download_manager); + + /* web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view)); + g_signal_handlers_disconnect_by_func (web_frame, + webkit_web_frame_load_done, view); */ + + G_OBJECT_CLASS (midori_view_parent_class)->finalize (object); +} + +static void +midori_view_set_property (GObject* object, + guint prop_id, + const GValue* value, + GParamSpec* pspec) +{ + MidoriView* view; + + view = MIDORI_VIEW (object); + + switch (prop_id) + { + case PROP_SOCKET_ID: + view->socket_id = g_value_get_uint (value); + break; + case PROP_TITLE: + katze_assign (view->title, g_value_dup_string (value)); + if (!midori_view_is_plug (view)) + { + #define title midori_view_get_display_title (view) + if (view->tab_label) + { + gtk_label_set_text (GTK_LABEL (view->tab_title), title); + gtk_widget_set_tooltip_text (view->tab_title, title); + } + if (view->menu_item) + gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN ( + view->menu_item))), title); + if (view->item) + katze_item_set_name (view->item, title); + #undef title + } + if (midori_view_is_plug (view)) + /* We must not send a NULL string here */ + send_command (view, "title", view->title ? view->title : ""); + break; + case PROP_ZOOM_LEVEL: + midori_view_set_zoom_level (view, g_value_get_float (value)); + if (midori_view_is_plug (view)) + send_command (view, "zoom-level", float_to_str (view->zoom_level)); + break; + case PROP_STATUSBAR_TEXT: + katze_assign (view->statusbar_text, g_value_dup_string (value)); + if (midori_view_is_plug (view)) + /* We must not send a NULL string here */ + send_command (view, "statusbar-text", + view->statusbar_text ? view->statusbar_text : ""); + break; + case PROP_SETTINGS: + midori_view_set_settings (view, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +midori_view_get_property (GObject* object, + guint prop_id, + GValue* value, + GParamSpec* pspec) +{ + MidoriView* view = MIDORI_VIEW (object); + + switch (prop_id) + { + case PROP_SOCKET_ID: + g_value_set_uint (value, view->socket_id); + break; + case PROP_URI: + g_value_set_string (value, view->uri); + break; + case PROP_TITLE: + g_value_set_string (value, view->title); + break; + case PROP_PROGRESS: + g_value_set_double (value, midori_view_get_progress (view)); + break; + case PROP_LOAD_STATUS: + g_value_set_enum (value, midori_view_get_load_status (view)); + break; + case PROP_ZOOM_LEVEL: + g_value_set_float (value, midori_view_get_zoom_level (view)); + break; + case PROP_STATUSBAR_TEXT: + g_value_set_string (value, view->statusbar_text); + break; + case PROP_SETTINGS: + g_value_set_object (value, view->settings); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * midori_view_new: + * @view: a #MidoriView + * + * Creates a new view. + * + * Return value: a new #MidoriView + **/ +GtkWidget* +midori_view_new (void) +{ + return g_object_new (MIDORI_TYPE_VIEW, NULL); +} + +/** + * midori_view_new_with_uri: + * @view: a #MidoriView + * @uri: an URI + * + * Creates a new view with a particular URI. + * + * This constructor supports opaque views and is + * in fact currently the only way to create them. + * + * The only currently supported opaque view is + * the source view, implementing a #MidoriSource. + * Pass an URI prefixed with "view-source:" in + * order to create a source view. + * + * Return value: a new #MidoriView + **/ +GtkWidget* +midori_view_new_with_uri (const gchar* uri) +{ + MidoriView* view; + gchar* title; + GtkWidget* widget; + + view = g_object_new (MIDORI_TYPE_VIEW, NULL); + + if (uri && g_str_has_prefix (uri, "view-source:")) + { + view->socket_id = -1; + katze_assign (view->uri, g_strdup (uri)); + g_object_notify (G_OBJECT (view), "uri"); + title = g_strdup_printf ("%s - %s", _("Source"), &uri[12]); + g_object_set (view, "title", title, NULL); + g_free (title); + katze_object_assign (view->icon, + gtk_widget_render_icon (GTK_WIDGET (view), + GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL)); + widget = midori_source_new (&uri[12]); + /* Adjustments are not created automatically */ + g_object_set (view, "hadjustment", NULL, "vadjustment", NULL, NULL); + gtk_container_add (GTK_CONTAINER (view), widget); + gtk_widget_show (widget); + } + else + midori_view_set_uri (view, uri); + + return (GtkWidget*)view; +} + +static void +_update_label_size (GtkWidget* label, + gint size) +{ + gint width, height; + + if (size > -1) + { + sokoke_widget_get_text_size (label, "M", &width, &height); + gtk_widget_set_size_request (label, width * size, -1); + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); + } + else + { + gtk_widget_set_size_request (label, -1, -1); + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE); + } +} + +static void +_midori_view_update_settings (MidoriView* view) +{ + g_object_get (view->settings, + "download-manager", &view->download_manager, + "close-buttons-on-tabs", &view->close_buttons_on_tabs, + NULL); + + if (midori_view_is_socket (view)) + send_command (view, "download-manager", view->download_manager); +} + +static void +midori_view_settings_notify_cb (MidoriWebSettings* settings, + GParamSpec* pspec, + MidoriView* view) +{ + const gchar* name; + GValue value = { 0, }; + + name = g_intern_string (g_param_spec_get_name (pspec)); + g_value_init (&value, pspec->value_type); + g_object_get_property (G_OBJECT (view->settings), name, &value); + + if (name == g_intern_string ("download-manager")) + { + katze_assign (view->download_manager, g_value_dup_string (&value)); + if (midori_view_is_socket (view)) + send_command (view, "download-manager", view->download_manager); + } + else if (name == g_intern_string ("tab-label-size")) + { + view->tab_label_size = g_value_get_int (&value); + if (!midori_view_is_plug (view)) + _update_label_size (view->tab_title, + sokoke_object_get_int (view->settings, "tab-label-size")); + } + else if (name == g_intern_string ("close-buttons-on-tabs")) + { + view->close_buttons_on_tabs = g_value_get_boolean (&value); + sokoke_widget_set_visible (view->tab_close, + view->close_buttons_on_tabs); + } + + g_value_unset (&value); +} + +/** + * midori_view_set_settings: + * @view: a #MidoriView + * @settings: a #MidoriWebSettings + * + * Assigns a settings instance to the view. + **/ +void +midori_view_set_settings (MidoriView* view, + MidoriWebSettings* settings) +{ + if (view->settings) + g_signal_handlers_disconnect_by_func (view->settings, + midori_view_settings_notify_cb, view); + katze_object_assign (view->settings, g_object_ref (settings)); + /* FIXME: Propagate settings to the web view */ + _midori_view_update_settings (view); + g_signal_connect (settings, "notify", + G_CALLBACK (midori_view_settings_notify_cb), view); + g_object_notify (G_OBJECT (view), "settings"); +} + +/** + * midori_view_load_status: + * @web_view: a #MidoriView + * + * Determines the current loading status of a view. + * + * Return value: the current #MidoriLoadStatus + **/ +MidoriLoadStatus +midori_view_get_load_status (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), MIDORI_LOAD_FINISHED); + + return view->load_status; +} + +/** + * midori_view_get_progress: + * @view: a #MidoriView + * + * Retrieves the current loading progress as + * a fraction between 0.0 and 1.0. + * + * Return value: the current loading progress + **/ +gdouble +midori_view_get_progress (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), 0.0); + + return view->progress; +} + +/** + * midori_view_set_uri: + * @view: a #MidoriView + * + * Opens the specified URI in the view. + * + * FIXME: + * If the view doesn't allow changing the URI it + * will automatically request a new tab. + **/ +void +midori_view_set_uri (MidoriView* view, + const gchar* uri) +{ + gchar* data; + + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + /* We must not send a NULL string here */ + send_command (view, "set-uri", uri ? uri : ""); + else + { + if (!view->web_view) + { + /* An URI is requested before the view was realized. + We special case this to load it when we are ready. */ + midori_debug ("Deferring premature uri '%s'", uri); + katze_assign (view->premature_uri, g_strdup (uri)); + return; + } + midori_debug ("Opening URI: %s", uri); + /* This is not prefectly elegant, but creating an + error page inline is the simplest solution. */ + if (g_str_has_prefix (uri, "error:")) + { + data = NULL; + if (!strncmp (uri, "error:died ", 11)) + { + katze_assign (view->uri, g_strdup (&uri[11])); + data = g_strdup_printf ( + "Page died - %s" + "

Page died - %s

" + "

The page you were navigating on died." + "

Try to load the page again, " + "or move on to another page." + "", + view->uri, view->uri, view->uri); + } + else if (!strncmp (uri, "error:404 ", 10)) + { + katze_assign (view->uri, g_strdup (&uri[10])); + data = g_strdup_printf ( + "Not found - %s" + "

Not found - %s

" + "

The page you were opening doesn't exist." + "

Try to load the page again, " + "or move on to another page." + "", + view->uri, view->uri, view->uri); + } + if (data) + { + webkit_web_view_load_html_string ( + WEBKIT_WEB_VIEW (view->web_view), data, view->uri); + g_free (data); + g_object_notify (G_OBJECT (view), "uri"); + return; + } + } + else + { + katze_assign (view->uri, g_strdup (uri)); + webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), uri); + } + } +} + +/** + * midori_view_is_blank: + * @view: a #MidoriView + * + * Determines whether the view is currently empty. + **/ +gboolean +midori_view_is_blank (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), TRUE); + + return !(view->uri && *view->uri); +} + +/** + * midori_view_get_icon: + * @view: a #MidoriView + * + * Retrieves the icon of the view. + * + * Return value: a #GdkPixbuf + **/ +GdkPixbuf* +midori_view_get_icon (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + return view->icon; +} + +/** + * midori_view_get_display_uri: + * @view: a #MidoriView + * + * Retrieves a string that is suitable for displaying, + * particularly an empty URI is represented as "about:blank". + * + * You can assume that the string is not %NULL. + * + * Return value: an URI string + **/ +const gchar* +midori_view_get_display_uri (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), "about:blank"); + + if (view->uri && *view->uri) + return view->uri; + return "about:blank"; +} + +/** + * midori_view_get_display_title: + * @view: a #MidoriView + * + * Retrieves a string that is suitable for displaying + * as a title. Most of the time this will be the title + * or the current URI. + * + * You can assume that the string is not %NULL. + * + * Return value: a title string + **/ +const gchar* +midori_view_get_display_title (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), "about:blank"); + + if (view->title && *view->title) + return view->title; + return midori_view_get_display_uri (view); +} + +/** + * midori_view_get_link_uri: + * @view: a #MidoriView + * + * Retrieves the uri of the currently focused link, + * particularly while the mouse hovers a link or a + * context menu is being opened. + * + * Return value: an URI string, or %NULL if there is no link focussed + **/ +const gchar* +midori_view_get_link_uri (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + return view->link_uri; +} + +/** + * midori_view_has_selection: + * @view: a #MidoriView + * + * Determines whether something in the view is selected. + * + * This function returns %FALSE if there is a selection + * that effectively only consists of whitespace. + * + * Return value: %TRUE if effectively there is a selection + **/ +gboolean +midori_view_has_selection (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); + + if (midori_view_is_socket (view)) + return view->has_selection; + else + { + view->selected_text = webkit_web_view_get_selected_text ( + WEBKIT_WEB_VIEW (view->web_view)); + if (view->selected_text && *view->selected_text) + return TRUE; + return FALSE; + } +} + +/** + * midori_view_get_selected_text: + * @view: a #MidoriView + * + * Retrieves the currently selected text. + * + * Return value: the selected text, or %NULL + **/ +const gchar* +midori_view_get_selected_text (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + if (midori_view_is_socket (view)) + return view->selected_text; + else if (midori_view_has_selection (view)) + return midori_view_get_selected_text (view); + else + return NULL; +} + +/** + * midori_view_can_cut_clipboard: + * @view: a #MidoriView + * + * Determines whether a selection can be cut. + * + * Return value: %TRUE if a selection can be cut + **/ +gboolean +midori_view_can_cut_clipboard (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); + + if (midori_view_is_socket (view)) + return view->can_cut_clipboard; + else if (view->web_view) + { + view->can_cut_clipboard = webkit_web_view_can_cut_clipboard ( + WEBKIT_WEB_VIEW (view->web_view)); + return view->can_cut_clipboard; + } + return FALSE; +} + +/** + * midori_view_can_copy_clipboard: + * @view: a #MidoriView + * + * Determines whether a selection can be copied. + * + * Return value: %TRUE if a selection can be copied + **/ +gboolean +midori_view_can_copy_clipboard (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); + + if (midori_view_is_socket (view)) + return view->can_copy_clipboard; + else if (view->web_view) + { + view->can_copy_clipboard = webkit_web_view_can_copy_clipboard ( + WEBKIT_WEB_VIEW (view->web_view)); + return view->can_copy_clipboard; + } + return FALSE; +} + +/** + * midori_view_can_paste_clipboard: + * @view: a #MidoriView + * + * Determines whether a selection can be pasted. + * + * Return value: %TRUE if a selection can be pasted + **/ +gboolean +midori_view_can_paste_clipboard (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); + + if (midori_view_is_socket (view)) + return view->can_paste_clipboard; + else if (view->web_view) + { + view->can_paste_clipboard = webkit_web_view_can_paste_clipboard ( + WEBKIT_WEB_VIEW (view->web_view)); + return view->can_paste_clipboard; + } + return FALSE; +} + +/** + * midori_view_get_proxy_menu_item: + * @view: a #MidoriView + * + * Retrieves a proxy menu item that is typically added to a Window menu + * and which on activation switches to the right window/ tab. + * + * The item is created on the first call and will be updated to reflect + * changes to the icon and title automatically. + * + * The menu item is valid until it is removed from its container. + * + * Return value: the proxy #GtkMenuItem + **/ +GtkWidget* +midori_view_get_proxy_menu_item (MidoriView* view) +{ + const gchar* title; + + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + if (!view->menu_item) + { + title = midori_view_get_display_title (view); + view->menu_item = sokoke_image_menu_item_new_ellipsized (title); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (view->menu_item), + gtk_image_new_from_pixbuf (view->icon)); + + g_signal_connect (view->menu_item, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &view->menu_item); + } + return view->menu_item; +} + +static gboolean +midori_view_tab_label_button_release_event (GtkWidget* tab_label, + GdkEventButton* event, + GtkWidget* widget) +{ + if (event->button == 2) + { + /* Close the widget on middle click */ + gtk_widget_destroy (widget); + return TRUE; + } + + return FALSE; +} + +static void +midori_view_tab_icon_style_set (GtkWidget* tab_icon, + GtkStyle* previous_style) +{ + GtkSettings* gtk_settings; + gint width, height; + + gtk_settings = gtk_widget_get_settings (tab_icon); + gtk_icon_size_lookup_for_settings (gtk_settings, GTK_ICON_SIZE_MENU, + &width, &height); + gtk_widget_set_size_request (tab_icon, width + 2, height + 2); +} + +static void +midori_view_tab_close_clicked (GtkWidget* tab_close, + GtkWidget* widget) +{ + gtk_widget_destroy (widget); +} + +/** + * midori_view_get_proxy_tab_label: + * @view: a #MidoriView + * + * Retrieves a proxy tab label that is typically used when + * adding the view to a notebook. + * + * The label is created on the first call and will be updated to reflect + * changes of the loading progress and title. + * + * The label is valid until it is removed from its container. + * + * Return value: the proxy #GtkEventBox + **/ +GtkWidget* +midori_view_get_proxy_tab_label (MidoriView* view) +{ + GtkWidget* event_box; + GtkWidget* hbox; + GtkRcStyle* rcstyle; + GtkWidget* image; + + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + if (!view->tab_label) + { + view->tab_icon = katze_throbber_new (); + katze_throbber_set_static_pixbuf (KATZE_THROBBER (view->tab_icon), + midori_view_get_icon (view)); + + view->tab_title = gtk_label_new (midori_view_get_display_title (view)); + + event_box = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE); + hbox = gtk_hbox_new (FALSE, 1); + gtk_container_border_width (GTK_CONTAINER (hbox), 2); + gtk_container_add (GTK_CONTAINER (event_box), GTK_WIDGET (hbox)); + gtk_misc_set_alignment (GTK_MISC (view->tab_icon), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (hbox), view->tab_icon, FALSE, FALSE, 0); + gtk_misc_set_alignment (GTK_MISC (view->tab_title), 0.0, 0.5); + /* TODO: make the tab initially look "unvisited" until it's focused */ + gtk_box_pack_start (GTK_BOX (hbox), view->tab_title, FALSE, TRUE, 0); + if (view->settings) + _update_label_size (view->tab_title, + sokoke_object_get_int (view->settings, "tab-label-size")); + + view->tab_close = gtk_button_new (); + gtk_button_set_relief (GTK_BUTTON (view->tab_close), GTK_RELIEF_NONE); + gtk_button_set_focus_on_click (GTK_BUTTON (view->tab_close), FALSE); + rcstyle = gtk_rc_style_new (); + rcstyle->xthickness = rcstyle->ythickness = 0; + gtk_widget_modify_style (view->tab_close, rcstyle); + g_object_unref (rcstyle); + image = katze_throbber_new (); + katze_throbber_set_static_stock_id (KATZE_THROBBER (image), + GTK_STOCK_CLOSE); + gtk_button_set_image (GTK_BUTTON (view->tab_close), image); + gtk_misc_set_alignment (GTK_MISC (image), 0.0, 0.0); + gtk_box_pack_end (GTK_BOX (hbox), view->tab_close, FALSE, FALSE, 0); + gtk_widget_show_all (GTK_WIDGET (event_box)); + + if (view->settings && + !sokoke_object_get_boolean (view->settings, "close-buttons-on-tabs")) + gtk_widget_hide (view->tab_close); + + g_signal_connect (event_box, "button-release-event", + G_CALLBACK (midori_view_tab_label_button_release_event), view); + g_signal_connect (view->tab_close, "style-set", + G_CALLBACK (midori_view_tab_icon_style_set), NULL); + g_signal_connect (view->tab_close, "clicked", + G_CALLBACK (midori_view_tab_close_clicked), view); + + view->tab_label = event_box; + g_signal_connect (view->tab_label, "destroy", + G_CALLBACK (gtk_widget_destroyed), + &view->tab_label); + } + return view->tab_label; +} + +/** + * midori_view_get_proxy_item: + * @view: a #MidoriView + * + * Retrieves a proxy item that can be used for bookmark storage as + * well as session management. + * + * The item is created on the first call and will be updated to reflect + * changes to the title and uri automatically. + * + * Return value: the proxy #KatzeItem + **/ +KatzeItem* +midori_view_get_proxy_item (MidoriView* view) +{ + const gchar* uri; + const gchar* title; + + g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL); + + if (!view->item) + { + view->item = katze_item_new (); + uri = midori_view_get_display_uri (view); + katze_item_set_uri (view->item, uri); + title = midori_view_get_display_title (view); + katze_item_set_name (view->item, title); + } + return view->item; +} + +/** + * midori_view_get_zoom_level: + * @view: a #MidoriView + * + * Determines the current zoom level of the view. + * + * Return value: the current zoom level + **/ +gfloat +midori_view_get_zoom_level (MidoriView* view) +{ + g_return_val_if_fail (MIDORI_IS_VIEW (view), 1.0); + + if (midori_view_is_socket (view)) + return view->zoom_level; + else if (view->web_view) + return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW (view->web_view)); + return FALSE; +} + +/** + * midori_view_set_zoom_level: + * @view: a #MidoriView + * @zoom_level: the new zoom level + * + * Sets the current zoom level of the view. + **/ +void +midori_view_set_zoom_level (MidoriView* view, + gfloat zoom_level) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "set-zoom-level", float_to_str (zoom_level)); + else + webkit_web_view_set_zoom_level ( + WEBKIT_WEB_VIEW (view->web_view), zoom_level); +} + +#define can_do(what) \ +gboolean \ +midori_view_can_##what (MidoriView* view) \ +{ \ + g_return_val_if_fail (MIDORI_IS_VIEW (view), FALSE); \ +\ + return view->socket_id > -1; \ +} + +can_do (zoom_in) +can_do (zoom_out) +can_do (reload) +can_do (go_back) +can_do (go_forward) +can_do (print) +#if HAVE_GIO + can_do (view_source) +#else + gboolean midori_view_can_view_source (MidoriView* view) + { + return FALSE; + } +#endif +can_do (find) + +/** + * midori_view_reload: + * @view: a #MidoriView + * @from_cache: whether to allow caching + * + * Reloads the view. + * + * Note: The @from_cache value is currently ignored. + **/ +void +midori_view_reload (MidoriView* view, + gboolean from_cache) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "reload", int_to_str (from_cache)); + else + webkit_web_view_reload (WEBKIT_WEB_VIEW (view->web_view)); +} + +/** + * midori_view_stop_loading + * @view: a #MidoriView + * + * Stops loading the view if it is currently loading. + **/ +void +midori_view_stop_loading (MidoriView* view) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "stop-loading", NULL); + else + webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (view->web_view)); +} + +/** + * midori_view_go_back + * @view: a #MidoriView + * + * Goes back one page in the view. + **/ +void +midori_view_go_back (MidoriView* view) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "go-back", NULL); + else + webkit_web_view_go_back (WEBKIT_WEB_VIEW (view->web_view)); +} + +/** + * midori_view_go_forward + * @view: a #MidoriView + * + * Goes forward one page in the view. + **/ +void +midori_view_go_forward (MidoriView* view) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "go-forward", NULL); + else + webkit_web_view_go_forward (WEBKIT_WEB_VIEW (view->web_view)); +} + +/** + * midori_view_print + * @view: a #MidoriView + * + * Prints the contents of the view. + **/ +void +midori_view_print (MidoriView* view) +{ + g_return_if_fail (MIDORI_IS_VIEW (view)); + + if (midori_view_is_socket (view)) + send_command (view, "print", NULL); + else + webkit_web_view_execute_script ( + WEBKIT_WEB_VIEW (view->web_view), "print();"); +} diff --git a/midori/midori-view.h b/midori/midori-view.h new file mode 100644 index 00000000..96b5d22e --- /dev/null +++ b/midori/midori-view.h @@ -0,0 +1,161 @@ +/* + Copyright (C) 2008 Christian Dywan + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + See the file COPYING for the full license text. +*/ + +#ifndef __MIDORI_VIEW_H__ +#define __MIDORI_VIEW_H__ + +#include "midori-websettings.h" + +#include + +G_BEGIN_DECLS + +typedef enum +{ + MIDORI_LOAD_PROVISIONAL, + MIDORI_LOAD_COMMITTED, + MIDORI_LOAD_FINISHED +} MidoriLoadStatus; + +GType +midori_load_status_get_type (void) G_GNUC_CONST; + +#define MIDORI_TYPE_LOAD_STATUS \ + (midori_load_status_get_type ()) + +#define MIDORI_TYPE_VIEW \ + (midori_view_get_type ()) +#define MIDORI_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEW, MidoriView)) +#define MIDORI_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_VIEW, MidoriViewClass)) +#define MIDORI_IS_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_VIEW)) +#define MIDORI_IS_VIEW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_VIEW)) +#define MIDORI_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_VIEW, MidoriViewClass)) + +typedef struct _MidoriView MidoriView; +typedef struct _MidoriViewClass MidoriViewClass; + +GType +midori_view_get_type (void); + +GtkWidget* +midori_view_new (void); + +GtkWidget* +midori_view_new_with_uri (const gchar* uri); + +void +midori_view_set_settings (MidoriView* view, + MidoriWebSettings* settings); + +gdouble +midori_view_get_progress (MidoriView* view); + +MidoriLoadStatus +midori_view_get_load_status (MidoriView* view); + +void +midori_view_set_uri (MidoriView* view, + const gchar* uri); + +gboolean +midori_view_is_blank (MidoriView* view); + +const gchar* +midori_view_get_display_uri (MidoriView* view); + +const gchar* +midori_view_get_display_title (MidoriView* view); + +GdkPixbuf* +midori_view_get_icon (MidoriView* view); + +const gchar* +midori_view_get_link_uri (MidoriView* view); + +gboolean +midori_view_has_selection (MidoriView* view); + +const gchar* +midori_view_get_selected_text (MidoriView* view); + +gboolean +midori_view_can_cut_clipboard (MidoriView* view); + +gboolean +midori_view_can_copy_clipboard (MidoriView* view); + +gboolean +midori_view_can_paste_clipboard (MidoriView* view); + +GtkWidget* +midori_view_get_proxy_menu_item (MidoriView* view); + +GtkWidget* +midori_view_get_proxy_tab_label (MidoriView* view); + +KatzeItem* +midori_view_get_proxy_item (MidoriView* view); + +gfloat +midori_view_get_zoom_level (MidoriView* view); + +gboolean +midori_view_can_zoom_in (MidoriView* view); + +gboolean +midori_view_can_zoom_out (MidoriView* view); + +void +midori_view_set_zoom_level (MidoriView* view, + gfloat zoom_level); + +gboolean +midori_view_can_reload (MidoriView* view); + +void +midori_view_reload (MidoriView* view, + gboolean from_cache); + +void +midori_view_stop_loading (MidoriView* view); + +gboolean +midori_view_can_go_back (MidoriView* view); + +void +midori_view_go_back (MidoriView* view); + +gboolean +midori_view_can_go_forward (MidoriView* view); + +void +midori_view_go_forward (MidoriView* view); + +gboolean +midori_view_can_print (MidoriView* view); + +void +midori_view_print (MidoriView* view); + +gboolean +midori_view_can_view_source (MidoriView* view); + +gboolean +midori_view_can_find (MidoriView* view); + +G_END_DECLS + +#endif /* __MIDORI_VIEW_H__ */ diff --git a/midori/midori-webview.c b/midori/midori-webview.c deleted file mode 100644 index 754529b0..00000000 --- a/midori/midori-webview.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* - Copyright (C) 2007-2008 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#if HAVE_CONFIG_H - #include -#endif - -#include "midori-webview.h" -#include "midori-stock.h" - -#include "compat.h" -#include "sokoke.h" -#include "gjs.h" - -#include -#if HAVE_GIO - #include -#endif -#include -#include - -/* This is unstable API, so we need to declare it */ -gchar* -webkit_web_view_get_selected_text (WebKitWebView* web_view); - -struct _MidoriWebView -{ - WebKitWebView parent_instance; - gboolean window_object_cleared; - - GdkPixbuf* icon; - gchar* uri; - gchar* title; - gdouble progress; - MidoriLoadStatus load_status; - gchar* statusbar_text; - gchar* link_uri; - KatzeArray* news_feeds; - - MidoriWebSettings* settings; - - GtkWidget* menu_item; - GtkWidget* tab_icon; - GtkWidget* tab_title; - KatzeXbelItem* xbel_item; -}; - -G_DEFINE_TYPE (MidoriWebView, midori_web_view, WEBKIT_TYPE_WEB_VIEW) - -GType -midori_load_status_get_type (void) -{ - static GType type = 0; - if (!type) - { - static const GEnumValue values[] = { - { MIDORI_LOAD_PROVISIONAL, "MIDORI_LOAD_PROVISIONAL", N_("Load Provisional") }, - { MIDORI_LOAD_COMMITTED, "MIDORI_LOAD_COMMITTED", N_("Load Committed") }, - { MIDORI_LOAD_FINISHED, "MIDORI_LOAD_FINISHED", N_("Load Finished") }, - { 0, NULL, NULL } - }; - type = g_enum_register_static ("MidoriLoadStatus", values); - } - return type; -} - -enum -{ - PROP_0, - - PROP_URI, - PROP_TITLE, - PROP_PROGRESS, - PROP_MLOAD_STATUS, - PROP_STATUSBAR_TEXT, - PROP_SETTINGS -}; - -enum { - ICON_READY, - NEWS_FEED_READY, - ELEMENT_MOTION, - NEW_TAB, - NEW_WINDOW, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -static void -midori_web_view_finalize (GObject* object); - -static void -midori_web_view_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec); - -static void -midori_web_view_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec); - -static void -midori_cclosure_marshal_VOID__STRING_STRING_STRING (GClosure* closure, - GValue* return_value, - guint n_param_values, - const GValue* param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef void(*GMarshalFunc_VOID__STRING_STRING_STRING) (gpointer data1, - const gchar* arg_1, - const gchar* arg_2, - const gchar* arg_3, - gpointer data2); - register GMarshalFunc_VOID__STRING_STRING_STRING callback; - register GCClosure* cc = (GCClosure*) closure; - register gpointer data1, data2; - - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__STRING_STRING_STRING) (marshal_data - ? marshal_data : cc->callback); - callback (data1, - g_value_get_string (param_values + 1), - g_value_get_string (param_values + 2), - g_value_get_string (param_values + 3), - data2); -} - -static void -midori_web_view_class_init (MidoriWebViewClass* class) -{ - signals[ICON_READY] = g_signal_new ( - "icon-ready", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, icon_ready), - 0, - NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - GDK_TYPE_PIXBUF); - - signals[NEWS_FEED_READY] = g_signal_new ( - "news-feed-ready", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, news_feed_ready), - 0, - NULL, - midori_cclosure_marshal_VOID__STRING_STRING_STRING, - G_TYPE_NONE, 3, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - - signals[ELEMENT_MOTION] = g_signal_new ( - "element-motion", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), - G_STRUCT_OFFSET (MidoriWebViewClass, element_motion), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[NEW_TAB] = g_signal_new ( - "new-tab", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriWebViewClass, new_tab), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - signals[NEW_WINDOW] = g_signal_new ( - "new-window", - G_TYPE_FROM_CLASS (class), - (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), - G_STRUCT_OFFSET (MidoriWebViewClass, new_window), - 0, - NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - GObjectClass* gobject_class = G_OBJECT_CLASS (class); - gobject_class->finalize = midori_web_view_finalize; - gobject_class->set_property = midori_web_view_set_property; - gobject_class->get_property = midori_web_view_get_property; - - GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - - if (!g_object_class_find_property (gobject_class, "uri")) - g_object_class_install_property (gobject_class, - PROP_URI, - g_param_spec_string ( - "uri", - "Uri", - _("The URI of the currently loaded page"), - "", - flags)); - - if (!g_object_class_find_property (gobject_class, "title")) - g_object_class_install_property (gobject_class, - PROP_TITLE, - g_param_spec_string ( - "title", - "Title", - _("The title of the currently loaded page"), - NULL, - flags)); - - if (!g_object_class_find_property (gobject_class, "progress")) - g_object_class_install_property (gobject_class, - PROP_PROGRESS, - g_param_spec_double ( - "progress", - "Progress", - _("The current loading progress"), - 0.0, 1.0, 0.0, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_MLOAD_STATUS, - g_param_spec_enum ( - "mload-status", - "Load Status", - _("The current loading status"), - MIDORI_TYPE_LOAD_STATUS, - MIDORI_LOAD_FINISHED, - G_PARAM_READABLE)); - - if (!g_object_class_find_property (gobject_class, "statusbar-text")) - g_object_class_install_property (gobject_class, - PROP_STATUSBAR_TEXT, - g_param_spec_string ( - "statusbar-text", - "Statusbar Text", - _("The text that is displayed in the statusbar"), - "", - G_PARAM_READABLE)); - - g_object_class_override_property (gobject_class, - PROP_SETTINGS, - "settings"); -} - -static void -webkit_web_view_load_started (MidoriWebView* web_view, - WebKitWebFrame* web_frame) -{ - web_view->window_object_cleared = FALSE; - - web_view->load_status = MIDORI_LOAD_PROVISIONAL; - g_object_notify (G_OBJECT (web_view), "mload-status"); - if (web_view->tab_icon) - katze_throbber_set_animated (KATZE_THROBBER (web_view->tab_icon), TRUE); - - web_view->progress = 0.0; - g_object_notify (G_OBJECT (web_view), "progress"); -} - -static void -webkit_web_view_window_object_cleared_cb (MidoriWebView* web_view, - WebKitWebFrame* web_frame, - JSGlobalContextRef js_context, - JSObjectRef js_window) -{ - web_view->window_object_cleared = TRUE; -} - -#if HAVE_GIO -void -loadable_icon_finish_cb (GdkPixbuf* icon, - GAsyncResult* res, - MidoriWebView* web_view) -{ - GInputStream* stream; - GdkPixbuf* pixbuf; - GdkPixbuf* pixbuf_scaled; - gint icon_width, icon_height; - - pixbuf = NULL; - stream = g_loadable_icon_load_finish (G_LOADABLE_ICON (icon), - res, NULL, NULL); - if (stream) - { - pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); - g_object_unref (stream); - } - if (!pixbuf) - pixbuf = gtk_widget_render_icon (GTK_WIDGET (web_view), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); - - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); - pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, - GDK_INTERP_BILINEAR); - g_object_unref (pixbuf); - web_view->icon = pixbuf_scaled; - g_signal_emit (web_view, signals[ICON_READY], 0, web_view->icon); -} - -void -file_info_finish_cb (GFile* icon_file, - GAsyncResult* res, - MidoriWebView* web_view) -{ - GFileInfo* info; - const gchar* content_type; - GIcon* icon; - GFile* parent; - GFile* file; - GdkPixbuf* pixbuf; - gint icon_width, icon_height; - GdkPixbuf* pixbuf_scaled; - - info = g_file_query_info_finish (G_FILE (icon_file), res, NULL); - if (info) - { - content_type = g_file_info_get_content_type (info); - if (g_str_has_prefix (content_type, "image/")) - { - icon = g_file_icon_new (icon_file); - g_loadable_icon_load_async (G_LOADABLE_ICON (icon), - 0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, web_view); - return; - } - } - - file = g_file_get_parent (icon_file); - parent = g_file_get_parent (file); - /* We need to check if file equals the parent due to a GIO bug */ - if (parent && !g_file_equal (file, parent)) - { - icon_file = g_file_get_child (parent, "favicon.ico"); - g_file_query_info_async (icon_file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, 0, NULL, - (GAsyncReadyCallback)file_info_finish_cb, web_view); - return; - } - - pixbuf = gtk_widget_render_icon (GTK_WIDGET (web_view), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); - pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, - GDK_INTERP_BILINEAR); - g_object_unref (pixbuf); - - web_view->icon = pixbuf_scaled; - g_signal_emit (web_view, signals[ICON_READY], 0, web_view->icon); -} -#endif - -static void -_midori_web_view_load_icon (MidoriWebView* web_view) -{ - #if HAVE_GIO - GFile* file; - GFile* icon_file; - #endif - GdkPixbuf* pixbuf; - gint icon_width, icon_height; - GdkPixbuf* pixbuf_scaled; - - #if HAVE_GIO - if (web_view->uri) - { - file = g_file_new_for_uri (web_view->uri); - icon_file = g_file_get_child (file, "favicon.ico"); - g_file_query_info_async (icon_file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, 0, NULL, - (GAsyncReadyCallback)file_info_finish_cb, web_view); - return; - } - #endif - - pixbuf = gtk_widget_render_icon (GTK_WIDGET (web_view), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height); - pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height, - GDK_INTERP_BILINEAR); - g_object_unref (pixbuf); - - web_view->icon = pixbuf_scaled; - g_signal_emit (web_view, signals[ICON_READY], 0, web_view->icon); -} - -static void -webkit_web_view_load_committed (MidoriWebView* web_view, - WebKitWebFrame* web_frame) -{ - const gchar* uri; - GdkPixbuf* icon; - - uri = webkit_web_frame_get_uri (web_frame); - katze_assign (web_view->uri, g_strdup (uri)); - if (web_view->xbel_item) - { - uri = midori_web_view_get_display_uri (web_view); - katze_xbel_bookmark_set_href (web_view->xbel_item, uri); - } - g_object_notify (G_OBJECT (web_view), "uri"); - g_object_set (web_view, "title", NULL, NULL); - - icon = gtk_widget_render_icon (GTK_WIDGET (web_view), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); - katze_object_assign (web_view->icon, icon); - _midori_web_view_load_icon (web_view); - - if (web_view->tab_icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), - icon); - - if (web_view->menu_item) - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (web_view->menu_item), - gtk_image_new_from_pixbuf (icon)); - - web_view->load_status = MIDORI_LOAD_COMMITTED; - g_object_notify (G_OBJECT (web_view), "mload-status"); -} - -static void -webkit_web_view_icon_ready (MidoriWebView* web_view, - GdkPixbuf* icon) -{ - if (web_view->tab_icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), - icon); - if (web_view->menu_item) - gtk_image_menu_item_set_image ( - GTK_IMAGE_MENU_ITEM (web_view->menu_item), - gtk_image_new_from_pixbuf (icon)); -} - -static void -webkit_web_view_progress_changed (MidoriWebView* web_view, gint progress) -{ - web_view->progress = progress ? progress / 100.0 : 0.0; - g_object_notify (G_OBJECT (web_view), "progress"); -} - -static void -gjs_value_links_foreach_cb (GjsValue* link, - MidoriWebView* web_view) -{ - const gchar* type; -#if HAVE_GIO - const gchar* rel; - GFile* icon_file; - GIcon* icon; -#endif - - if (gjs_value_is_object (link) && gjs_value_has_attribute (link, "href")) - { - if (gjs_value_has_attribute (link, "type")) - { - type = gjs_value_get_attribute_string (link, "type"); - if (!strcmp (type, "application/rss+xml") - || !strcmp (type, "application/x.atom+xml") - || !strcmp (type, "application/atom+xml")) - { - katze_array_add_item (web_view->news_feeds, link); - g_signal_emit (web_view, signals[NEWS_FEED_READY], 0, - gjs_value_get_attribute_string (link, "href"), type, - gjs_value_has_attribute (link, "title") - ? gjs_value_get_attribute_string (link, "title") : NULL); - } - } -#if HAVE_GIO - if (gjs_value_has_attribute (link, "rel")) - { - rel = gjs_value_get_attribute_string (link, "rel"); - if (!strcmp (rel, "icon") || !strcmp (rel, "shortcut icon")) - { - icon_file = g_file_new_for_uri ( - gjs_value_get_attribute_string (link, "href")); - icon = g_file_icon_new (icon_file); - g_loadable_icon_load_async (G_LOADABLE_ICON (icon), - 0, NULL, (GAsyncReadyCallback)loadable_icon_finish_cb, web_view); - } - } -#endif - } -} - -static void -webkit_web_frame_load_done (WebKitWebFrame* web_frame, - gboolean success, - MidoriWebView* web_view) -{ - JSContextRef js_context; - JSValueRef js_window; - GjsValue* value; - GjsValue* document; - GjsValue* links; - - /* If WebKit didn't emit the signal due to a bug, we will */ - if (!web_view->window_object_cleared) - { - js_context = webkit_web_frame_get_global_context (web_frame); - js_window = JSContextGetGlobalObject (js_context); - g_signal_emit_by_name (web_view, "window-object-cleared", - web_frame, js_context, js_window); - } - - value = gjs_value_new (webkit_web_frame_get_global_context (web_frame), NULL); - document = gjs_value_get_by_name (value, "document"); - links = gjs_value_get_elements_by_tag_name (document, "link"); - katze_array_clear (web_view->news_feeds); - gjs_value_foreach (links, (GjsCallback)gjs_value_links_foreach_cb, web_view); - g_object_unref (links); - g_object_unref (document); - g_object_unref (value); - - if (web_view->tab_icon) - katze_throbber_set_animated (KATZE_THROBBER (web_view->tab_icon), - FALSE); - web_view->load_status = MIDORI_LOAD_FINISHED; - g_object_notify (G_OBJECT (web_view), "mload-status"); -} - -static void -webkit_web_view_load_finished (MidoriWebView* web_view) -{ - web_view->progress = 1.0; - g_object_notify (G_OBJECT (web_view), "progress"); -} - -static void -webkit_web_view_title_changed (MidoriWebView* web_view, - WebKitWebFrame* web_frame, const gchar* title) -{ - g_object_set (web_view, "title", title, NULL); -} - -static void -webkit_web_view_statusbar_text_changed (MidoriWebView* web_view, - const gchar* text) -{ - katze_assign (web_view->statusbar_text, g_strdup (text)); - g_object_notify (G_OBJECT (web_view), "statusbar-text"); -} - -static void -webkit_web_view_hovering_over_link (MidoriWebView* web_view, - const gchar* tooltip, - const gchar* link_uri) -{ - katze_assign (web_view->link_uri, g_strdup (link_uri)); - g_signal_emit (web_view, signals[ELEMENT_MOTION], 0, link_uri); -} - -static gboolean -gtk_widget_button_press_event_after (MidoriWebView* web_view, - GdkEventButton* event) -{ - GdkModifierType state; - GtkClipboard* clipboard; - gchar* uri; - gchar* new_uri; - - if (event->button == 2 && sokoke_object_get_boolean - (web_view->settings, "middle-click-opens-selection")) - { - state = (GdkModifierType) event->state; - clipboard = gtk_clipboard_get_for_display ( - gtk_widget_get_display (GTK_WIDGET (web_view)), - GDK_SELECTION_PRIMARY); - uri = gtk_clipboard_wait_for_text (clipboard); - if (uri && strchr (uri, '.') && !strchr (uri, ' ')) - { - new_uri = sokoke_magic_uri (uri, NULL); - if (state & GDK_CONTROL_MASK) - g_signal_emit (web_view, signals[NEW_TAB], 0, new_uri); - else - { - g_object_set (web_view, "uri", new_uri, NULL); - gtk_widget_grab_focus (GTK_WIDGET (web_view)); - } - g_free (new_uri); - g_free (uri); - return TRUE; - } - } - return FALSE; -} - -static gboolean -gtk_widget_button_release_event (MidoriWebView* web_view, - GdkEventButton* event) -{ - GtkClipboard* clipboard; - gchar* text; - - /* Emulate the primary clipboard, which WebKit doesn't support */ - text = webkit_web_view_get_selected_text (WEBKIT_WEB_VIEW (web_view)); - clipboard = gtk_clipboard_get_for_display ( - gtk_widget_get_display (GTK_WIDGET (web_view)), GDK_SELECTION_PRIMARY); - gtk_clipboard_set_text (clipboard, text, -1); - g_free (text); - return FALSE; -} - -static gboolean -gtk_widget_scroll_event (MidoriWebView* web_view, - GdkEventScroll* event) -{ - GdkModifierType state = (GdkModifierType)0; - gint x, y; - - gdk_window_get_pointer (NULL, &x, &y, &state); - if (state & GDK_CONTROL_MASK) - { - if (event->direction == GDK_SCROLL_DOWN) - webkit_web_view_zoom_out (WEBKIT_WEB_VIEW (web_view)); - else if(event->direction == GDK_SCROLL_UP) - webkit_web_view_zoom_in (WEBKIT_WEB_VIEW (web_view)); - return TRUE; - } - else - return FALSE; -} - -static void -midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget, - MidoriWebView* web_view) -{ - const gchar* uri = g_object_get_data (G_OBJECT (widget), "uri"); - g_signal_emit (web_view, signals[NEW_TAB], 0, uri); -} - -static void -midori_web_view_menu_new_window_activate_cb (GtkWidget* widget, - MidoriWebView* web_view) -{ - const gchar* uri = g_object_get_data (G_OBJECT (widget), "uri"); - g_signal_emit (web_view, signals[NEW_WINDOW], 0, uri); -} - -static void -midori_web_view_menu_download_activate_cb (GtkWidget* widget, - MidoriWebView* web_view) -{ - gchar* program; - const gchar* uri; - - g_object_get (web_view->settings, "download-manager", &program, NULL); - uri = g_object_get_data (G_OBJECT (widget), "uri"); - sokoke_spawn_program (program, uri); - g_free (program); -} - -static void -webkit_web_view_populate_popup_cb (GtkWidget* web_view, - GtkWidget* menu) -{ - const gchar* uri; - GtkWidget* menuitem; - GdkScreen* screen; - GtkIconTheme* icon_theme; - GtkWidget* icon; - gchar* text; - GList* items; - gchar* program; - - uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view)); - if (uri) - { - menuitem = gtk_image_menu_item_new_with_mnemonic ( - _("Open Link in New _Tab")); - screen = gtk_widget_get_screen (web_view); - icon_theme = gtk_icon_theme_get_for_screen (screen); - if (gtk_icon_theme_has_icon (icon_theme, STOCK_TAB_NEW)) - { - icon = gtk_image_new_from_stock (STOCK_TAB_NEW, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - } - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 1); - g_object_set_data (G_OBJECT (menuitem), "uri", (gchar*)uri); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); - gtk_widget_show (menuitem); - /* hack to implement New Window */ - items = gtk_container_get_children (GTK_CONTAINER (menu)); - menuitem = (GtkWidget*)g_list_nth_data (items, 2); - g_object_set_data (G_OBJECT (menuitem), "uri", (gchar*)uri); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_new_window_activate_cb), web_view); - menuitem = (GtkWidget*)g_list_nth_data (items, 3); - /* hack to disable non-functional Download File */ - gtk_widget_set_sensitive (menuitem, FALSE); - g_list_free (items); - g_object_get (MIDORI_WEB_VIEW (web_view)->settings, - "download-manager", &program, NULL); - if (program && *program) - { - menuitem = gtk_image_menu_item_new_with_mnemonic ( - _("Download Link with Download _Manager")); - icon = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 4); - g_object_set_data (G_OBJECT (menuitem), "uri", (gchar*)uri); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_download_activate_cb), web_view); - gtk_widget_show (menuitem); - } - } - - if (!uri && midori_web_view_has_selection (MIDORI_WEB_VIEW (web_view))) - { - text = webkit_web_view_get_selected_text (WEBKIT_WEB_VIEW (web_view)); - if (text && strchr (text, '.') && !strchr (text, ' ')) - { - menuitem = gtk_image_menu_item_new_with_mnemonic ( - _("Open URL in New _Tab")); - icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon); - gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1); - g_object_set_data (G_OBJECT (menuitem), "uri", text); - g_signal_connect (menuitem, "activate", - G_CALLBACK (midori_web_view_menu_new_tab_activate_cb), web_view); - gtk_widget_show (menuitem); - } - /* text should be const, but it is allocated, so we must free it */ - g_free (text); - } -} - -static void -midori_web_view_init (MidoriWebView* web_view) -{ - web_view->icon = gtk_widget_render_icon (GTK_WIDGET (web_view), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); - web_view->progress = 0.0; - web_view->load_status = MIDORI_LOAD_FINISHED; - web_view->news_feeds = katze_array_new (GJS_TYPE_VALUE); - - web_view->settings = midori_web_settings_new (); - g_object_set (web_view, "WebKitWebView::settings", web_view->settings, NULL); - - WebKitWebFrame* web_frame; - web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)); - - g_object_connect (web_view, - "signal::load-started", - webkit_web_view_load_started, NULL, - "signal::window-object-cleared", - webkit_web_view_window_object_cleared_cb, NULL, - "signal::load-committed", - webkit_web_view_load_committed, NULL, - "signal::icon-ready", - webkit_web_view_icon_ready, NULL, - "signal::load-progress-changed", - webkit_web_view_progress_changed, NULL, - "signal::load-finished", - webkit_web_view_load_finished, NULL, - "signal::title-changed", - webkit_web_view_title_changed, NULL, - "signal::status-bar-text-changed", - webkit_web_view_statusbar_text_changed, NULL, - "signal::hovering-over-link", - webkit_web_view_hovering_over_link, NULL, - "signal::button-press-event", - gtk_widget_button_press_event_after, NULL, - "signal::button-release-event", - gtk_widget_button_release_event, NULL, - "signal::scroll-event", - gtk_widget_scroll_event, NULL, - "signal::populate-popup", - webkit_web_view_populate_popup_cb, NULL, - NULL); - g_object_connect (web_frame, - "signal::load-done", - webkit_web_frame_load_done, web_view, - NULL); -} - -static void -midori_web_view_finalize (GObject* object) -{ - MidoriWebView* web_view; - WebKitWebFrame* web_frame; - - web_view = MIDORI_WEB_VIEW (object); - - if (web_view->icon) - g_object_unref (web_view->icon); - g_free (web_view->uri); - g_free (web_view->title); - g_free (web_view->statusbar_text); - g_free (web_view->link_uri); - g_object_unref (web_view->news_feeds); - - if (web_view->settings) - g_object_unref (web_view->settings); - - if (web_view->xbel_item) - katze_xbel_item_unref (web_view->xbel_item); - - web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view)); - g_signal_handlers_disconnect_by_func (web_frame, - webkit_web_frame_load_done, web_view); - - G_OBJECT_CLASS (midori_web_view_parent_class)->finalize (object); -} - -static void -midori_web_view_set_property (GObject* object, - guint prop_id, - const GValue* value, - GParamSpec* pspec) -{ - MidoriWebView* web_view = MIDORI_WEB_VIEW (object); - - switch (prop_id) - { - case PROP_URI: - { - const gchar* uri = g_value_get_string (value); - if (uri && *uri) - webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), uri); - break; - } - case PROP_TITLE: - katze_assign (web_view->title, g_value_dup_string (value)); - const gchar* title = midori_web_view_get_display_title (web_view); - if (web_view->tab_title) - { - gtk_label_set_text (GTK_LABEL (web_view->tab_title), title); - gtk_widget_set_tooltip_text (web_view->tab_title, title); - } - if (web_view->menu_item) - gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN ( - web_view->menu_item))), title); - if (web_view->xbel_item) - katze_xbel_item_set_title (web_view->xbel_item, title); - break; - case PROP_SETTINGS: - katze_object_assign (web_view->settings, g_value_get_object (value)); - g_object_ref (web_view->settings); - g_object_set (object, "WebKitWebView::settings", web_view->settings, NULL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -midori_web_view_get_property (GObject* object, - guint prop_id, - GValue* value, - GParamSpec* pspec) -{ - MidoriWebView* web_view = MIDORI_WEB_VIEW (object); - - switch (prop_id) - { - case PROP_URI: - g_value_set_string (value, web_view->uri); - break; - case PROP_TITLE: - g_value_set_string (value, web_view->title); - break; - case PROP_PROGRESS: - g_value_set_double (value, web_view->progress); - break; - case PROP_MLOAD_STATUS: - g_value_set_enum (value, web_view->load_status); - break; - case PROP_STATUSBAR_TEXT: - g_value_set_string (value, web_view->statusbar_text); - break; - case PROP_SETTINGS: - g_value_set_object (value, web_view->settings); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * midori_web_view_new: - * - * Creates a new web view widget. - * - * Return value: a new #MidoriWebView - **/ -GtkWidget* -midori_web_view_new (void) -{ - MidoriWebView* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW, - NULL); - - return GTK_WIDGET (web_view); -} - -/** - * midori_web_view_set_settings: - * @web_view: a #MidoriWebView - * @web_settings: a #MidoriWebSettings - * - * Assigns a settings instance to the web view. - **/ -void -midori_web_view_set_settings (MidoriWebView* web_view, - MidoriWebSettings* web_settings) -{ - g_object_set (web_view, "settings", web_settings, NULL); -} - -/** - * midori_web_view_get_proxy_menu_item: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy menu item that is typically added to a Window menu - * and which on activation switches to the right window/ tab. - * - * The item is created on the first call and will be updated to reflect - * changes to the icon and title automatically. - * - * Note: The item is only valid as the web view is embedded in a #GtkNotebook. - * - * Return value: the proxy #GtkMenuItem or %NULL - **/ -GtkWidget* -midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) -{ - const gchar* title; - - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); - - if (!web_view->menu_item) - { - title = midori_web_view_get_display_title (web_view); - web_view->menu_item = sokoke_image_menu_item_new_ellipsized (title); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (web_view->menu_item), - gtk_image_new_from_pixbuf (web_view->icon)); - - g_signal_connect (web_view->menu_item, "destroy", - G_CALLBACK (gtk_widget_destroyed), - &web_view->menu_item); - } - return web_view->menu_item; -} - -/** - * midori_web_view_get_proxy_tab_icon: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy tab icon that is typically used in a tab label. - * - * The icon is created on the first call and will be updated to reflect - * loading progress and changes of the actual icon. - * - * Note: If a proxy tab label has been created before, this represents - * the existing icon used in the label. - * - * Return value: the proxy #GtkImage - **/ -GtkWidget* -midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - if (!web_view->tab_icon) - { - web_view->tab_icon = katze_throbber_new (); - katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), - web_view->icon); - - g_signal_connect (web_view->tab_icon, "destroy", - G_CALLBACK (gtk_widget_destroyed), - &web_view->tab_icon); - } - return web_view->tab_icon; -} - -/** - * midori_web_view_get_proxy_tab_title: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy tab title that is typically used as the label - * of a #GtkNotebook page. - * - * The title is created on the first call and will be updated to - * reflect changes automatically. - * - * Return value: the proxy #GtkLabel - **/ -GtkWidget* -midori_web_view_get_proxy_tab_title (MidoriWebView* web_view) -{ - const gchar* title; - - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - if (!web_view->tab_title) - { - title = midori_web_view_get_display_title (web_view); - web_view->tab_title = gtk_label_new (title); - - g_signal_connect (web_view->tab_title, "destroy", - G_CALLBACK (gtk_widget_destroyed), - &web_view->tab_title); - } - return web_view->tab_title; -} - -/** - * midori_web_view_get_proxy_xbel_item: - * @web_view: a #MidoriWebView - * - * Retrieves a proxy xbel item that can be used for bookmark storage as - * well as session management. - * - * The item is created on the first call and will be updated to reflect - * changes to the title and href automatically. - * - * Note: Currently the item is always a bookmark, but this might change - * in the future. - * - * Return value: the proxy #KatzeXbelItem - **/ -KatzeXbelItem* -midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view) -{ - const gchar* uri; - const gchar* title; - - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - if (!web_view->xbel_item) - { - web_view->xbel_item = katze_xbel_bookmark_new (); - uri = midori_web_view_get_display_uri (web_view); - katze_xbel_bookmark_set_href (web_view->xbel_item, uri); - title = midori_web_view_get_display_title (web_view); - katze_xbel_item_set_title (web_view->xbel_item, title); - } - return web_view->xbel_item; -} - -/** - * midori_web_view_load_status: - * @web_view: a #MidoriWebView - * - * Determines the current loading status of a page. - * - * Return value: the current #MidoriLoadStatus - **/ -MidoriLoadStatus -midori_web_view_get_load_status (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), MIDORI_LOAD_FINISHED); - - return web_view->load_status; -} - -/** - * midori_web_view_get_progress: - * @web_view: a #MidoriWebView - * - * Retrieves the current loading progress as - * a fraction between 0.0 and 1.0. - * - * Return value: the current loading progress - **/ -gdouble -midori_web_view_get_progress (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), 0.0); - - return web_view->progress; -} - -/** - * midori_web_view_get_display_uri: - * @web_view: a #MidoriWebView - * - * Retrieves a string that is suitable for displaying, particularly an - * empty URI is represented as "". - * - * You can assume that the string is not %NULL. - * - * Return value: an URI string - **/ -const gchar* -midori_web_view_get_display_uri (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), ""); - - return web_view->uri ? web_view->uri : ""; -} - -/** - * midori_web_view_get_display_title: - * @web_view: a #MidoriWebView - * - * Retrieves a string that is suitable for displaying as a title. Most of the - * time this will be the title or the current URI. - * - * You can assume that the string is not %NULL. - * - * Return value: a title string - **/ -const gchar* -midori_web_view_get_display_title (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), "about:blank"); - - if (web_view->title) - return web_view->title; - if (web_view->uri) - return web_view->uri; - return "about:blank"; -} - -/** - * midori_web_view_get_link_uri: - * @web_view: a #MidoriWebView - * - * Retrieves the uri of the currently focused link, particularly while the - * mouse hovers a link or a context menu is being opened. - * - * Return value: an URI string, or %NULL if there is no link focussed - **/ -const gchar* -midori_web_view_get_link_uri (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - return web_view->link_uri; -} - -/** - * midori_web_view_get_news_feeds: - * @web_view: a #MidoriWebView - * - * Retrieves a list of news feeds for the current page - * or %NULL if there are no feeds at all. - * - * Return value: a #KatzeArray, or %NULL - **/ -KatzeArray* -midori_web_view_get_news_feeds (MidoriWebView* web_view) -{ - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); - - if (!katze_array_is_empty (web_view->news_feeds)) - return web_view->news_feeds; - return NULL; -} - -/** - * midori_web_view_has_selection: - * @web_view: a #MidoriWebView - * - * Determines whether something on the page is selected. - * - * By contrast to webkit_web_view_has_selection() this - * returns %FALSE if there is a selection that - * effectively only consists of whitespace. - * - * Return value: %TRUE if effectively there is a selection - **/ -gboolean -midori_web_view_has_selection (MidoriWebView* web_view) -{ - gchar* text; - - g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); - - text = webkit_web_view_get_selected_text (WEBKIT_WEB_VIEW (web_view)); - if (text && *text) - { - g_free (text); - return TRUE; - } - g_free (text); - return FALSE; -} diff --git a/midori/midori-webview.h b/midori/midori-webview.h deleted file mode 100644 index 8773c1e4..00000000 --- a/midori/midori-webview.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - Copyright (C) 2008 Christian Dywan - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - See the file COPYING for the full license text. -*/ - -#ifndef __MIDORI_WEB_VIEW_H__ -#define __MIDORI_WEB_VIEW_H__ - -#include "midori-websettings.h" - -#include -#include - -G_BEGIN_DECLS - -#define MIDORI_TYPE_WEB_VIEW \ - (midori_web_view_get_type ()) -#define MIDORI_WEB_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebView)) -#define MIDORI_WEB_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) -#define MIDORI_IS_WEB_VIEW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_VIEW)) -#define MIDORI_IS_WEB_VIEW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_VIEW)) -#define MIDORI_WEB_VIEW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_VIEW, MidoriWebViewClass)) - -typedef struct _MidoriWebView MidoriWebView; -typedef struct _MidoriWebViewClass MidoriWebViewClass; - -struct _MidoriWebViewClass -{ - WebKitWebViewClass parent_class; - - /* Signals */ - void - (*icon_ready) (MidoriWebView* web_view, - GdkPixbuf* icon); - void - (*news_feed_ready) (MidoriWebView* web_view, - const gchar* href, - const gchar* type, - const gchar* title); - void - (*load_done) (MidoriWebView* web_view, - WebKitWebFrame* frame); - void - (*element_motion) (MidoriWebView* web_view, - const gchar* link_uri); - void - (*close) (MidoriWebView* web_view); - void - (*new_tab) (MidoriWebView* web_view, - const gchar* uri); - void - (*new_window) (MidoriWebView* web_view, - const gchar* uri); -}; - -typedef enum -{ - MIDORI_LOAD_PROVISIONAL, - MIDORI_LOAD_COMMITTED, - MIDORI_LOAD_FINISHED -} MidoriLoadStatus; - -GType -midori_load_status_get_type (void) G_GNUC_CONST; - -#define MIDORI_TYPE_LOAD_STATUS \ - (midori_load_status_get_type ()) - -GType -midori_web_view_get_type (void); - -GtkWidget* -midori_web_view_new (void); - -void -midori_web_view_set_settings (MidoriWebView* web_view, - MidoriWebSettings* web_settings); - -GtkWidget* -midori_web_view_get_proxy_menu_item (MidoriWebView* web_view); - -GtkWidget* -midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view); - -GtkWidget* -midori_web_view_get_proxy_tab_title (MidoriWebView* web_view); - -KatzeXbelItem* -midori_web_view_get_proxy_xbel_item (MidoriWebView* web_view); - -gdouble -midori_web_view_get_progress (MidoriWebView* web_view); - -MidoriLoadStatus -midori_web_view_get_load_status (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_display_uri (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_display_title (MidoriWebView* web_view); - -const gchar* -midori_web_view_get_link_uri (MidoriWebView* web_view); - -KatzeArray* -midori_web_view_get_news_feeds (MidoriWebView* web_view); - -gboolean -midori_web_view_has_selection (MidoriWebView* web_view); - -G_END_DECLS - -#endif /* __MIDORI_WEB_VIEW_H__ */ diff --git a/midori/sokoke.c b/midori/sokoke.c index 9af538b5..4efd01c8 100644 --- a/midori/sokoke.c +++ b/midori/sokoke.c @@ -24,6 +24,32 @@ #include #include +/** + * sokoke_remember_argv0: + * @argv0: the contents of argv[0] or %NULL + * + * Stores or retrieves the value of argv[0]. + * + * Call it with a string for argv0 to store. + * + * Passing %NULL for argv0 will preserve + * a previously stored value. + * + * Return value: the contents of argv[0] or %NULL + **/ +const gchar* +sokoke_remember_argv0 (const gchar* argv0) +{ + static const gchar* remembered_argv0 = NULL; + + if (argv0) + remembered_argv0 = argv0; + + g_return_val_if_fail (remembered_argv0 != NULL, NULL); + + return remembered_argv0; +} + static void error_dialog (const gchar* short_message, const gchar* detailed_message) @@ -260,9 +286,10 @@ sokoke_widget_popup (GtkWidget* widget, event_time = gtk_get_current_event_time (); } - if (!gtk_menu_get_attach_widget(menu)) + if (!gtk_menu_get_attach_widget (menu)) gtk_menu_attach_to_widget (menu, widget, NULL); + if (widget) { SokokePopupInfo info = { widget, pos }; @@ -350,7 +377,7 @@ sokoke_superuser_warning_new (void) gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL, >K_WIDGET (label)->style->fg[GTK_STATE_SELECTED]); gtk_widget_show (label); - gtk_container_add (GTK_CONTAINER(hbox), GTK_WIDGET (label)); + gtk_container_add (GTK_CONTAINER (hbox), GTK_WIDGET (label)); gtk_widget_show (hbox); return hbox; } @@ -399,7 +426,7 @@ sokoke_on_entry_focus_in_event (GtkEntry* entry, if (has_default) { gtk_entry_set_text (entry, ""); - g_object_set_data (G_OBJECT(entry), "sokoke_has_default", + g_object_set_data (G_OBJECT (entry), "sokoke_has_default", GINT_TO_POINTER (0)); sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), PANGO_STYLE_NORMAL); @@ -418,7 +445,7 @@ sokoke_on_entry_focus_out_event (GtkEntry* entry, const gchar* default_text = (const gchar*)g_object_get_data ( G_OBJECT (entry), "sokoke_default_text"); gtk_entry_set_text (entry, default_text); - g_object_set_data (G_OBJECT(entry), + g_object_set_data (G_OBJECT (entry), "sokoke_has_default", GINT_TO_POINTER (1)); sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), PANGO_STYLE_ITALIC); diff --git a/midori/sokoke.h b/midori/sokoke.h index c40ba2bd..46edc48e 100644 --- a/midori/sokoke.h +++ b/midori/sokoke.h @@ -19,6 +19,9 @@ /* Many themes need this hack for small toolbars to work */ #define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON +const gchar* +sokoke_remember_argv0 (const gchar* argv0); + gboolean sokoke_spawn_program (const gchar* command, const gchar* argument);