[devhelp] Let middle click open links in new tabs, in the background



commit 2b0ddd3adc7fdb1abb9c0b09a76e5380194bf273
Author: Frédéric Péters <fpeters 0d be>
Date:   Fri Aug 28 21:50:22 2009 +0200

    Let middle click open links in new tabs, in the background

 .gitignore                   |    2 +
 configure.ac                 |    1 +
 src/Makefile.am              |   18 +++++-
 src/dh-enum-types.c.template |   39 +++++++++++++
 src/dh-enum-types.h.template |   27 +++++++++
 src/dh-marshal.list          |    1 +
 src/dh-window.c              |  129 +++++++++++++++++++++++++++---------------
 src/dh-window.h              |   13 ++++-
 8 files changed, 182 insertions(+), 48 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index a392796..0f0810d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,4 +42,6 @@ libtool
 /src/devhelp
 /src/dh-marshal.c
 /src/dh-marshal.h
+/src/dh-enum-types.c
+/src/dh-enum-types.h
 /stamp-h1
diff --git a/configure.ac b/configure.ac
index b7fe5a4..7c4d53c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,6 +98,7 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Package name for gettext
 AM_GLIB_GNU_GETTEXT
 
 AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
+AC_PATH_PROG(GLIB_MKENUMS, glib-mkenums)
 
 AM_PATH_PYTHON([2.3],[],[no])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 4988b3d..89b6260 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,10 +8,14 @@ dh-marshal.c: dh-marshal.list
 BUILT_SOURCES = 		\
 	dh-marshal.h		\
 	dh-marshal.c		\
+	dh-enum-types.h		\
+	dh-enum-types.c		\
 	$(NULL)
 
 EXTRA_DIST =			\
 	dh-marshal.list		\
+	dh-enum-types.c.template \
+	dh-enum-types.h.template \
 	$(NULL)
 
 AM_CPPFLAGS = 						\
@@ -44,8 +48,7 @@ devhelp_LDADD = 					\
 
 lib_LTLIBRARIES = libdevhelp-1.la
 
-devhelpincludedir = $(includedir)/devhelp-1.0/devhelp
-devhelpinclude_HEADERS = 				\
+INST_H_FILES = 						\
 	dh-assistant.h					\
 	dh-assistant-view.h				\
 	dh-base.h					\
@@ -56,9 +59,14 @@ devhelpinclude_HEADERS = 				\
 	dh-search.h					\
 	dh-window.h
 
+devhelpincludedir = $(includedir)/devhelp-1.0/devhelp
+devhelpinclude_HEADERS = $(INST_H_FILES)
+
 libdevhelp_1_la_SOURCES =				\
 	dh-marshal.c					\
 	dh-marshal.h					\
+	dh-enum-types.c					\
+	dh-enum-types.h					\
 	dh-assistant.c					\
 	dh-assistant-view.c				\
 	dh-base.c					\
@@ -98,6 +106,12 @@ libdevhelp_1_la_LDFLAGS =				\
 	-export-symbols-regex ^dh_ \
 	$(ZLIB_LDFLAGS)
 
+dh-enum-types.h: dh-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
+	$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template dh-enum-types.h.template $(INST_H_FILES)) > $@
+
+dh-enum-types.c: dh-enum-types.c.template $(INST_H_FILES) $(GLIB_MKENUMS)
+	$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template dh-enum-types.c.template $(INST_H_FILES)) > $@
+
 if HAVE_PLATFORM_OSX
 conf_platform_sources = ige-conf-mac.c
 libdevhelp_1_la_CPPFLAGS += -xobjective-c
diff --git a/src/dh-enum-types.c.template b/src/dh-enum-types.c.template
new file mode 100644
index 0000000..1b5957e
--- /dev/null
+++ b/src/dh-enum-types.c.template
@@ -0,0 +1,39 @@
+/*** BEGIN file-header ***/
+#include "dh-enum-types.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+#include "@filename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+	static GType the_type = 0;
+	
+	if (the_type == 0)
+	{
+		static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+			{ @VALUENAME@,
+			  "@VALUENAME@",
+			  "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+			{ 0, NULL, NULL }
+		};
+		the_type = g_ type@_register_static (
+				g_intern_static_string ("@EnumName@"),
+				values);
+	}
+	return the_type;
+}
+
+/*** END value-tail ***/
diff --git a/src/dh-enum-types.h.template b/src/dh-enum-types.h.template
new file mode 100644
index 0000000..fc97c74
--- /dev/null
+++ b/src/dh-enum-types.h.template
@@ -0,0 +1,27 @@
+/*** BEGIN file-header ***/
+#ifndef __DH_ENUM_TYPES_H__
+#define __DH_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN enumeration-production ***/
+#define DH_TYPE_ ENUMSHORT@	(@enum_name _get_type())
+GType @enum_name _get_type	(void) G_GNUC_CONST;
+
+/*** END enumeration-production ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __DH_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
diff --git a/src/dh-marshal.list b/src/dh-marshal.list
index 0e021f4..969dff3 100644
--- a/src/dh-marshal.list
+++ b/src/dh-marshal.list
@@ -2,3 +2,4 @@ VOID:BOOLEAN
 VOID:POINTER
 VOID:STRING
 BOOLEAN:STRING
+VOID:STRING,FLAGS
diff --git a/src/dh-window.c b/src/dh-window.c
index 73044af..f5ebb6b 100644
--- a/src/dh-window.c
+++ b/src/dh-window.c
@@ -34,6 +34,8 @@
 #include "dh-search.h"
 #include "dh-window.h"
 #include "dh-util.h"
+#include "dh-marshal.h"
+#include "dh-enum-types.h"
 #include "eggfindbar.h"
 #include "ige-conf.h"
 
@@ -57,6 +59,13 @@ struct _DhWindowPriv {
         GtkActionGroup *action_group;
 };
 
+enum {
+        OPEN_LINK,
+        LAST_SIGNAL
+};
+
+static gint signals[LAST_SIGNAL] = { 0 };
+
 static guint tab_accel_keys[] = {
         GDK_1, GDK_2, GDK_3, GDK_4, GDK_5,
         GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
@@ -118,8 +127,9 @@ static void           window_findbar_close_cb        (GtkWidget       *widget,
                                                       DhWindow        *window);
 static GtkWidget *    window_new_tab_label           (DhWindow        *window,
                                                       const gchar     *label);
-static void           window_open_new_tab            (DhWindow        *window,
-                                                      const gchar     *location);
+static int            window_open_new_tab            (DhWindow        *window,
+                                                      const gchar     *location,
+                                                      gboolean         switch_focus);
 static WebKitWebView *window_get_active_web_view     (DhWindow        *window);
 static void           window_update_title            (DhWindow        *window,
                                                       WebKitWebView   *web_view,
@@ -154,7 +164,7 @@ window_activate_new_tab (GtkAction *action,
 
         priv = window->priv;
 
-        window_open_new_tab (window, NULL);
+        window_open_new_tab (window, NULL, TRUE);
 }
 
 static void
@@ -379,6 +389,24 @@ window_activate_about (GtkAction *action,
                                NULL);
 }
 
+static void
+window_open_link_cb (DhWindow *window,
+                     const char *location,
+                     DhOpenLinkFlags flags)
+{
+        DhWindowPriv *priv;
+        priv = window->priv;
+
+        if (flags & DH_OPEN_LINK_NEW_TAB) {
+                window_open_new_tab (window, location, FALSE);
+        }
+        else if (flags & DH_OPEN_LINK_NEW_WINDOW) {
+                GtkWidget *new_window;
+                new_window = dh_base_new_window (priv->base);
+                gtk_widget_show (new_window);
+        }
+}
+
 static const GtkActionEntry actions[] = {
         { "FileMenu", NULL, N_("_File") },
         { "EditMenu", NULL, N_("_Edit") },
@@ -462,6 +490,18 @@ dh_window_class_init (DhWindowClass *klass)
 
         object_class->finalize = window_finalize;
 
+        signals[OPEN_LINK] =
+                g_signal_new ("open-link",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (DhWindowClass, open_link),
+                              NULL, NULL,
+                              _dh_marshal_VOID__STRING_FLAGS,
+                              G_TYPE_NONE,
+                              2,
+                              G_TYPE_STRING,
+                              DH_TYPE_OPEN_LINK_FLAGS);
+
         gtk_rc_parse_string ("style \"devhelp-tab-close-button-style\"\n"
                              "{\n"
                              "GtkWidget::focus-padding = 0\n"
@@ -505,6 +545,11 @@ dh_window_init (DhWindow *window)
 
         gtk_container_add (GTK_CONTAINER (window), priv->main_box);
 
+        g_signal_connect (window,
+                          "open-link",
+                          G_CALLBACK (window_open_link_cb),
+                          window);
+
         g_signal_connect (priv->manager,
                           "add-widget",
                           G_CALLBACK (window_manager_add_widget),
@@ -780,14 +825,16 @@ window_populate (DhWindow *window)
 
         gtk_widget_show_all (priv->hpaned);
 
-        window_open_new_tab (window, NULL);
+        window_open_new_tab (window, NULL, TRUE);
 }
 
-static WebKitNavigationResponse
-window_web_view_navigation_requested_cb (WebKitWebView        *web_view,
-                                         WebKitWebFrame       *frame,
-                                         WebKitNetworkRequest *request,
-                                         DhWindow             *window)
+static gboolean
+window_web_view_navigation_policy_decision_requested (WebKitWebView             *web_view,
+                                                      WebKitWebFrame            *frame,
+                                                      WebKitNetworkRequest      *request,
+                                                      WebKitWebNavigationAction *navigation_action,
+                                                      WebKitWebPolicyDecision   *policy_decision,
+                                                      DhWindow                  *window)
 {
         DhWindowPriv *priv;
         const char   *uri;
@@ -795,25 +842,29 @@ window_web_view_navigation_requested_cb (WebKitWebView        *web_view,
         priv = window->priv;
 
         uri = webkit_network_request_get_uri (request);
-        if (strcmp (uri, "about:blank") == 0) {
-                return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
+
+        if (webkit_web_navigation_action_get_button (navigation_action) == 2) { /* middle click */
+                webkit_web_policy_decision_ignore (policy_decision);
+                g_signal_emit (window, signals[OPEN_LINK], 0, uri, DH_OPEN_LINK_NEW_TAB);
+                return TRUE;
         }
 
         if (strncmp (uri, "file://", 7) != 0) {
+                webkit_web_policy_decision_ignore (policy_decision);
                 gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, NULL);
-                return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
+                return TRUE;
         }
 
-        if (web_view == window_get_active_web_view (window)) {
-                const gchar *uri;
-
-                uri = webkit_network_request_get_uri (request);
+        if (strcmp (uri, "about:blank") == 0) {
+                return FALSE;
+        }
 
+        if (web_view == window_get_active_web_view (window)) {
                 dh_book_tree_select_uri (DH_BOOK_TREE (priv->book_tree), uri);
                 window_check_history (window, web_view);
         }
 
-        return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
+        return FALSE;
 }
 
 static void
@@ -829,21 +880,10 @@ window_tree_link_selected_cb (GObject  *ignored,
 
         view = window_get_active_web_view (window);
 
-        /* Block so we don't try to sync the tree when we have already
-         * clicked in it.
-         */
-        g_signal_handlers_block_by_func (view,
-                                         window_web_view_navigation_requested_cb,
-                                         window);
-
         uri = dh_link_get_uri (link);
         webkit_web_view_open (view, uri);
         g_free (uri);
 
-        g_signal_handlers_unblock_by_func (view,
-                                           window_web_view_navigation_requested_cb,
-                                           window);
-
         window_check_history (window, view);
 }
 
@@ -908,9 +948,11 @@ window_web_view_title_changed_cb (WebKitWebView  *web_view,
                                   const gchar    *title,
                                   DhWindow       *window)
 {
-        window_update_title (window,
-                             window_get_active_web_view (window),
-                             title);
+        if (web_view == window_get_active_web_view (window)) {
+                window_update_title (window, web_view, title);
+        }
+
+        window_tab_set_title (window, web_view, title);
 }
 
 static gboolean
@@ -1057,9 +1099,10 @@ window_web_view_tab_accel_cb (GtkAccelGroup   *accel_group,
         }
 }
 
-static void
+static int
 window_open_new_tab (DhWindow    *window,
-                     const gchar *location)
+                     const gchar *location,
+                     gboolean     switch_focus)
 {
         DhWindowPriv *priv;
         GtkWidget    *view;
@@ -1104,16 +1147,10 @@ window_open_new_tab (DhWindow    *window,
                           G_CALLBACK (window_web_view_button_press_event_cb),
                           window);
 
-        g_signal_connect (view, "navigation-requested",
-                          G_CALLBACK (window_web_view_navigation_requested_cb),
+        g_signal_connect (view, "navigation-policy-decision-requested",
+                          G_CALLBACK (window_web_view_navigation_policy_decision_requested),
                           window);
 
-        /*
-        g_signal_connect (view, "open-new-tab",
-                          G_CALLBACK (window_web_view_open_new_tab_cb),
-                          window);
-        */
-
         num = gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook),
                                         scrolled_window, NULL);
 
@@ -1127,12 +1164,16 @@ window_open_new_tab (DhWindow    *window,
         }
 
         if (location) {
-                webkit_web_view_open (WEBKIT_WEB_VIEW (view), location);
+                webkit_web_view_load_uri (WEBKIT_WEB_VIEW (view), location);
         } else {
                 webkit_web_view_open (WEBKIT_WEB_VIEW (view), "about:blank");
         }
 
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), num);
+        if (switch_focus) {
+                gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), num);
+        }
+
+        return num;
 }
 
 #ifndef GDK_WINDOWING_QUARTZ
@@ -1264,8 +1305,6 @@ window_update_title (DhWindow      *window,
                 web_view_title = webkit_web_frame_get_title (web_frame);
         }
 
-        window_tab_set_title (window, web_view, web_view_title);
-
         if (web_view_title && *web_view_title == '\0') {
                 web_view_title = NULL;
         }
diff --git a/src/dh-window.h b/src/dh-window.h
index 969c487..8003806 100644
--- a/src/dh-window.h
+++ b/src/dh-window.h
@@ -39,13 +39,24 @@ typedef struct _DhWindow       DhWindow;
 typedef struct _DhWindowClass  DhWindowClass;
 typedef struct _DhWindowPriv   DhWindowPriv;
 
+typedef enum
+{
+        DH_OPEN_LINK_NEW_WINDOW = 1 << 0,
+        DH_OPEN_LINK_NEW_TAB    = 1 << 1
+} DhOpenLinkFlags;
+
 struct _DhWindow {
         GtkWindow     parent_instance;
-	DhWindowPriv *priv;
+        DhWindowPriv *priv;
 };
 
 struct _DhWindowClass {
         GtkWindowClass parent_class;
+
+        /* Signals */
+        void (*open_link) (DhWindow        *window,
+                           const char      *location,
+                           DhOpenLinkFlags  flags);
 };
 
 GType      dh_window_get_type     (void) G_GNUC_CONST;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]