From e6eaab55a12a828a81762647d585b70f05bc43fd Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Sun, 6 Jul 2008 16:12:27 +0200 Subject: [PATCH] Basic favicon support through GIO --- midori/compat.c | 85 ++++++++++++++++++++++++++- midori/compat.h | 13 +++++ midori/midori-browser.c | 19 ++++-- midori/midori-webview.c | 126 ++++++++++++++++++++++++++++------------ midori/midori-webview.h | 3 + 5 files changed, 203 insertions(+), 43 deletions(-) diff --git a/midori/compat.c b/midori/compat.c index 4f8a7401..5bd73b70 100644 --- a/midori/compat.c +++ b/midori/compat.c @@ -11,10 +11,93 @@ #include "compat.h" +#if !GTK_CHECK_VERSION(2, 14, 0) + +#if GLIB_CHECK_VERSION(2, 16, 0) + +/* GTK+/ GdkPixbuf internal helper function + Copyright (C) 2008 Matthias Clasen + Copied from Gtk+ 2.13, coding style adjusted */ + +static GdkPixbuf* +load_from_stream (GdkPixbufLoader* loader, + GInputStream* stream, + GCancellable* cancellable, + GError** error) +{ + GdkPixbuf* pixbuf; + gssize n_read; + guchar buffer[65536]; + gboolean res; + + res = TRUE; + while (1) + { + n_read = g_input_stream_read (stream, buffer, sizeof (buffer), + cancellable, error); + if (n_read < 0) + { + res = FALSE; + error = NULL; /* Ignore further errors */ + break; + } + + if (!n_read) + break; + + if (!gdk_pixbuf_loader_write (loader, buffer, n_read, + error)) + { + res = FALSE; + error = NULL; + break; + } + } + + if (!gdk_pixbuf_loader_close (loader, error)) + { + res = FALSE; + error = NULL; + } + + pixbuf = NULL; + if (res) + { + pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); + if (pixbuf) + g_object_ref (pixbuf); + } + + return pixbuf; +} + +/* GTK+/ GdkPixbuf stream loading function + Copyright (C) 2008 Matthias Clasen + Copied from Gtk+ 2.13, coding style adjusted */ +GdkPixbuf* +gdk_pixbuf_new_from_stream (GInputStream* stream, + GCancellable* cancellable, + GError** error) +{ + GdkPixbuf* pixbuf; + GdkPixbufLoader* loader; + + loader = gdk_pixbuf_loader_new (); + pixbuf = load_from_stream (loader, stream, cancellable, error); + g_object_unref (loader); + + return pixbuf; +} + +#endif + +#endif + #if !GTK_CHECK_VERSION(2, 12, 0) void -gtk_widget_set_tooltip_text (GtkWidget* widget, const gchar* text) +gtk_widget_set_tooltip_text (GtkWidget* widget, + const gchar* text) { static GtkTooltips* tooltips; if (!tooltips) diff --git a/midori/compat.h b/midori/compat.h index c0818d8c..de818e8a 100644 --- a/midori/compat.h +++ b/midori/compat.h @@ -12,10 +12,23 @@ #ifndef __COMPAT_H__ #define __COMPAT_H__ +#include "glib.h" +#if GLIB_CHECK_VERSION(2, 16, 0) +#include +#endif #include G_BEGIN_DECLS +#if !GTK_CHECK_VERSION(2, 14, 0) + +GdkPixbuf* +gdk_pixbuf_new_from_stream (GInputStream* stream, + GCancellable* cancellable, + GError** error); + +#endif + #if !GTK_CHECK_VERSION(2, 12, 0) void diff --git a/midori/midori-browser.c b/midori/midori-browser.c index a0e09573..265d297f 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -165,8 +165,12 @@ _midori_browser_update_actions (MidoriBrowser* browser) static void _midori_browser_update_interface (MidoriBrowser* browser) { - gboolean loading = FALSE; - GtkWidget* web_view = midori_browser_get_current_web_view (browser); + gboolean loading; + GtkWidget* web_view; + GdkPixbuf* pixbuf; + + loading = FALSE; + web_view = midori_browser_get_current_web_view (browser); if (web_view) { loading = midori_web_view_is_loading (MIDORI_WEB_VIEW (web_view)); @@ -202,8 +206,15 @@ _midori_browser_update_interface (MidoriBrowser* browser) gtk_widget_show (browser->progressbar); } katze_throbber_set_animated (KATZE_THROBBER (browser->throbber), loading); - gtk_image_set_from_stock (GTK_IMAGE (browser->location_icon), - GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); + if (web_view && MIDORI_IS_WEB_VIEW (web_view)) + { + pixbuf = midori_web_view_get_icon (MIDORI_WEB_VIEW (web_view)); + gtk_image_set_from_pixbuf (GTK_IMAGE (browser->location_icon), pixbuf); + g_object_unref (pixbuf); + } + else + gtk_image_set_from_stock (GTK_IMAGE (browser->location_icon), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU); } static GtkWidget* diff --git a/midori/midori-webview.c b/midori/midori-webview.c index 0570a291..2733bdb8 100644 --- a/midori/midori-webview.c +++ b/midori/midori-webview.c @@ -15,6 +15,9 @@ #include "sokoke.h" #include "compat.h" +#if GLIB_CHECK_VERSION (2, 16, 0) +#include +#endif #include #include @@ -29,7 +32,6 @@ struct _MidoriWebView GtkWidget* tab_icon; GtkWidget* tab_label; GtkWidget* tab_close; - GdkPixbuf* icon; gchar* uri; gchar* title; gboolean is_loading; @@ -53,7 +55,6 @@ enum { PROP_0, - PROP_ICON, PROP_URI, PROP_TITLE, PROP_STATUSBAR_TEXT, @@ -173,7 +174,7 @@ midori_web_view_class_init (MidoriWebViewClass* class) signals[NEW_WINDOW] = g_signal_new( "new-window", G_TYPE_FROM_CLASS(class), - (GSignalFlags)(G_SIGNAL_RUN_LAST), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), G_STRUCT_OFFSET (MidoriWebViewClass, new_window), 0, NULL, @@ -188,15 +189,6 @@ midori_web_view_class_init (MidoriWebViewClass* class) GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT; - g_object_class_install_property (gobject_class, - PROP_ICON, - g_param_spec_object ( - "icon", - "Icon", - _("The icon of the currently loaded page"), - GDK_TYPE_PIXBUF, - G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_URI, g_param_spec_string ( @@ -255,9 +247,16 @@ static void webkit_web_view_load_committed (MidoriWebView* web_view, WebKitWebFrame* web_frame) { + const gchar* uri; + GdkPixbuf* icon; + web_view->progress = 0; - const gchar* uri = webkit_web_frame_get_uri (web_frame); + uri = webkit_web_frame_get_uri (web_frame); _midori_web_view_set_uri (web_view, uri); + icon = midori_web_view_get_icon (web_view); + katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), + icon); + g_object_unref (icon); } static void @@ -291,10 +290,18 @@ static void webkit_web_frame_load_done (WebKitWebFrame* web_frame, gboolean success, MidoriWebView* web_view) { + GdkPixbuf* icon; + web_view->is_loading = FALSE; web_view->progress = -1; if (web_view->tab_icon) + { katze_throbber_set_animated (KATZE_THROBBER (web_view->tab_icon), FALSE); + icon = midori_web_view_get_icon (web_view); + katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), + icon); + g_object_unref (icon); + } g_signal_emit (web_view, signals[LOAD_DONE], 0, web_frame); } @@ -372,10 +379,15 @@ static gboolean gtk_widget_button_press_event_after (MidoriWebView* web_view, GdkEventButton* event) { + GdkModifierType state; + GtkClipboard* clipboard; + if (event->button == 2 && web_view->middle_click_opens_selection) { - GdkModifierType state = (GdkModifierType) event->state; - GtkClipboard* clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); + state = (GdkModifierType) event->state; + clipboard = gtk_clipboard_get_for_display ( + gtk_widget_get_display (GTK_WIDGET (web_view)), + GDK_SELECTION_PRIMARY); gchar* uri = gtk_clipboard_wait_for_text (clipboard); if (uri && strchr (uri, '.') && !strchr (uri, ' ')) { @@ -579,8 +591,6 @@ midori_web_view_finalize (GObject* object) { MidoriWebView* 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); @@ -612,13 +622,6 @@ midori_web_view_set_property (GObject* object, switch (prop_id) { - case PROP_ICON: - katze_object_assign (web_view->icon, g_value_get_object (value)); - g_object_ref (web_view->icon); - if (web_view->tab_icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), - web_view->icon); - break; case PROP_URI: { const gchar* uri = g_value_get_string (value); @@ -670,9 +673,6 @@ midori_web_view_get_property (GObject* object, switch (prop_id) { - case PROP_ICON: - g_value_set_object (value, web_view->icon); - break; case PROP_URI: g_value_set_string (value, web_view->uri); break; @@ -738,15 +738,20 @@ midori_web_view_set_settings (MidoriWebView* web_view, GtkWidget* midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) { + const gchar* title; + GtkWidget* menu_item; + GdkPixbuf* icon; + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), FALSE); if (!web_view->proxy_menu_item) { - const gchar* title = midori_web_view_get_display_title (web_view); - GtkWidget* menu_item = gtk_image_menu_item_new_with_label (title); - GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE, - GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon); + title = midori_web_view_get_display_title (web_view); + menu_item = gtk_image_menu_item_new_with_label (title); + icon = midori_web_view_get_icon (web_view); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), + gtk_image_new_from_pixbuf (icon)); + g_object_unref (icon); web_view->proxy_menu_item = menu_item; } @@ -770,17 +775,17 @@ midori_web_view_get_proxy_menu_item (MidoriWebView* web_view) GtkWidget* midori_web_view_get_proxy_tab_icon (MidoriWebView* web_view) { + GdkPixbuf* icon; + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); if (!web_view->tab_icon) { web_view->tab_icon = katze_throbber_new (); - if (web_view->icon) - katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), - web_view->icon); - else - katze_throbber_set_static_stock_id (KATZE_THROBBER (web_view->tab_icon), - GTK_STOCK_FILE); + icon = midori_web_view_get_icon (web_view); + katze_throbber_set_static_pixbuf (KATZE_THROBBER (web_view->tab_icon), + icon); + g_object_unref (icon); } return web_view->tab_icon; } @@ -1031,3 +1036,48 @@ midori_web_view_get_link_uri (MidoriWebView* web_view) return web_view->link_uri; } + +/** + * midori_web_view_get_icon: + * @web_view: a #MidoriWebView + * + * Retrieves an icon associated with the currently loaded URI. If no + * icon is available a default icon is used. + * + * Return value: a #GdkPixbuf + **/ +GdkPixbuf* +midori_web_view_get_icon (MidoriWebView* web_view) +{ + GFile* file; + GFile* icon_file; + GIcon* icon; + GInputStream* stream; + GdkPixbuf* pixbuf; + + g_return_val_if_fail (MIDORI_IS_WEB_VIEW (web_view), NULL); + + #if GLIB_CHECK_VERSION (2, 16, 0) + file = g_file_new_for_uri (web_view->uri ? web_view->uri : ""); + icon_file = g_file_get_child (file, "favicon.ico"); + icon = g_file_icon_new (icon_file); + if (icon) + stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), + GTK_ICON_SIZE_MENU, + NULL, NULL, NULL); + else + stream = NULL; + if (stream) + { + pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); + g_object_unref (stream); + } + g_object_unref (icon); + g_object_unref (icon_file); + g_object_unref (file); + if (!stream) + #endif + pixbuf = gtk_widget_render_icon (GTK_WIDGET (web_view), + GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL); + return pixbuf; +} diff --git a/midori/midori-webview.h b/midori/midori-webview.h index 431e1bef..91491a89 100644 --- a/midori/midori-webview.h +++ b/midori/midori-webview.h @@ -99,6 +99,9 @@ midori_web_view_get_display_title (MidoriWebView* web_view); const gchar* midori_web_view_get_link_uri (MidoriWebView* web_view); +GdkPixbuf* +midori_web_view_get_icon (MidoriWebView* web_view); + G_END_DECLS #endif /* __MIDORI_WEB_VIEW_H__ */