From: Daniel Carl Date: Fri, 21 Dec 2012 14:09:14 +0000 (+0100) Subject: Added logic to process hinted elements. X-Git-Url: https://git.owens.tech///git?a=commitdiff_plain;h=ac7ac5605284e7fc0e1f7ff5eb9a306865474e2d;p=vimb.git Added logic to process hinted elements. Added commend to write hinted link url to the inputbar. --- diff --git a/doc/config b/doc/config index 27fe492..cc4e2b3 100644 --- a/doc/config +++ b/doc/config @@ -25,6 +25,8 @@ nmap k scrollup nmap j scrolldown nmap f hint-link nmap F hint-link-new +nmap go hint-input-open +nmap gt hint-input-tabopen cmap complete cmap complete-back hmap hint-focus-next diff --git a/src/command.c b/src/command.c index 6242fe8..e1b6342 100644 --- a/src/command.c +++ b/src/command.c @@ -25,49 +25,51 @@ #include "hints.h" static CommandInfo cmd_list[] = { - /* command function arg mode */ - {"open", command_open, {VP_TARGET_CURRENT, ""}, VP_MODE_NORMAL}, - {"tabopen", command_open, {VP_TARGET_NEW, ""}, VP_MODE_NORMAL}, - {"input", command_input, {0, ":"}, VP_MODE_COMMAND}, - {"inputopen", command_input, {0, ":open "}, VP_MODE_COMMAND}, - {"inputtabopen", command_input, {0, ":tabopen "}, VP_MODE_COMMAND}, - {"inputopencurrent", command_input, {VP_INPUT_CURRENT_URI, ":open "}, VP_MODE_COMMAND}, - {"inputtabopencurrent", command_input, {VP_INPUT_CURRENT_URI, ":tabopen "}, VP_MODE_COMMAND}, - {"quit", command_close, {0}, VP_MODE_NORMAL}, - {"source", command_view_source, {0}, VP_MODE_NORMAL}, - {"back", command_navigate, {VP_NAVIG_BACK}, VP_MODE_NORMAL}, - {"forward", command_navigate, {VP_NAVIG_FORWARD}, VP_MODE_NORMAL}, - {"reload", command_navigate, {VP_NAVIG_RELOAD}, VP_MODE_NORMAL}, - {"reload!", command_navigate, {VP_NAVIG_RELOAD_FORCE}, VP_MODE_NORMAL}, - {"stop", command_navigate, {VP_NAVIG_STOP_LOADING}, VP_MODE_NORMAL}, - {"jumpleft", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_LEFT}, VP_MODE_NORMAL}, - {"jumpright", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_RIGHT}, VP_MODE_NORMAL}, - {"jumptop", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_TOP}, VP_MODE_NORMAL}, - {"jumpbottom", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_DOWN}, VP_MODE_NORMAL}, - {"pageup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_PAGE}, VP_MODE_NORMAL}, - {"pagedown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_PAGE}, VP_MODE_NORMAL}, - {"halfpageup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_HALFPAGE}, VP_MODE_NORMAL}, - {"halfpagedown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_HALFPAGE}, VP_MODE_NORMAL}, - {"scrollleft", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_LEFT | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, - {"scrollright", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_RIGHT | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, - {"scrollup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, - {"scrolldown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, - {"nmap", command_map, {VP_MODE_NORMAL}, VP_MODE_NORMAL}, - {"imap", command_map, {VP_MODE_INSERT}, VP_MODE_NORMAL}, - {"cmap", command_map, {VP_MODE_COMMAND}, VP_MODE_NORMAL}, - {"hmap", command_map, {VP_MODE_HINTING}, VP_MODE_NORMAL}, - {"nunmap", command_unmap, {VP_MODE_NORMAL}, VP_MODE_NORMAL}, - {"iunmap", command_unmap, {VP_MODE_INSERT}, VP_MODE_NORMAL}, - {"cunmap", command_unmap, {VP_MODE_COMMAND}, VP_MODE_NORMAL}, - {"hunmap", command_unmap, {VP_MODE_HINTING}, VP_MODE_NORMAL}, - {"set", command_set, {0}, VP_MODE_NORMAL}, - {"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, {HINTS_TYPE_LINK, "."}, VP_MODE_HINTING}, - {"hint-link-new", command_hints, {HINTS_TYPE_LINK | HINTS_CLICK_BLANK, ","}, VP_MODE_HINTING}, - {"hint-focus-next", command_hints_focus, {0}, VP_MODE_HINTING}, - {"hint-focus-prev", command_hints_focus, {1}, VP_MODE_HINTING}, + /* command function arg mode */ + {"open", command_open, {VP_TARGET_CURRENT, ""}, VP_MODE_NORMAL}, + {"tabopen", command_open, {VP_TARGET_NEW, ""}, VP_MODE_NORMAL}, + {"input", command_input, {0, ":"}, VP_MODE_COMMAND}, + {"inputopen", command_input, {0, ":open "}, VP_MODE_COMMAND}, + {"inputtabopen", command_input, {0, ":tabopen "}, VP_MODE_COMMAND}, + {"inputopencurrent", command_input, {VP_INPUT_CURRENT_URI, ":open "}, VP_MODE_COMMAND}, + {"inputtabopencurrent", command_input, {VP_INPUT_CURRENT_URI, ":tabopen "}, VP_MODE_COMMAND}, + {"quit", command_close, {0}, VP_MODE_NORMAL}, + {"source", command_view_source, {0}, VP_MODE_NORMAL}, + {"back", command_navigate, {VP_NAVIG_BACK}, VP_MODE_NORMAL}, + {"forward", command_navigate, {VP_NAVIG_FORWARD}, VP_MODE_NORMAL}, + {"reload", command_navigate, {VP_NAVIG_RELOAD}, VP_MODE_NORMAL}, + {"reload!", command_navigate, {VP_NAVIG_RELOAD_FORCE}, VP_MODE_NORMAL}, + {"stop", command_navigate, {VP_NAVIG_STOP_LOADING}, VP_MODE_NORMAL}, + {"jumpleft", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_LEFT}, VP_MODE_NORMAL}, + {"jumpright", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_RIGHT}, VP_MODE_NORMAL}, + {"jumptop", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_TOP}, VP_MODE_NORMAL}, + {"jumpbottom", command_scroll, {VP_SCROLL_TYPE_JUMP | VP_SCROLL_DIRECTION_DOWN}, VP_MODE_NORMAL}, + {"pageup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_PAGE}, VP_MODE_NORMAL}, + {"pagedown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_PAGE}, VP_MODE_NORMAL}, + {"halfpageup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_HALFPAGE}, VP_MODE_NORMAL}, + {"halfpagedown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_HALFPAGE}, VP_MODE_NORMAL}, + {"scrollleft", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_LEFT | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, + {"scrollright", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_RIGHT | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, + {"scrollup", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_TOP | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, + {"scrolldown", command_scroll, {VP_SCROLL_TYPE_SCROLL | VP_SCROLL_DIRECTION_DOWN | VP_SCROLL_UNIT_LINE}, VP_MODE_NORMAL}, + {"nmap", command_map, {VP_MODE_NORMAL}, VP_MODE_NORMAL}, + {"imap", command_map, {VP_MODE_INSERT}, VP_MODE_NORMAL}, + {"cmap", command_map, {VP_MODE_COMMAND}, VP_MODE_NORMAL}, + {"hmap", command_map, {VP_MODE_HINTING}, VP_MODE_NORMAL}, + {"nunmap", command_unmap, {VP_MODE_NORMAL}, VP_MODE_NORMAL}, + {"iunmap", command_unmap, {VP_MODE_INSERT}, VP_MODE_NORMAL}, + {"cunmap", command_unmap, {VP_MODE_COMMAND}, VP_MODE_NORMAL}, + {"hunmap", command_unmap, {VP_MODE_HINTING}, VP_MODE_NORMAL}, + {"set", command_set, {0}, VP_MODE_NORMAL}, + {"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, {HINTS_TYPE_LINK, "."}, VP_MODE_HINTING}, + {"hint-link-new", command_hints, {HINTS_TYPE_LINK | HINTS_TARGET_BLANK, ","}, VP_MODE_HINTING}, + {"hint-input-open", command_hints, {HINTS_TYPE_LINK | HINTS_PROCESS | HINTS_PROCESS_INPUT, ";o"}, VP_MODE_HINTING}, + {"hint-input-tabopen", command_hints, {HINTS_TYPE_LINK | HINTS_TARGET_BLANK | HINTS_PROCESS | HINTS_PROCESS_INPUT, ";t"}, VP_MODE_HINTING}, + {"hint-focus-next", command_hints_focus, {0}, VP_MODE_HINTING}, + {"hint-focus-prev", command_hints_focus, {1}, VP_MODE_HINTING}, }; static void command_write_input(const gchar* str); diff --git a/src/dom.c b/src/dom.c index b4e2a84..e05e010 100644 --- a/src/dom.c +++ b/src/dom.c @@ -134,6 +134,20 @@ gboolean dom_is_editable(Element* element) return FALSE; } +/** + * Retrieves the src or href attribute of the given element. + */ +gchar* dom_element_get_source(Element* elem) +{ + gchar* url = NULL; + + url = webkit_dom_html_anchor_element_get_href(WEBKIT_DOM_HTML_ANCHOR_ELEMENT(elem)); + if (!url) { + url = webkit_dom_html_image_element_get_src(WEBKIT_DOM_HTML_IMAGE_ELEMENT(elem)); + } + + return url; +} static gboolean dom_auto_insert(Element* element) { diff --git a/src/dom.h b/src/dom.h index 74a5571..1dfca61 100644 --- a/src/dom.h +++ b/src/dom.h @@ -53,5 +53,6 @@ gboolean dom_element_is_visible(Window* win, Element* element); DomBoundingRect dom_elemen_get_bounding_rect(Element* element); void dom_dispatch_mouse_event(Document* doc, Element* element, gchar* type, gushort button); gboolean dom_is_editable(Element* element); +gchar* dom_element_get_source(Element* elem); #endif /* end of include guard: DOM_H */ diff --git a/src/hints.c b/src/hints.c index 382bdee..6cde84f 100644 --- a/src/hints.c +++ b/src/hints.c @@ -21,7 +21,7 @@ #include #include "hints.h" #include "dom.h" -#include "main.h" +#include "command.h" #define MAX_HINTS 200 #define HINT_CONTAINER_ID "__hint_container" @@ -58,6 +58,8 @@ static void hints_create_for_window( gulong top_height, gulong offsetX, gulong offsetY); static void hints_focus(const gulong num); static void hints_fire(const gulong num); +static void hints_click_fired_hint(guint mode, Element* elem); +static void hints_process_fired_hint(guint mode, const gchar* uri); static Hint* hints_get_hint_by_number(const gulong num); static GList* hints_get_hint_list_by_number(const gulong num); static gchar* hints_get_xpath(const gchar* input); @@ -110,7 +112,6 @@ void hints_create(const gchar* input, guint mode) gulong top_width, top_height, offsetX, offsetY; currentMode = mode; - hints_clear(); doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(vp.gui.webview)); @@ -307,6 +308,7 @@ static void hints_focus(const gulong num) dom_element_style_set_property(hint->elem, "background-color", ELEM_BACKGROUND_FOCUS); dom_dispatch_mouse_event(doc, hint->elem, "mouseover", 0); + webkit_dom_element_blur(hint->elem); } currentFocusNum = num; @@ -322,39 +324,68 @@ static void hints_fire(const gulong num) webkit_dom_element_focus(hint->elem); vp_set_mode(VP_MODE_INSERT, FALSE); } else { - if (currentMode & HINTS_OPEN_USE) { - /* get the elements source or href attribute */ - + if (currentMode & HINTS_PROCESS) { + hints_process_fired_hint(currentMode, dom_element_get_source(hint->elem)); } else { - /* 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_CLICK_BLANK) { /* 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); + hints_click_fired_hint(currentMode, hint->elem); - /* 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 and witch to normal mode */ + vp_set_mode(VP_MODE_NORMAL, TRUE); } - - /* remove the hint filter input and witch to normal mode */ - vp_set_mode(VP_MODE_NORMAL, TRUE); } hints_clear(); } +/** + * Perform a mouse click to given element. + */ +static void hints_click_fired_hint(guint mode, Element* elem) +{ + /* TODO I don't get the mouse click event dispatched here to + * invoke the gtk events for button press wich might be the better + * way hanlding to open new windows than setting temporary target + * attribute here */ + gchar* target = webkit_dom_element_get_attribute(elem, "target"); + if (mode & HINTS_TARGET_BLANK) { /* open in new window */ + webkit_dom_element_set_attribute(elem, "target", "_blank", NULL); + } else if (g_strcmp0(target, "_blank") == 0) { /* remove possible target attribute */ + webkit_dom_element_remove_attribute(elem, "target"); + } + + /* dispatch click event */ + /* TODO use document of the hint an not the default one, but this is only + * required if we hint also into frames and iframes */ + Document* doc = webkit_web_view_get_dom_document(vp.gui.webview); + dom_dispatch_mouse_event(doc, elem, "click", 0); + + /* reset previous target attribute */ + if (target && strlen(target)) { + webkit_dom_element_set_attribute(elem, "target", target, NULL); + } else { + webkit_dom_element_remove_attribute(elem, "target"); + } +} + +/** + * Handle fired hints that are not opened via simulated mouse click. + */ +static void hints_process_fired_hint(guint mode, const gchar* uri) +{ + HintsProcess type = HINTS_GET_PROCESSING(mode); + Arg a = {0}; + switch (type) { + case HINTS_PROCESS_INPUT: + a.s = g_strconcat((mode & HINTS_TARGET_BLANK) ? ":tabopen " : ":open ", uri, NULL); + command_input(&a); + g_free(a.s); + break; + + case HINTS_PROCESS_YANK: + /* TODO not implemented */ + break; + } +} + static Hint* hints_get_hint_by_number(const gulong num) { GList* list = hints_get_hint_list_by_number(num); @@ -390,7 +421,7 @@ static gchar* hints_get_xpath(const gchar* input) { gchar* xpath = NULL; - switch (CLEAN_HINTS_TYPE(currentMode)) { + switch (HINTS_GET_TYPE(currentMode)) { case HINTS_TYPE_LINK: if (input == NULL) { xpath = g_strdup( @@ -452,9 +483,8 @@ static gboolean hints_changed_callback(GtkEditable *entry, gpointer data) { const gchar* text = GET_TEXT(); - if (text[0] == '.' || text[0] == ',') { - hints_create(text + 1, currentMode); - } + /* skip hinting prefixes like '. ', ', ', ';y' ... */ + hints_create(text + 2, currentMode); return TRUE; } diff --git a/src/hints.h b/src/hints.h index 2e7c4c9..8286697 100644 --- a/src/hints.h +++ b/src/hints.h @@ -22,25 +22,38 @@ #include "main.h" -#define CLEAN_HINTS_TYPE(type) ((type) & ~(HINTS_OPEN_USE | HINTS_CLICK_BLANK)) - -enum { +#define HINTS_GET_TYPE(type) ((type) & (HINTS_TYPE_LAST)) +#define HINTS_GET_PROCESSING(type) ((type) & ~(HINTS_TYPE_LAST | HINTS_PROCESS | HINTS_TARGET_BLANK)) + +/* +bits 1 and 2 form the hint type +3: 0 = click hint 1 = process source +4: 0 = open current 1 = open in new window +all further bits are used for processing types +*/ +typedef enum { HINTS_TYPE_LINK, HINTS_TYPE_IMAGE, HINTS_TYPE_DEFAULT, - HINTS_TYPE_FORM + HINTS_TYPE_FORM, + HINTS_TYPE_LAST = HINTS_TYPE_FORM, } HintsType; enum { - HINTS_OPEN_CLICK, - HINTS_OPEN_USE = (1 << 2) + HINTS_CLICK, + HINTS_PROCESS = (1 << 2) }; enum { - HINTS_CLICK_CURRENT, - HINTS_CLICK_BLANK = (1 << 3) + HINTS_TARGET_CURRENT, + HINTS_TARGET_BLANK = (1 << 3) }; +typedef enum { + HINTS_PROCESS_INPUT = (1 << 4), + HINTS_PROCESS_YANK +} HintsProcess; + void hints_create(const gchar* input, guint mode); void hints_update(const gulong num); void hints_clear(void);