diff --git a/amiga/ctxmenu.c b/amiga/ctxmenu.c index 2b7575321..bf16e21b0 100644 --- a/amiga/ctxmenu.c +++ b/amiga/ctxmenu.c @@ -23,29 +23,43 @@ #ifdef __amigaos4__ #include +#include #include -#include + +#include #include +#include +#include + #include #include #include "amiga/ctxmenu.h" #include "amiga/gui.h" #include "amiga/libs.h" +#include "amiga/theme.h" +#include "amiga/utf8.h" + +#include "desktop/browser.h" +#include "desktop/mouse.h" #include "utils/log.h" +#include "utils/messages.h" +#include "utils/nsoption.h" enum { AMI_CTX_ID_TEST = 1, + AMI_CTX_ID_URLOPEN, + AMI_CTX_ID_URLOPENWIN, + AMI_CTX_ID_URLOPENTAB, AMI_CTX_ID_MAX }; static Object *ctxmenu_obj = NULL; -static struct Hook ctxmenu_hook; static struct Hook ctxmenu_item_hook[AMI_CTX_ID_MAX]; static char *ctxmenu_item_label[AMI_CTX_ID_MAX]; -static char *ctxmenu_item_image[AMI_CTX_ID_MAX]; +static Object *ctxmenu_item_image[AMI_CTX_ID_MAX]; /** Menu functions - called automatically by RA_HandleInput **/ HOOKF(void, ami_ctxmenu_item_test, APTR, window, struct IntuiMessage *) @@ -53,57 +67,143 @@ HOOKF(void, ami_ctxmenu_item_test, APTR, window, struct IntuiMessage *) printf("testing\n"); } -/** Hook function called by Intuition, creates context menu structure **/ -static uint32 ctxmenu_hook_func(struct Hook *hook, struct Window *window, struct ContextMenuMsg *msg) +HOOKF(void, ami_ctxmenu_item_urlopentab, APTR, window, struct IntuiMessage *) { - if(msg->State != CM_QUERY) return 0; + struct browser_window *bw; + nsurl *url = (nsurl *)hook->h_Data; + struct gui_window_2 *gwin; - ctxmenu_item_hook[AMI_CTX_ID_TEST].h_Entry = (void *)ami_ctxmenu_item_test; - ctxmenu_item_hook[AMI_CTX_ID_TEST].h_Data = 0; + GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin); + nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY | BW_CREATE_TAB, + url, + browser_window_get_url(gwin->gw->bw), + gwin->gw->bw, + &bw); + + if (error != NSERROR_OK) + warn_user(messages_get_errorcode(error), 0); +} + +HOOKF(void, ami_ctxmenu_item_urlopenwin, APTR, window, struct IntuiMessage *) +{ + struct browser_window *bw; + nsurl *url = (nsurl *)hook->h_Data; + struct gui_window_2 *gwin; + + GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin); + nserror error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY, + url, + browser_window_get_url(gwin->gw->bw), + gwin->gw->bw, + &bw); + + if (error != NSERROR_OK) + warn_user(messages_get_errorcode(error), 0); +} + + +/** Add an initialised item to a context menu **/ +static void ami_ctxmenu_add_item(Object *root_menu, int id, APTR data) +{ + ctxmenu_item_hook[id].h_Data = data; + + IDoMethod(root_menu, OM_ADDMEMBER, MStrip, + MA_Type, T_ITEM, + MA_Label, ctxmenu_item_label[id], + MA_ID, id, + MA_Image, ctxmenu_item_image[id], + MA_UserData, &ctxmenu_item_hook[id], + MEnd); +} + +/** Hook function called by Intuition, creates context menu structure **/ +static uint32 ami_ctxmenu_hook_func(struct Hook *hook, struct Window *window, struct ContextMenuMsg *msg) +{ + Object *root_menu; + bool ctxmenu_has_content = false; + struct gui_window_2 *gwin = hook->h_Data; + struct hlcache_handle *cc = browser_window_get_content(gwin->gw->bw); + struct browser_window_features ccdata; + int mx = window->MouseX; + int my = window->MouseY; + int x, y; + + if(msg->State != CM_QUERY) return 0; + if(nsoption_bool(kiosk_mode) == true) return 0; +// check window is active if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj); ctxmenu_obj = MStrip, MA_Type, T_ROOT, - MA_AddChild, MStrip, + MA_AddChild, root_menu = MStrip, MA_Type, T_MENU, MA_Label, NULL, //"NetSurf", - MA_AddChild, MStrip, - MA_Type, T_ITEM, - MA_Label, ctxmenu_item_label[AMI_CTX_ID_TEST], - MA_ID, AMI_CTX_ID_TEST, - MA_Image, BitMapObj, - IA_Scalable, TRUE, - BITMAP_SourceFile, ctxmenu_item_image[AMI_CTX_ID_TEST], - BITMAP_Screen, scrn, - BITMAP_Masking, TRUE, - BITMAP_Width, 16, - BITMAP_Height, 16, - BitMapEnd, - MA_UserData, &ctxmenu_item_hook[AMI_CTX_ID_TEST], - MEnd, + MA_EmbeddedKey, FALSE, + MA_FreeImage, FALSE, MEnd, MEnd; - msg->Menu = ctxmenu_obj; + if(ami_mouse_to_ns_coords(gwin, &x, &y, mx, my) == false) { + /* Outside browser render area */ + return 0; + } + + browser_window_get_features(gwin->gw->bw, x, y, &ccdata); + + if(ccdata.link) { + ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENTAB, ccdata.link); + ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENWIN, ccdata.link); + ctxmenu_has_content = true; + } + + if(ctxmenu_has_content == true) { + msg->Menu = ctxmenu_obj; + ami_set_pointer(gwin, GUI_POINTER_DEFAULT, false); + } return 0; } -/** Exported interface documented in ctxmenu.h **/ -struct Hook *ami_ctxmenu_get_hook(void) +/** Initial menu item creation **/ +static void ami_ctxmenu_alloc_item(int id, const char *label, const char *image, void *func) { - return &ctxmenu_hook; + ctxmenu_item_label[id] = ami_utf8_easy(messages_get(label)); + ctxmenu_item_image[id] = BitMapObj, + BITMAP_Screen, scrn, + BITMAP_SourceFile, image, + BITMAP_Masking, TRUE, + BitMapEnd; + + SetAttrs(ctxmenu_item_image[id], + BITMAP_Width, 16, + BITMAP_Height, 16, + TAG_DONE); + + ctxmenu_item_hook[id].h_Entry = func; + ctxmenu_item_hook[id].h_Data = 0; +} + +/** Exported interface documented in ctxmenu.h **/ +struct Hook *ami_ctxmenu_get_hook(APTR data) +{ + return AllocSysObjectTags(ASOT_HOOK, + ASOHOOK_Entry, (HOOKFUNC)ami_ctxmenu_hook_func, + ASOHOOK_Data, data, + TAG_DONE); +} + +/** Exported interface documented in ctxmenu.h **/ +void ami_ctxmenu_release_hook(struct Hook *hook) +{ + FreeSysObject(ASOT_HOOK, hook); } /** Exported interface documented in ctxmenu.h **/ void ami_ctxmenu_init(void) { - ctxmenu_hook.h_Entry = (HOOKFUNC)ctxmenu_hook_func; - ctxmenu_hook.h_Data = 0; - - ctxmenu_item_label[AMI_CTX_ID_TEST] = strdup("test item"); - ctxmenu_item_image[AMI_CTX_ID_TEST] = strdup("TBimages:list_info"); + ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENWIN, "LinkNewWin", "TBImages:list_app", ami_ctxmenu_item_urlopenwin); + ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENTAB, "LinkNewTab", "TBImages:list_add", ami_ctxmenu_item_urlopentab); } /** Exported interface documented in ctxmenu.h **/ @@ -111,11 +211,12 @@ void ami_ctxmenu_free(void) { for(int i = 1; i < AMI_CTX_ID_MAX; i++) { if(ctxmenu_item_label[i] != NULL) { - free(ctxmenu_item_label[i]); + ami_utf8_free(ctxmenu_item_label[i]); ctxmenu_item_label[i] = NULL; } + if(ctxmenu_item_image[i] != NULL) { - free(ctxmenu_item_image[i]); + DisposeObject(ctxmenu_item_image[i]); ctxmenu_item_image[i] = NULL; } } diff --git a/amiga/ctxmenu.h b/amiga/ctxmenu.h index e23c723f1..678208647 100644 --- a/amiga/ctxmenu.h +++ b/amiga/ctxmenu.h @@ -26,7 +26,8 @@ struct Hook; /** - * Initialise context menus code + * Initialise context menus code (allocate label text, etc) + * Must be called *after* NetSurf's screen pointer is obtained. */ void ami_ctxmenu_init(void); @@ -38,8 +39,20 @@ void ami_ctxmenu_free(void); /** * Get a Hook for WA_ContextMenuHook * + * \param data ptr for the hook to use (struct gui_window_2 *) * \returns pointer to a struct Hook */ -struct Hook *ami_ctxmenu_get_hook(void); -#endif +struct Hook *ami_ctxmenu_get_hook(APTR data); +/** + * Release a Hook for WA_ContextMenuHook + * + * \param hook ptr to hook + */ +void ami_ctxmenu_release_hook(struct Hook *hook); +#else +inline void ami_ctxmenu_init(void) {} +inline void ami_ctxmenu_free(void) {} +inline struct Hook *ami_ctxmenu_get_hook(APTR data) {return NULL;} +inline void ami_ctxmenu_release_hook(struct Hook *hook) {} +#endif diff --git a/amiga/gui.c b/amiga/gui.c index 46973f282..9b312e52f 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -1318,7 +1318,7 @@ static bool ami_spacebox_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y, return true; } -static bool ami_mouse_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y, +bool ami_mouse_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y, int mouse_x, int mouse_y) { int ns_x, ns_y; @@ -3769,6 +3769,8 @@ gui_window_create(struct browser_window *bw, newprefs_hook.h_Entry = (void *)ami_gui_newprefs_hook; newprefs_hook.h_Data = 0; + + g->shared->ctxmenu_hook = ami_ctxmenu_get_hook(g->shared); if(nsoption_bool(window_simple_refresh) == true) { refresh_mode = WA_SimpleRefresh; @@ -3932,7 +3934,7 @@ gui_window_create(struct browser_window *bw, WA_ReportMouse,TRUE, refresh_mode, TRUE, WA_SizeBBottom, TRUE, - WA_ContextMenuHook, ami_ctxmenu_get_hook(), + WA_ContextMenuHook, g->shared->ctxmenu_hook, WA_IDCMP, IDCMP_MENUPICK | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE | IDCMP_RAWKEY | idcmp_sizeverify | @@ -4376,7 +4378,6 @@ static void gui_window_destroy(struct gui_window *g) DisposeObject(g->shared->objects[OID_MAIN]); ami_gui_appicon_remove(g->shared); if(g->shared->appwin) RemoveAppWindow(g->shared->appwin); - ami_gui_hotlist_toolbar_free(g->shared, &g->shared->hotlist_toolbar_list); /* These aren't freed by the above. @@ -4390,6 +4391,7 @@ static void gui_window_destroy(struct gui_window *g) ami_gui_opts_websearch_free(g->shared->web_search_list); if(g->shared->search_bm) DisposeObject(g->shared->search_bm); + ami_ctxmenu_release_hook(g->shared->ctxmenu_hook); ami_free_menulabs(g->shared); #ifndef __amigaos4__ ami_menu_free_os3(g->shared); @@ -5433,7 +5435,6 @@ int main(int argc, char** argv) ami_amiupdate(); /* set env-vars for AmiUpdate */ ami_init_fonts(); ami_context_menu_init(); - ami_ctxmenu_init(); save_complete_init(); ami_theme_init(); ami_init_mouse_pointers(); @@ -5449,6 +5450,8 @@ int main(int argc, char** argv) gui_init2(argc, argv); + ami_ctxmenu_init(); /* Requires screen pointer */ + ami_gui_splash_close(splash_window); strlcpy(script, nsoption_charp(arexx_dir), 1024); diff --git a/amiga/gui.h b/amiga/gui.h old mode 100755 new mode 100644 index 7ac140b19..9f8284b56 --- a/amiga/gui.h +++ b/amiga/gui.h @@ -132,6 +132,7 @@ struct gui_window_2 { struct DiskObject *dobj; /* iconify appicon */ struct Hook favicon_hook; struct Hook throbber_hook; + struct Hook *ctxmenu_hook; gui_drag_type drag_op; struct IBox *ptr_lock; struct AppWindow *appwin; @@ -174,6 +175,8 @@ void ami_schedule_redraw(struct gui_window_2 *gwin, bool full_redraw); STRPTR ami_locale_langs(void); int ami_key_to_nskey(ULONG keycode, struct InputEvent *ie); bool ami_text_box_at_point(struct gui_window_2 *gwin, ULONG *x, ULONG *y); +bool ami_mouse_to_ns_coords(struct gui_window_2 *gwin, int *x, int *y, + int mouse_x, int mouse_y); BOOL ami_gadget_hit(Object *obj, int x, int y); void ami_gui_history(struct gui_window_2 *gwin, bool back); void ami_gui_hotlist_update_all(void);