diff -uprEb a/src/dh-window.c b/src/dh-window.c
--- a/src/dh-window.c	2012-11-06 14:13:21.619786140 +0900
+++ b/src/dh-window.c	2012-11-09 23:32:56.145920429 +0900
@@ -54,6 +54,8 @@
 
 #define FULLSCREEN_ANIMATION_SPEED 4
 #define TAB_WIDTH_N_CHARS 15
+#define KEY_LINK_UNDER_POINTER  "dh-window-link-under-pointer"
+#define KEY_POPUP_ITEM_NAME     "dh-popup-item-action-name"
 
 struct _DhWindowPriv {
         GtkWidget      *main_box;
@@ -66,6 +68,8 @@ struct _DhWindowPriv {
         GtkWidget      *vbox;
         GtkWidget      *findbar;
 
+        GtkWidget      *popup;
+
         GtkWidget      *fullscreen_controls;
         guint           fullscreen_animation_timeout_id;
         gboolean        fullscreen_animation_enter;
@@ -578,6 +582,20 @@ leave_fullscreen_cb (GSimpleAction *acti
         g_action_change_state (G_ACTION (fs_action), g_variant_new_boolean (FALSE));
 }
 
+static void
+open_in_tab_cb (GSimpleAction    *action,
+                GVariant         *parameter,
+                gpointer          data)
+{
+        DhWindow *window = data;
+        WebKitWebView *web_view;
+        const gchar *location; 
+
+        web_view = window_get_active_web_view (window);
+        location = g_object_get_data (G_OBJECT (web_view), KEY_LINK_UNDER_POINTER);
+        window_open_new_tab (window, location, (location != NULL));
+}
+
 static GActionEntry win_entries[] = {
         /* file */
         { "new-tab",          new_tab_cb,          NULL, NULL, NULL },
@@ -599,6 +617,7 @@ static GActionEntry win_entries[] = {
         { "go-forward",       go_forward_cb,       NULL, "false", NULL },
         { "go-contents-tab",  go_contents_tab_cb,  NULL, NULL, NULL },
         { "go-search-tab",    go_search_tab_cb,    NULL, NULL, NULL },
+        { "open-in-tab",      open_in_tab_cb,      NULL, NULL, NULL },
 };
 
 static gboolean
@@ -811,6 +830,148 @@ window_fullscreen_controls_show (DhWindo
 }
 
 static void
+popup_item_activated_cb (GtkWidget *widget, DhWindow *window)
+{
+        GAction *action;
+        const gchar *action_name;
+
+        action_name = g_object_get_data (G_OBJECT (widget), KEY_POPUP_ITEM_NAME);
+
+        if (!action_name)
+                return;
+                
+        action = g_action_map_lookup_action (G_ACTION_MAP (window), action_name);
+
+        if (action)
+                g_action_activate (action, NULL);
+}
+
+static void
+popup_set_item_visible (DhWindow *window,
+                        const gchar *item_name,
+                        gboolean setting)
+{
+        GList *children, *node;
+
+        children = gtk_container_get_children (GTK_CONTAINER (window->priv->popup));
+
+        for (node = children; node; node = node->next) {
+                GObject *object;
+                const gchar *data;
+
+                object = node->data;
+                data = g_object_get_data (object, KEY_POPUP_ITEM_NAME);
+
+                if (g_strcmp0 (data, item_name) == 0) {
+                        gtk_widget_set_visible (GTK_WIDGET (object), setting);
+                        break;
+                }
+
+        }
+
+        g_list_free (children);
+}
+
+static void
+append_popup_item (DhWindow     *window,
+                   GtkWidget    *menu,
+                   const gchar  *item_label,
+                   const gchar  *item_name,
+                   gboolean     from_stock)
+{
+        GtkWidget *item;
+
+        if (item_label) {
+                if (from_stock)
+                        item = gtk_image_menu_item_new_from_stock (item_label, NULL);
+                else
+                        item = gtk_menu_item_new_with_mnemonic (item_label);
+
+                g_object_set_data_full (G_OBJECT (item), KEY_POPUP_ITEM_NAME,
+                                        g_strdup (item_name), g_free);
+
+                g_signal_connect (item, "activate",
+                                  G_CALLBACK (popup_item_activated_cb), window);
+        } else {
+                item = gtk_separator_menu_item_new ();
+        }
+        gtk_menu_shell_insert (GTK_MENU_SHELL (menu), item, -1);
+}
+
+#ifdef HAVE_WEBKIT2
+static gboolean
+window_web_view_context_menu_cb (WebKitWebView       *web_view,
+                                 WebKitContextMenu   *context_menu,
+                                 GdkEvent            *event,
+                                 WebKitHitTestResult *hit_test_result,
+                                 DhWindow            *window)
+#else
+static gboolean
+window_web_view_context_menu_cb (WebKitWebView       *web_view,
+                                 GtkWidget           *default_menu,
+                                 WebKitHitTestResult *hit_test_result,
+                                 gboolean             triggered_with_keyboard,
+                                 DhWindow            *window)
+#endif
+{
+        gboolean can_back;
+        gboolean can_forward;
+        gboolean got_uri = FALSE;
+        gboolean has_selection = TRUE;
+        gchar *location = NULL;
+        WebKitHitTestResultContext context;
+
+        g_object_get (G_OBJECT (hit_test_result), "link-uri", &location,
+                                        "context", &context, NULL);
+
+        if (location != NULL && g_str_has_prefix (location, "file://")) {
+                g_object_set_data_full (G_OBJECT (web_view), KEY_LINK_UNDER_POINTER,
+                                        location, g_free);
+                got_uri = TRUE;
+        } else {
+                g_object_set_data (G_OBJECT (web_view), KEY_LINK_UNDER_POINTER, NULL);
+
+                if (location)
+                        g_free (location);
+        }
+        
+        can_back = webkit_web_view_can_go_back (web_view);
+        can_forward = webkit_web_view_can_go_forward (web_view);
+#ifndef HAVE_WEBKIT2
+        has_selection = ((context & WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION) != 0);
+#endif
+
+        popup_set_item_visible (window, "go-back", can_back);
+        popup_set_item_visible (window, "go-forward", can_forward);
+        popup_set_item_visible (window, "copy", has_selection);
+        popup_set_item_visible (window, "open-in-tab", got_uri);
+        popup_set_item_visible (window, "new-tab", !got_uri);
+
+        gtk_menu_popup (GTK_MENU (window->priv->popup), NULL, NULL, NULL, NULL, 3,
+#ifdef HAVE_WEBKIT2
+                                        ((GdkEventButton *) event)->time);
+#else
+                                        gtk_get_current_event_time ());
+#endif
+        return TRUE;
+}
+
+static GtkWidget*
+create_popup_menu (DhWindow *window)
+{
+        GtkWidget *menu;
+
+        menu = gtk_menu_new ();
+        append_popup_item (window, menu, GTK_STOCK_GO_BACK, "go-back", TRUE);
+        append_popup_item (window, menu, GTK_STOCK_GO_FORWARD, "go-forward", TRUE);
+        append_popup_item (window, menu, GTK_STOCK_COPY, "copy", TRUE);
+        append_popup_item (window, menu, _("Open link in tab"), "open-in-tab", FALSE);
+        append_popup_item (window, menu, _("New _Tab"), "new-tab", FALSE);
+
+        return menu;
+}
+
+static void
 dh_window_init (DhWindow *window)
 {
         DhWindowPriv  *priv;
@@ -848,6 +1009,7 @@ dh_window_init (DhWindow *window)
                                          win_entries, G_N_ELEMENTS (win_entries),
                                          window);
 
+        priv->popup = create_popup_menu (window);
         accel_group = gtk_accel_group_new ();
         gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
         for (i = 0; i < G_N_ELEMENTS (tab_accel_keys); i++) {
@@ -1367,10 +1529,6 @@ window_web_view_button_press_event_cb (W
                                        GdkEventButton *event,
                                        DhWindow       *window)
 {
-        if (event->button == 3) {
-                return TRUE;
-        }
-
         return FALSE;
 }
 
@@ -1644,6 +1802,9 @@ window_open_new_tab (DhWindow    *window
         g_signal_connect (view, "button-press-event",
                           G_CALLBACK (window_web_view_button_press_event_cb),
                           window);
+        g_signal_connect (view, "context-menu",
+                          G_CALLBACK (window_web_view_context_menu_cb),
+                          window);
 #ifdef HAVE_WEBKIT2
         g_signal_connect (view, "decide-policy",
                           G_CALLBACK (window_web_view_decide_policy_cb),
@@ -1652,6 +1813,7 @@ window_open_new_tab (DhWindow    *window
         g_signal_connect (view, "navigation-policy-decision-requested",
                           G_CALLBACK (window_web_view_navigation_policy_decision_requested),
                           window);
+
 #endif
 #ifdef HAVE_WEBKIT2
         g_signal_connect (view, "load-failed",
