{"complete", command_complete, {0}, VP_MODE_COMMAND | VP_MODE_COMPLETE},
{"complete-back", command_complete, {1}, VP_MODE_COMMAND | VP_MODE_COMPLETE},
{"inspect", command_inspect, {0}, VP_MODE_NORMAL},
- {"hint-link", command_hints, {0, "."}, VP_MODE_HINTING},
+ {"hint-link", command_hints, {HINTS_MODE_LINK, "."}, VP_MODE_HINTING},
+ {"hint-link-new", command_hints, {HINTS_MODE_LINK_NEW, ","}, VP_MODE_HINTING},
{"hint-focus-next", command_hints_focus, {0}, VP_MODE_HINTING},
{"hint-focus-prev", command_hints_focus, {1}, VP_MODE_HINTING},
};
{
Hint* hint = hints_get_hint_by_number(num);
if (hint) {
- /* TODO
- * if the elemt has a target attribute - remove it temporary
- * fire mousedown and click events on the element
- * if it is an form element focus it and return */
-
if (dom_is_editable(hint->elem)) {
webkit_dom_element_focus(hint->elem);
vp_set_mode(VP_MODE_INSERT, FALSE);
} else {
- /* remove possible target attribute */
- gchar* type = webkit_dom_element_get_attribute(hint->elem, "target");
- if (g_strcmp0(type, "_blank") == 0) {
+ /* TODO I don't get the mouse click event dispatched here to
+ * invoce the gtk events for button press wich might be the better
+ * way hanlding to open new windows that setting temporary target
+ * attribute here */
+ gchar* target = webkit_dom_element_get_attribute(hint->elem, "target");
+ if (currentMode == HINTS_MODE_LINK_NEW) { /* open in new window */
+ webkit_dom_element_set_attribute(hint->elem, "target", "_blank", NULL);
+ } else if (g_strcmp0(target, "_blank") == 0) { /* remove possible target attribute */
webkit_dom_element_remove_attribute(hint->elem, "target");
}
+
+ /* dispatch click event */
Document* doc = webkit_web_view_get_dom_document(vp.gui.webview);
dom_dispatch_mouse_event(doc, hint->elem, "click", 0);
+
+ /* reset previous target attribute */
+ if (target && strlen(target)) {
+ webkit_dom_element_set_attribute(hint->elem, "target", target, NULL);
+ } else {
+ webkit_dom_element_remove_attribute(hint->elem, "target");
+ }
+
/* remove the hint filter input */
vp_clean_input();
}
switch (currentMode) {
case HINTS_MODE_LINK:
+ case HINTS_MODE_LINK_NEW:
if (input == NULL) {
xpath = g_strdup(
"//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @ role='link'] | "
#include "hints.h"
/* variables */
+static gchar **args;
VpCore vp;
/* callbacks */
static void vp_gotheaders_cb(SoupMessage* message, gpointer data);
#endif
static WebKitWebView* vp_inspect_web_view_cb(gpointer inspector, WebKitWebView* web_view);
+static gboolean vp_button_relase_cb(WebKitWebView *webview, GdkEventButton* event, gpointer data);
+static gboolean vp_new_window_policy_cb(
+ WebKitWebView* view, WebKitWebFrame* frame, WebKitNetworkRequest* request,
+ WebKitWebNavigationAction* navig, WebKitWebPolicyDecision* policy, gpointer data);
+static WebKitWebView* vp_create_new_webview_cb(WebKitWebView* webview, WebKitWebFrame* frame, gpointer data);
+static void vp_create_new_webview_uri_cb(WebKitWebView* view, GParamSpec param_spec);
/* functions */
static gboolean vp_process_input(const char* input);
static void vp_init_gui(void);
static void vp_init_files(void);
static void vp_setup_signals(void);
-static gboolean vp_notify_event_cb(WebKitWebView *webview, GdkEventButton* event, gpointer data);
#ifdef FEATURE_COOKIE
static void vp_set_cookie(SoupCookie* cookie);
static const gchar* vp_get_cookies(SoupURI *uri);
}
uri = g_strrstr(line, "://") ? g_strdup(line) : g_strdup_printf("http://%s", line);
+ if (arg->i == VP_TARGET_NEW) {
+ gchar *argv[64];
+ argv[0] = *args;
+ argv[1] = uri;
+ argv[2] = NULL;
+
+ /* spawn a new browser instance */
+ g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
+ } else {
+ /* Load a web page into the browser instance */
+ webkit_web_view_load_uri(vp.gui.webview, uri);
- /* Load a web page into the browser instance */
- webkit_web_view_load_uri(vp.gui.webview, uri);
+ /* change state to normal mode */
+ vp_set_mode(VP_MODE_NORMAL, FALSE);
+ }
g_free(uri);
- /* change state to normal mode */
- vp_set_mode(VP_MODE_NORMAL, FALSE);
-
return TRUE;
}
g_signal_connect(G_OBJECT(gui->webview), "notify::load-status", G_CALLBACK(vp_webview_load_status_cb), NULL);
g_object_connect(
G_OBJECT(gui->webview),
- "signal::button-release-event", G_CALLBACK(vp_notify_event_cb), NULL,
+ "signal::button-release-event", G_CALLBACK(vp_button_relase_cb), NULL,
+ "signal::new-window-policy-decision-requested", G_CALLBACK(vp_new_window_policy_cb), NULL,
+ "signal::create-web-view", G_CALLBACK(vp_create_new_webview_cb), NULL,
NULL
);
g_object_set(vp.net.soup_session, "max-conns-per-host", SETTING_MAX_CONNS_PER_HOST, NULL);
g_signal_connect_after(G_OBJECT(vp.net.soup_session), "request-started", G_CALLBACK(vp_new_request_cb), NULL);
#endif
-
+
/* inspector */
g_signal_connect(
G_OBJECT(vp.gui.inspector),
);
}
-static gboolean vp_notify_event_cb(WebKitWebView* webview, GdkEventButton* event, gpointer data)
+static gboolean vp_button_relase_cb(WebKitWebView* webview, GdkEventButton* event, gpointer data)
{
- if (GET_CLEAN_MODE() == VP_MODE_NORMAL) {
- return FALSE;
- }
- WebKitHitTestResult *result = webkit_web_view_get_hit_test_result(webview, event);
WebKitHitTestResultContext context;
+ Mode mode = GET_CLEAN_MODE();
+ WebKitHitTestResult *result = webkit_web_view_get_hit_test_result(webview, event);
+
g_object_get(result, "context", &context, NULL);
- if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE) {
+ if (mode == VP_MODE_NORMAL && context & WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE) {
vp_set_mode(VP_MODE_INSERT, FALSE);
return TRUE;
}
+ /* middle mouse click onto link */
+ if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK && event->button == 2) {
+ Arg a = {VP_TARGET_NEW};
+ g_object_get(result, "link-uri", &a.s, NULL);
+ vp_load_uri(&a);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean vp_new_window_policy_cb(
+ WebKitWebView* view, WebKitWebFrame* frame, WebKitNetworkRequest* request,
+ WebKitWebNavigationAction* navig, WebKitWebPolicyDecision* policy, gpointer data)
+{
+ if (webkit_web_navigation_action_get_reason(navig) == WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED) {
+ /* open in a new window */
+ Arg a = {VP_TARGET_NEW, (gchar*)webkit_network_request_get_uri(request)};
+ vp_load_uri(&a);
+ webkit_web_policy_decision_ignore(policy);
+ return TRUE;
+ }
return FALSE;
}
+static WebKitWebView* vp_create_new_webview_cb(WebKitWebView* webview, WebKitWebFrame* frame, gpointer data)
+{
+ /* create only a temporary webview */
+ WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+
+ /* wait until the new webview receives its new URI */
+ g_object_connect(view, "signal::notify::uri", G_CALLBACK(vp_create_new_webview_uri_cb), NULL, NULL);
+ return view;
+}
+
+static void vp_create_new_webview_uri_cb(WebKitWebView* view, GParamSpec param_spec)
+{
+ Arg a = {VP_TARGET_NEW, (gchar*)webkit_web_view_get_uri(view)};
+ /* clean up */
+ webkit_web_view_stop_loading(view);
+ gtk_widget_destroy(GTK_WIDGET(view));
+ /* open the requested window */
+ vp_load_uri(&a);
+}
+
int main(int argc, char* argv[])
{
static gboolean ver = false;
vp_print_version();
return EXIT_SUCCESS;
}
+
+ /* save arguments */
+ args = argv;
+
vp_init();
/* command line argument: URL */
- Arg arg;
+ Arg arg = {VP_TARGET_CURRENT};
if (argc > 1) {
arg.s = g_strdup(argv[argc - 1]);
} else {