// // !!! THIS IS STILL A CONCEPT/PROTOTYPE. USE AT YOUR OWN RISK !!! // // Author: Michal Idziorek // // Last Update: 16th March 2018 // // Last Tested: with surf commit 81f0452bc6c2a110239fa303ad1e72f11c33dc94 // from htps://git.suckless.org/surf // // The following simple Webkit2GTK+ extension was hacked together // in the sleepless night between 09th and 10th March 2018 (and later // refined). // // The DOM is manipulated,i.e: a with a number added to every // link encountered. // // Named FIFO pipes are used for communication with the ui process. // // TODO: g_free where appropriate !! // TODO: allow focus on input boxes/forms // TODO: 1024 hardcoded doc references!. make dynamic and free unused. // TODO: more todos directly in source // TODO: implement New window in surf on msg receive // TODO: fix hints positions! // #include #include #include #include #include #include #include "piper_webext.h" #define CSS_CLASS_NAME "webext_piper_hint" #define MAX_DOCS 1024 WebKitDOMHTMLDocument *my_doc[MAX_DOCS]; bool hints_active[MAX_DOCS]; void hide_hints(WebKitDOMHTMLDocument *doc,int skip) { WebKitDOMNodeList *hints=webkit_dom_document_get_elements_by_class_name (doc,CSS_CLASS_NAME); gulong c=webkit_dom_node_list_get_length (hints); int s=0; for(gulong i=0;i%03d", CSS_CLASS_NAME,(int)webkit_dom_element_get_scroll_left(body)+(int)webkit_dom_client_rect_get_left(rect),(int)webkit_dom_element_get_scroll_top(body)+(int)webkit_dom_client_rect_get_top(rect),i); webkit_dom_element_insert_adjacent_html (body,"beforeend",buf,NULL); } } void toggle_hints(int i) { if(hints_active[i]) { hide_hints(my_doc[i],-1); hints_active[i]=false; return; } show_hints(my_doc[i]); hints_active[i]=true; } void document_loaded_callback (WebKitWebPage *web_page, GPtrArray *elements, GVariant *user_data) { int id=webkit_web_page_get_id(web_page); g_print("Document Loaded Callback Called (page id:%i)\n",id); hints_active[id]=false; my_doc[id] = webkit_web_page_get_dom_document(web_page); } void page_created_callback (WebKitWebExtension *extension, WebKitWebPage *web_page, GVariant *user_data) { g_print("Page Created Callback Called\n"); g_signal_connect (web_page, "document-loaded", G_CALLBACK (document_loaded_callback), user_data); } static void follow_link(int id,int link_num,bool new_win) { WebKitDOMHTMLCollection *links = webkit_dom_document_get_links(my_doc[id]); gulong c = webkit_dom_html_collection_get_length (links); if(link_num>=c)return; WebKitDOMHTMLAnchorElement *node = webkit_dom_html_collection_item (links,link_num); if(!new_win) { hide_hints(my_doc[id],link_num); hints_active[id]=false; webkit_dom_html_element_click(node); return; } char *href=webkit_dom_html_anchor_element_get_href (node); char buf[1024]; snprintf(buf,1024,"%s\n",href); piper_send(buf); } void rcv(char *msg) { static int num[3]; static int l=0; static bool new=false; int id; int cmd; sscanf(msg,"%d %d",&id,&cmd); if(cmd<10) { num[l++]=cmd; if(l==3) { int link_num=100*num[0]+10*num[1]+num[2]; g_printf("link_num: %i\n",link_num); l=0; follow_link(id,link_num,new); } } else { l=0; if(cmd==100)new=false; if(cmd==101)new=true; toggle_hints(id); } } G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data (WebKitWebExtension *extension, GVariant *user_data) { g_print("webext started [%i]\n",getpid()); piper_init("surf-to-ext","ext-to-surf",rcv,NULL); g_signal_connect (extension, "page-created", G_CALLBACK (page_created_callback), user_data ); }