Merge branch 'chris/menuclass'

This replaces the old popupmenu.class-based context menus with Intuition-based ones.  This provides the following advantages:
- No more RMBTrap, so menu shortcuts work without having to be manually handled
- Standard menus now display when not over a contextual zone, so the not-really-contextual menu items have been removed
- No buggy system crash problems, so they are always enabled now
- Menus can be attached directly to gadgets, so the history menu is now attached directly to the back/forward buttons (however they now need to be periodically refreshed as they can't be created on demand)

Additionally, the menu items now have images.
popupmenu.class is now only used (optionally) for form select menus.  This code has been bug-fixed and is now toggleable from the prefs GUI.  However, due to the inability to display more items than fit on the screen, it still isn't recommended to use it.
This commit is contained in:
Chris Young 2015-09-05 16:38:48 +01:00
commit 1a8cf5b7a7
18 changed files with 887 additions and 1519 deletions

View File

@ -70,12 +70,13 @@ MESSAGES_FILTER=ami
S_AMIGA := gui.c tree.c history.c hotlist.c schedule.c file.c \
misc.c bitmap.c font.c filetype.c utf8.c login.c \
plotters.c object.c menu.c save_pdf.c arexx.c version.c \
cookies.c context_menu.c clipboard.c help.c font_scan.c \
cookies.c ctxmenu.c clipboard.c help.c font_scan.c \
launch.c search.c history_local.c download.c iff_dr2d.c \
sslcert.c gui_options.c print.c theme.c drag.c icon.c libs.c \
datatypes.c dt_picture.c dt_anim.c dt_sound.c plugin_hack.c \
stringview/stringview.c stringview/urlhistory.c rtg.c \
agclass/amigaguide_class.c os3support.c font_bitmap.c
agclass/amigaguide_class.c os3support.c font_bitmap.c \
selectmenu.c
S_AMIGA := $(addprefix amiga/,$(S_AMIGA))
# This is the final source build list

View File

@ -19,6 +19,7 @@
#ifndef AMIGA_BITMAP_H
#define AMIGA_BITMAP_H
#include <stdbool.h>
#include <exec/types.h>
#include <proto/graphics.h>
#include <intuition/classusr.h>

View File

@ -327,7 +327,7 @@ void ami_drag_selection(struct gui_window *g)
}
}
bool ami_easy_clipboard(char *text)
bool ami_easy_clipboard(const char *text)
{
gui_set_clipboard(text, strlen(text), NULL, 0);
return true;

View File

@ -34,7 +34,7 @@ void gui_start_selection(struct gui_window *g);
void ami_clipboard_init(void);
void ami_clipboard_free(void);
void ami_drag_selection(struct gui_window *g);
bool ami_easy_clipboard(char *text);
bool ami_easy_clipboard(const char *text);
bool ami_easy_clipboard_bitmap(struct bitmap *bitmap);
#ifdef WITH_NS_SVG
bool ami_easy_clipboard_svg(struct hlcache_handle *c);

File diff suppressed because it is too large Load Diff

557
amiga/ctxmenu.c Normal file
View File

@ -0,0 +1,557 @@
/*
* Copyright 2015 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Intuition-based context menu operations
*/
#ifdef __amigaos4__
#include <string.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/bitmap.h>
#include <images/bitmap.h>
#include <proto/window.h>
#include <classes/window.h>
#include <intuition/menuclass.h>
#include <reaction/reaction_macros.h>
#include "amiga/bitmap.h"
#include "amiga/clipboard.h"
#include "amiga/ctxmenu.h"
#include "amiga/filetype.h"
#include "amiga/gui.h"
#include "amiga/libs.h"
#include "amiga/plugin_hack.h"
#include "amiga/theme.h"
#include "amiga/utf8.h"
#include "desktop/browser.h"
#include "desktop/browser_history.h"
#include "desktop/mouse.h"
#include "desktop/textinput.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsoption.h"
enum {
AMI_CTX_ID_NONE = 0,
/* Text selection */
AMI_CTX_ID_SELCOPY,
/* Links */
AMI_CTX_ID_URLOPENTAB,
AMI_CTX_ID_URLOPENWIN,
AMI_CTX_ID_URLDOWNLOAD,
AMI_CTX_ID_URLCOPY,
/* Objects */
AMI_CTX_ID_OBJSHOW,
AMI_CTX_ID_OBJCOPY,
AMI_CTX_ID_OBJCMD,
/* Frames */
AMI_CTX_ID_FRAMESHOW,
/* History */
AMI_CTX_ID_HISTORY,
AMI_CTX_ID_HISTORY0,
AMI_CTX_ID_HISTORY9F = AMI_CTX_ID_HISTORY0 + 19,
/* Tabs */
AMI_CTX_ID_TABNEW,
AMI_CTX_ID_MAX
};
static Object *ctxmenu_obj = NULL;
static struct Hook ctxmenu_item_hook[AMI_CTX_ID_MAX];
static char *ctxmenu_item_label[AMI_CTX_ID_MAX];
static char *ctxmenu_item_shortcut[AMI_CTX_ID_MAX];
static Object *ctxmenu_item_image[AMI_CTX_ID_MAX];
/****************************
* Menu item hook functions *
****************************/
/** Menu functions - called automatically by RA_HandleInput **/
HOOKF(void, ami_ctxmenu_item_selcopy, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin = (struct gui_window_2 *)hook->h_Data;
browser_window_key_press(gwin->gw->bw, NS_KEY_COPY_SELECTION);
browser_window_key_press(gwin->gw->bw, NS_KEY_CLEAR_SELECTION);
}
HOOKF(void, ami_ctxmenu_item_urlopentab, 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 | 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);
}
HOOKF(void, ami_ctxmenu_item_urldownload, APTR, window, struct IntuiMessage *)
{
nsurl *url = (nsurl *)hook->h_Data;
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
browser_window_navigate(gwin->gw->bw,
url,
browser_window_get_url(gwin->gw->bw),
BW_NAVIGATE_DOWNLOAD,
NULL,
NULL,
NULL);
}
HOOKF(void, ami_ctxmenu_item_urlcopy, APTR, window, struct IntuiMessage *)
{
nsurl *url = (nsurl *)hook->h_Data;
ami_easy_clipboard(nsurl_access(url));
}
HOOKF(void, ami_ctxmenu_item_objshow, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
browser_window_navigate(gwin->gw->bw,
hlcache_handle_get_url(hook->h_Data),
browser_window_get_url(gwin->gw->bw),
BW_NAVIGATE_HISTORY,
NULL,
NULL,
NULL);
}
HOOKF(void, ami_ctxmenu_item_objcopy, APTR, window, struct IntuiMessage *)
{
struct bitmap *bm;
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
struct hlcache_handle *object = (struct hlcache_handle *)hook->h_Data;
if((bm = content_get_bitmap(object)))
{
bm->url = (char *)nsurl_access(hlcache_handle_get_url(object));
bm->title = (char *)content_get_title(object);
ami_easy_clipboard_bitmap(bm);
}
#ifdef WITH_NS_SVG
else if(ami_mime_compare(object, "svg") == true)
{
ami_easy_clipboard_svg(object);
}
#endif
}
HOOKF(void, ami_ctxmenu_item_objcmd, APTR, window, struct IntuiMessage *)
{
amiga_plugin_hack_execute((struct hlcache_handle *)hook->h_Data);
}
HOOKF(void, ami_ctxmenu_item_frameshow, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
browser_window_navigate(gwin->gw->bw,
hlcache_handle_get_url(hook->h_Data),
browser_window_get_url(gwin->gw->bw),
BW_NAVIGATE_HISTORY,
NULL,
NULL,
NULL);
}
/** Hooks for clicktab context menu entries **/
HOOKF(void, ami_ctxmenu_item_tabnew, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
ami_gui_new_blank_tab(gwin);
}
/** Hook for history context menu entries **/
HOOKF(void, ami_ctxmenu_item_history, APTR, window, struct IntuiMessage *)
{
struct gui_window_2 *gwin;
GetAttr(WINDOW_UserData, (Object *)window, (ULONG *)&gwin);
browser_window_history_go(gwin->gw->bw, (struct history_entry *)hook->h_Data, false);
}
/*************************
* Browser context menus *
*************************/
/** 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_ID, id,
MA_Label, ctxmenu_item_label[id],
MA_Key, ctxmenu_item_shortcut[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, root_menu = MStrip,
MA_Type, T_MENU,
MA_Label, NULL, //"NetSurf",
MA_EmbeddedKey, FALSE,
MA_FreeImage, FALSE,
MEnd,
MEnd;
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((browser_window_can_select(gwin->gw->bw)) &&
((browser_window_get_editor_flags(gwin->gw->bw) & BW_EDITOR_CAN_COPY))) {
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_SELCOPY, gwin);
ctxmenu_has_content = true;
}
if(ccdata.link) {
if(ctxmenu_has_content == true)
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENTAB, ccdata.link);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLOPENWIN, ccdata.link);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLDOWNLOAD, ccdata.link);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_URLCOPY, ccdata.link);
ctxmenu_has_content = true;
}
if(ccdata.object) {
if(ctxmenu_has_content == true)
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJSHOW, ccdata.object);
if(content_get_type(ccdata.object) == CONTENT_IMAGE)
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCOPY, ccdata.object);
if(ami_mime_content_to_cmd(ccdata.object))
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_OBJCMD, ccdata.object);
ctxmenu_has_content = true;
}
if(ccdata.main && (ccdata.main != cc)) {
if(ctxmenu_has_content == true)
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_NONE, NULL);
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_FRAMESHOW, ccdata.main);
ctxmenu_has_content = true;
}
if(ctxmenu_has_content == true) {
msg->Menu = ctxmenu_obj;
ami_set_pointer(gwin, GUI_POINTER_DEFAULT, false);
}
return 0;
}
/** Initial menu item creation **/
static void ami_ctxmenu_alloc_item(int id, const char *label, const char *key, const char *image, void *func)
{
if(label == ML_SEPARATOR) {
ctxmenu_item_label[id] = ML_SEPARATOR;
} else {
ctxmenu_item_label[id] = ami_utf8_easy(messages_get(label));
}
if(key != NULL) {
ctxmenu_item_shortcut[id] = strdup(key);
} else {
ctxmenu_item_shortcut[id] = NULL;
}
if(image != NULL) {
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_free(void)
{
for(int i = 1; i < AMI_CTX_ID_MAX; i++) {
if((ctxmenu_item_label[i] != NULL) && (ctxmenu_item_label[i] != ML_SEPARATOR)) {
ami_utf8_free(ctxmenu_item_label[i]);
}
ctxmenu_item_label[i] = NULL;
if(ctxmenu_item_shortcut[i] != NULL) {
free(ctxmenu_item_shortcut[i]);
ctxmenu_item_shortcut[i] = NULL;
}
if(ctxmenu_item_image[i] != NULL) {
DisposeObject(ctxmenu_item_image[i]);
ctxmenu_item_image[i] = NULL;
}
}
if(ctxmenu_obj != NULL) DisposeObject(ctxmenu_obj);
ctxmenu_obj = NULL;
}
/** Exported interface documented in ctxmenu.h **/
void ami_ctxmenu_init(void)
{
ami_ctxmenu_alloc_item(AMI_CTX_ID_NONE, ML_SEPARATOR, NULL, NULL, NULL);
ami_ctxmenu_alloc_item(AMI_CTX_ID_SELCOPY, "CopyNS", "C", "TBImages:list_copy",
ami_ctxmenu_item_selcopy);
ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENTAB, "LinkNewTab", NULL, "TBImages:list_tab",
ami_ctxmenu_item_urlopentab);
ami_ctxmenu_alloc_item(AMI_CTX_ID_URLOPENWIN, "LinkNewWin", NULL, "TBImages:list_app",
ami_ctxmenu_item_urlopenwin);
ami_ctxmenu_alloc_item(AMI_CTX_ID_URLDOWNLOAD, "LinkDload", NULL, "TBImages:list_save",
ami_ctxmenu_item_urldownload);
ami_ctxmenu_alloc_item(AMI_CTX_ID_URLCOPY, "CopyURL", NULL, "TBImages:list_copy",
ami_ctxmenu_item_urlcopy);
ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJSHOW, "ObjShow", NULL, "TBImages:list_preview",
ami_ctxmenu_item_objshow);
ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCOPY, "CopyClip", NULL, "TBImages:list_copy",
ami_ctxmenu_item_objcopy);
ami_ctxmenu_alloc_item(AMI_CTX_ID_OBJCMD, "ExternalApp", NULL, "TBImages:list_tool",
ami_ctxmenu_item_objcmd);
ami_ctxmenu_alloc_item(AMI_CTX_ID_FRAMESHOW, "FrameOnly", NULL, "TBImages:list_preview",
ami_ctxmenu_item_frameshow);
ami_ctxmenu_alloc_item(AMI_CTX_ID_TABNEW, "NewTab", "T", "TBImages:list_add",
ami_ctxmenu_item_tabnew);
}
/********************************
* History button context menus *
********************************/
/** Create menu entries from browser history **/
static bool ami_ctxmenu_history(int direction, struct gui_window_2 *gwin, const struct history_entry *entry)
{
Object *history_root;
int id = AMI_CTX_ID_HISTORY0 + gwin->temp;
if(direction == AMI_CTXMENU_HISTORY_FORWARD) id += 10;
if(gwin->temp >= 10) return false;
ctxmenu_item_hook[id].h_Entry = (HOOKFUNC)ami_ctxmenu_item_history;
ctxmenu_item_hook[id].h_Data = (APTR)entry;
history_root = (Object *)IDoMethod(gwin->history_ctxmenu[direction], MM_FINDID, 0, AMI_CTX_ID_HISTORY);
IDoMethod(history_root, OM_ADDMEMBER, MStrip,
MA_Type, T_ITEM,
MA_Label, browser_window_history_entry_get_title(entry),
MA_ID, id,
MA_Image, NULL,
MA_UserData, &ctxmenu_item_hook[id],
MEnd);
gwin->temp++;
return true;
}
/** Callback for browser_window_history_enumerate **/
static bool ami_ctxmenu_history_back(const struct browser_window *bw,
int x0, int y0, int x1, int y1,
const struct history_entry *entry, void *user_data)
{
return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_BACK, (struct gui_window_2 *)user_data, entry);
}
/** Callback for browser_window_history_enumerate **/
static bool ami_ctxmenu_history_forward(const struct browser_window *bw,
int x0, int y0, int x1, int y1,
const struct history_entry *entry, void *user_data)
{
return ami_ctxmenu_history(AMI_CTXMENU_HISTORY_FORWARD, (struct gui_window_2 *)user_data, entry);
}
/** Exported interface documented in ctxmenu.h **/
struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin)
{
Object *obj;
if(gwin->history_ctxmenu[direction] == NULL) {
if(ctxmenu_item_label[AMI_CTX_ID_HISTORY] == NULL)
ctxmenu_item_label[AMI_CTX_ID_HISTORY] = ami_utf8_easy(messages_get("History"));
gwin->history_ctxmenu[direction] = MStrip,
MA_Type, T_ROOT,
MA_AddChild, MStrip,
MA_Type, T_MENU,
MA_ID, AMI_CTX_ID_HISTORY,
MA_Label, ctxmenu_item_label[AMI_CTX_ID_HISTORY],
MA_EmbeddedKey, FALSE,
//MA_FreeImage, FALSE,
MEnd,
MEnd;
} else {
for (int i = 0; i < 20; i++) {
obj = (Object *)IDoMethod(gwin->history_ctxmenu[direction],
MM_FINDID, 0, AMI_CTX_ID_HISTORY0 + i);
if(obj != NULL) IDoMethod(gwin->history_ctxmenu[direction], OM_REMMEMBER, obj);
}
gwin->temp = 0;
if(direction == AMI_CTXMENU_HISTORY_BACK) {
browser_window_history_enumerate_back(gwin->gw->bw, ami_ctxmenu_history_back, gwin);
} else {
browser_window_history_enumerate_forward(gwin->gw->bw, ami_ctxmenu_history_forward, gwin);
}
}
return (struct Menu *)gwin->history_ctxmenu[direction];
}
/**************************
* ClickTab context menus *
**************************/
/** Exported interface documented in ctxmenu.h **/
struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin)
{
Object *root_menu;
if(gwin->clicktab_ctxmenu != NULL) return (struct Menu *)gwin->clicktab_ctxmenu;
gwin->clicktab_ctxmenu = MStrip,
MA_Type, T_ROOT,
MA_AddChild, root_menu = MStrip,
MA_Type, T_MENU,
MA_Label, NULL,
MA_EmbeddedKey, FALSE,
MEnd,
MEnd;
ami_ctxmenu_add_item(root_menu, AMI_CTX_ID_TABNEW, gwin);
return (struct Menu *)gwin->clicktab_ctxmenu;
}
#endif

89
amiga/ctxmenu.h Normal file
View File

@ -0,0 +1,89 @@
/*
* Copyright 2015 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* Interface to Intuition-based context menu operations
*/
#ifndef AMIGA_CTXMENU_H
#define AMIGA_CTXMENU_H 1
struct Hook;
struct Menu;
struct gui_window_2;
enum {
AMI_CTXMENU_HISTORY_BACK = 0,
AMI_CTXMENU_HISTORY_FORWARD = 1
};
/**
* Initialise context menus code (allocate label text, etc)
* Must be called *after* NetSurf's screen pointer is obtained.
*/
void ami_ctxmenu_init(void);
/**
* Cleanup context menus code
*/
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(APTR data);
/**
* Release a Hook for WA_ContextMenuHook
*
* \param hook ptr to hook
*/
void ami_ctxmenu_release_hook(struct Hook *hook);
/**
* Create history context menu
* The first time this is run it will create an empty menu,
* Subsequent runs will (re-)populate with the history.
* This is to allow the pointer to be obtained before the browser_window is opened.
*
* \param direction AMI_CTXMENU_HISTORY_(BACK|FORWARD)
* \param gwin struct gui_window_2 *
* \returns pointer to menu (for convenience, is also stored in gwin structure)
* The returned pointer MUST be disposed of with DisposeObject before program exit.
*/
struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin);
/**
* Create ClickTab context menu
*
* \param gwin struct gui_window_2 *
* \returns pointer to menu (for convenience, is also stored in gwin structure)
* The returned pointer MUST be disposed of with DisposeObject before program exit.
*/
struct Menu *ami_ctxmenu_clicktab_create(struct gui_window_2 *gwin);
#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) {}
inline struct Menu *ami_ctxmenu_history_create(int direction, struct gui_window_2 *gwin) {return NULL;}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008-2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
* Copyright 2008-2015 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -34,9 +34,6 @@
#include <proto/intuition.h>
#include <proto/keymap.h>
#include <proto/locale.h>
#ifdef __amigaos4__
#include <proto/popupmenu.h>
#endif
#include <proto/utility.h>
#include <proto/wb.h>
@ -119,8 +116,8 @@
#include "amiga/arexx.h"
#include "amiga/bitmap.h"
#include "amiga/clipboard.h"
#include "amiga/context_menu.h"
#include "amiga/cookies.h"
#include "amiga/ctxmenu.h"
#include "amiga/datatypes.h"
#include "amiga/download.h"
#include "amiga/drag.h"
@ -144,6 +141,7 @@
#include "amiga/print.h"
#include "amiga/schedule.h"
#include "amiga/search.h"
#include "amiga/selectmenu.h"
#include "amiga/theme.h"
#include "amiga/tree.h"
#include "amiga/utf8.h"
@ -541,9 +539,8 @@ static nserror ami_set_options(struct nsoption_s *defaults)
STRPTR tempacceptlangs;
char temp[1024];
/* The following line disables the popupmenu.class select menu
** This will become a user option when/if popupmenu.class is
** updated to show more items than can fit in one column vertically
/* The following line disables the popupmenu.class select menu.
** It's not recommended to use it!
*/
nsoption_set_bool(core_select_menu, true);
@ -626,9 +623,6 @@ static nserror ami_set_options(struct nsoption_s *defaults)
}
}
if(popupmenu_lib_ok == FALSE)
nsoption_set_bool(context_menu, false);
#ifndef __amigaos4__
nsoption_set_bool(download_notify, false);
nsoption_set_bool(font_antialiasing, false);
@ -1102,6 +1096,10 @@ static void ami_update_buttons(struct gui_window_2 *gwin)
SetGadgetAttrs((struct Gadget *)gwin->objects[GID_CLOSETAB],
gwin->win, NULL, GA_Disabled, tabclose, TAG_DONE);
}
/* Update the back/forward buttons history context menu */
ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_BACK, gwin);
ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_FORWARD, gwin);
}
void ami_gui_history(struct gui_window_2 *gwin, bool back)
@ -1317,7 +1315,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;
@ -1918,7 +1916,6 @@ static void ami_handle_msg(void)
if((x>=xs) && (y>=ys) && (x<width+xs) && (y<height+ys))
{
ami_update_quals(gwin);
ami_context_menu_mouse_trap(gwin, TRUE);
if(gwin->mouse_state & BROWSER_MOUSE_PRESS_1)
{
@ -1934,11 +1931,7 @@ static void ami_handle_msg(void)
{
browser_window_mouse_track(gwin->gw->bw,gwin->mouse_state | gwin->key_state,x,y);
}
}
else
{
ami_context_menu_mouse_trap(gwin, FALSE);
} else {
if(!gwin->mouse_state) ami_set_pointer(gwin, GUI_POINTER_DEFAULT, true);
}
break;
@ -1988,10 +1981,6 @@ static void ami_handle_msg(void)
switch(code)
{
case MENUDOWN:
ami_context_menu_show(gwin,x,y);
break;
case SELECTUP:
if(gwin->mouse_state & BROWSER_MOUSE_PRESS_1)
{
@ -2265,104 +2254,10 @@ static void ami_handle_msg(void)
if((ie->ie_Qualifier & IEQUALIFIER_RCOMMAND) &&
((31 < nskey) && (nskey < 127))) {
/* We are duplicating the menu shortcuts here, as if RMBTRAP is
* active (ie. when context menus are enabled and the mouse is over
* the browser rendering area), Intuition also does not catch the
* menu shortcut key presses. Context menus possibly need to be
* changed to use MENUVERIFY not RMBTRAP.
* NB: Some keypresses are converted to generic keypresses above
* rather than being "menu-emulated" here.
*/
/* NB: Some keypresses are converted to generic keypresses above
* rather than being "menu-emulated" here. */
switch(nskey)
{
case 'n':
if ((nsoption_bool(kiosk_mode) == false)) {
nsurl *urlns;
nserror error;
error = nsurl_create(nsoption_charp(homepage_url), &urlns);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY,
urlns,
NULL,
gwin->gw->bw,
NULL);
nsurl_unref(urlns);
}
if (error != NSERROR_OK) {
warn_user(messages_get_errorcode(error), 0);
}
}
break;
case 't':
if((nsoption_bool(kiosk_mode) == false)) {
nsurl *urlns;
nserror error;
error = nsurl_create(nsoption_charp(homepage_url), &urlns);
if (error == NSERROR_OK) {
error = browser_window_create(BW_CREATE_CLONE | BW_CREATE_HISTORY |
BW_CREATE_TAB,
urlns,
NULL,
gwin->gw->bw,
NULL);
nsurl_unref(urlns);
}
if (error != NSERROR_OK) {
warn_user(messages_get_errorcode(error), 0);
}
}
break;
case 'k':
if((nsoption_bool(kiosk_mode) == false))
browser_window_destroy(gwin->gw->bw);
break;
case 'o':
ami_file_open(gwin);
break;
case 's':
ami_file_save_req(AMINS_SAVE_SOURCE, gwin,
browser_window_get_content(gwin->gw->bw));
break;
case 'p':
ami_print_ui(browser_window_get_content(gwin->gw->bw));
break;
case 'q':
if((nsoption_bool(kiosk_mode) == false))
ami_quit_netsurf();
break;
case 'f':
ami_search_open(gwin->gw);
break;
case 'h':
if((nsoption_bool(kiosk_mode) == false))
ami_tree_open(hotlist_window, AMI_TREE_HOTLIST);
break;
case '-':
if(gwin->gw->scale > 0.1)
ami_gui_set_scale(gwin->gw, gwin->gw->scale - 0.1);
break;
case '=':
ami_gui_set_scale(gwin->gw, 1.0);
break;
case '+':
ami_gui_set_scale(gwin->gw, gwin->gw->scale + 0.1);
break;
/* The following aren't available from the menu at the moment */
case 'r': // reload
@ -3037,7 +2932,7 @@ static void gui_quit(void)
if(nsscreentitle) FreeVec(nsscreentitle);
LOG("Freeing menu items");
ami_context_menu_free();
ami_ctxmenu_free();
ami_menu_free_glyphs();
LOG("Freeing mouse pointers");
@ -3314,6 +3209,7 @@ static void ami_toggletabbar(struct gui_window_2 *gwin, bool show)
GA_ID, GID_TABS,
GA_RelVerify, TRUE,
GA_Underscore, 13, // disable kb shortcuts
GA_ContextMenu, ami_ctxmenu_clicktab_create(gwin),
CLICKTAB_Labels, &gwin->tab_list,
CLICKTAB_LabelTruncate, TRUE,
CLICKTAB_CloseImage, gwin->objects[GID_CLOSETAB_BM],
@ -3849,7 +3745,7 @@ gui_window_create(struct browser_window *bw,
}
ami_NewMinList(&g->shared->shared_pens);
g->shared->scrollerhook.h_Entry = (void *)ami_scroller_hook;
g->shared->scrollerhook.h_Data = g->shared;
@ -3861,6 +3757,11 @@ 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);
g->shared->history_ctxmenu[AMI_CTXMENU_HISTORY_BACK] = NULL;
g->shared->history_ctxmenu[AMI_CTXMENU_HISTORY_FORWARD] = NULL;
g->shared->clicktab_ctxmenu = NULL;
if(nsoption_bool(window_simple_refresh) == true) {
refresh_mode = WA_SimpleRefresh;
@ -4024,6 +3925,7 @@ gui_window_create(struct browser_window *bw,
WA_ReportMouse,TRUE,
refresh_mode, TRUE,
WA_SizeBBottom, TRUE,
WA_ContextMenuHook, g->shared->ctxmenu_hook,
WA_IDCMP, IDCMP_MENUPICK | IDCMP_MOUSEMOVE |
IDCMP_MOUSEBUTTONS | IDCMP_NEWSIZE |
IDCMP_RAWKEY | idcmp_sizeverify |
@ -4051,9 +3953,10 @@ gui_window_create(struct browser_window *bw,
LAYOUT_AddChild, g->shared->objects[GID_TOOLBARLAYOUT] = LayoutHObj,
LAYOUT_VertAlignment, LALIGN_CENTER,
LAYOUT_AddChild, g->shared->objects[GID_BACK] = ButtonObj,
GA_ID,GID_BACK,
GA_RelVerify,TRUE,
GA_Disabled,TRUE,
GA_ID, GID_BACK,
GA_RelVerify, TRUE,
GA_Disabled, TRUE,
GA_ContextMenu, ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_BACK, g->shared),
GA_HintInfo, g->shared->helphints[GID_BACK],
BUTTON_RenderImage,BitMapObj,
BITMAP_SourceFile,nav_west,
@ -4066,9 +3969,10 @@ gui_window_create(struct browser_window *bw,
CHILD_WeightedWidth,0,
CHILD_WeightedHeight,0,
LAYOUT_AddChild, g->shared->objects[GID_FORWARD] = ButtonObj,
GA_ID,GID_FORWARD,
GA_RelVerify,TRUE,
GA_Disabled,TRUE,
GA_ID, GID_FORWARD,
GA_RelVerify, TRUE,
GA_Disabled, TRUE,
GA_ContextMenu, ami_ctxmenu_history_create(AMI_CTXMENU_HISTORY_FORWARD, g->shared),
GA_HintInfo, g->shared->helphints[GID_FORWARD],
BUTTON_RenderImage,BitMapObj,
BITMAP_SourceFile,nav_east,
@ -4423,8 +4327,7 @@ static void gui_window_destroy(struct gui_window *g)
cur_gw = NULL;
if(g->shared->tabs > 1)
{
if(g->shared->tabs > 1) {
SetGadgetAttrs((struct Gadget *)g->shared->objects[GID_TABS],g->shared->win,NULL,
CLICKTAB_Labels,~0,
TAG_DONE);
@ -4467,7 +4370,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.
@ -4481,6 +4383,11 @@ 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);
/* This appears to be disposed along with the ClickTab object
if(g->shared->clicktab_ctxmenu) DisposeObject((Object *)g->shared->clicktab_ctxmenu); */
DisposeObject((Object *)g->shared->history_ctxmenu[AMI_CTXMENU_HISTORY_BACK]);
DisposeObject((Object *)g->shared->history_ctxmenu[AMI_CTXMENU_HISTORY_FORWARD]);
ami_ctxmenu_release_hook(g->shared->ctxmenu_hook);
ami_free_menulabs(g->shared);
#ifndef __amigaos4__
ami_menu_free_os3(g->shared);
@ -4493,8 +4400,7 @@ static void gui_window_destroy(struct gui_window *g)
free(g->shared->helphints[gid]);
DelObject(g->shared->node);
if(g->tab_node)
{
if(g->tab_node) {
Remove(g->tab_node);
FreeClickTabNode(g->tab_node);
}
@ -5446,19 +5352,6 @@ int main(int argc, char** argv)
/* Open splash window */
Object *splash_window = ami_gui_splash_open();
/* Open popupmenu.library just to check the version.
* Versions older than 53.11 are dangerous, so we
* forcibly disable context menus if these are in use.
*/
popupmenu_lib_ok = FALSE;
#ifdef __amigaos4__
if((PopupMenuBase = OpenLibrary("popupmenu.library", 53))) {
LOG("popupmenu.library v%d.%d", PopupMenuBase->lib_Version, PopupMenuBase->lib_Revision);
if(LIB_IS_AT_LEAST((struct Library *)PopupMenuBase, 53, 11))
popupmenu_lib_ok = TRUE;
CloseLibrary(PopupMenuBase);
}
#endif
if (ami_open_resources() == false) { /* alloc message ports */
ami_misc_fatal_error("Unable to allocate resources");
return RETURN_FAIL;
@ -5523,7 +5416,6 @@ int main(int argc, char** argv)
ami_openurl_open();
ami_amiupdate(); /* set env-vars for AmiUpdate */
ami_init_fonts();
ami_context_menu_init();
save_complete_init();
ami_theme_init();
ami_init_mouse_pointers();
@ -5539,6 +5431,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);

15
amiga/gui.h Executable file → Normal file
View File

@ -1,5 +1,5 @@
/*
* Copyright 2008-2014 Chris Young <chris@unsatisfactorysoftware.co.uk>
* Copyright 2008-2015 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@ -18,15 +18,16 @@
#ifndef AMIGA_GUI_H
#define AMIGA_GUI_H
#include <stdbool.h>
#include <graphics/rastport.h>
#include "amiga/object.h"
#include <intuition/classusr.h>
#include <dos/dos.h>
#include <devices/inputevent.h>
#include "amiga/menu.h"
#include "amiga/object.h"
#include "amiga/os3support.h"
#include "amiga/plotters.h"
#include "amiga/menu.h"
#include "desktop/gui_window.h"
#ifdef __amigaos4__
#define HOOKF(ret,func,type,ptr,msgtype) static ret func(struct Hook *hook, type ptr, msgtype msg)
@ -131,6 +132,9 @@ struct gui_window_2 {
struct DiskObject *dobj; /* iconify appicon */
struct Hook favicon_hook;
struct Hook throbber_hook;
struct Hook *ctxmenu_hook;
Object *history_ctxmenu[2];
Object *clicktab_ctxmenu;
gui_drag_type drag_op;
struct IBox *ptr_lock;
struct AppWindow *appwin;
@ -173,6 +177,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);
@ -220,6 +226,5 @@ struct MsgPort *sport;
struct gui_window *cur_gw;
struct gui_globals browserglob;
BOOL ami_autoscroll;
BOOL popupmenu_lib_ok;
#endif

View File

@ -71,6 +71,7 @@
#include "amiga/libs.h"
#include "amiga/misc.h"
#include "amiga/object.h"
#include "amiga/selectmenu.h"
#include "amiga/theme.h"
#include "amiga/utf8.h"
@ -132,7 +133,7 @@ enum
GID_OPTS_TAB_CLOSE,
GID_OPTS_SEARCH_PROV,
GID_OPTS_CLIPBOARD,
GID_OPTS_CONTEXTMENU,
GID_OPTS_SELECTMENU,
GID_OPTS_STARTUP_NO_WIN,
GID_OPTS_CLOSE_NO_QUIT,
GID_OPTS_DOCKY,
@ -328,7 +329,7 @@ static void ami_gui_opts_setup(struct ami_gui_opts_window *gow)
gadlab[GID_OPTS_TAB_CLOSE] = (char *)ami_utf8_easy((char *)messages_get("TabClose"));
gadlab[GID_OPTS_SEARCH_PROV] = (char *)ami_utf8_easy((char *)messages_get("SearchProvider"));
gadlab[GID_OPTS_CLIPBOARD] = (char *)ami_utf8_easy((char *)messages_get("ClipboardUTF8"));
gadlab[GID_OPTS_CONTEXTMENU] = (char *)ami_utf8_easy((char *)messages_get("ContextMenu"));
gadlab[GID_OPTS_SELECTMENU] = (char *)ami_utf8_easy((char *)messages_get("PopupMenu"));
gadlab[GID_OPTS_STARTUP_NO_WIN] = (char *)ami_utf8_easy((char *)messages_get("OptionNoWindow"));
gadlab[GID_OPTS_CLOSE_NO_QUIT] = (char *)ami_utf8_easy((char *)messages_get("OptionNoQuit"));
gadlab[GID_OPTS_DOCKY] = (char *)ami_utf8_easy((char *)messages_get("OptionDocky"));
@ -1360,22 +1361,22 @@ void ami_gui_opts_open(void)
LAYOUT_BevelStyle, BVS_GROUP,
LAYOUT_Label, gadlab[GRP_OPTS_MISC],
LAYOUT_SpaceOuter, TRUE,
#ifdef __amigaos4__
LAYOUT_AddChild, gow->objects[GID_OPTS_CONTEXTMENU] = CheckBoxObj,
GA_ID, GID_OPTS_CONTEXTMENU,
GA_RelVerify, TRUE,
GA_Text, gadlab[GID_OPTS_CONTEXTMENU],
GA_Selected, nsoption_bool(context_menu),
GA_Disabled, !popupmenu_lib_ok,
CheckBoxEnd,
#endif
LAYOUT_AddChild, gow->objects[GID_OPTS_FASTSCROLL] = CheckBoxObj,
GA_ID, GID_OPTS_FASTSCROLL,
GA_RelVerify, TRUE,
GA_Text, gadlab[GID_OPTS_FASTSCROLL],
GA_Selected, nsoption_bool(faster_scroll),
CheckBoxEnd,
LayoutEnd, // context menus
#ifdef __amigaos4__
LAYOUT_AddChild, gow->objects[GID_OPTS_SELECTMENU] = CheckBoxObj,
GA_ID, GID_OPTS_SELECTMENU,
GA_RelVerify, TRUE,
GA_Text, gadlab[GID_OPTS_SELECTMENU],
GA_Selected, !nsoption_bool(core_select_menu),
GA_Disabled, !ami_selectmenu_is_safe(),
CheckBoxEnd,
#endif
LayoutEnd, // misc
CHILD_WeightedHeight, 0,
LayoutEnd, // page vgroup
@ -1855,11 +1856,11 @@ static void ami_gui_opts_use(bool save)
nsoption_set_bool(clipboard_write_utf8, false);
}
GetAttr(GA_Selected,gow->objects[GID_OPTS_CONTEXTMENU],(ULONG *)&data);
GetAttr(GA_Selected,gow->objects[GID_OPTS_SELECTMENU],(ULONG *)&data);
if (data) {
nsoption_set_bool(context_menu, true);
nsoption_set_bool(core_select_menu, false);
} else {
nsoption_set_bool(context_menu, false);
nsoption_set_bool(core_select_menu, true);
}
GetAttr(GA_Selected,gow->objects[GID_OPTS_STARTUP_NO_WIN],(ULONG *)&data);

View File

@ -561,7 +561,7 @@ static void ami_menu_alloc_item(struct gui_window_2 *gwin, int num, UBYTE type,
gwin->menulab[num] = ami_utf8_easy(messages_get(label));
}
}
gwin->menuicon[num] = NULL;
if(key) gwin->menukey[num] = key;
if(func) gwin->menu_hook[num].h_Entry = (HOOKFUNC)func;

View File

@ -34,7 +34,6 @@ NSOPTION_INTEGER(screen_ydpi, 85)
NSOPTION_INTEGER(cache_bitmaps, 0)
NSOPTION_STRING(theme, "PROGDIR:Resources/Themes/Default")
NSOPTION_BOOL(clipboard_write_utf8, false)
NSOPTION_BOOL(context_menu, true)
NSOPTION_BOOL(truecolour_mouse_pointers, false)
NSOPTION_BOOL(os_mouse_pointers, true)
NSOPTION_BOOL(use_openurl_lib, false)

View File

@ -73,6 +73,7 @@
#define GETFONT_ScalableOnly TAG_IGNORE
#define PDTA_PromoteMask TAG_IGNORE
#define RPTAG_APenColor TAG_IGNORE
#define GA_ContextMenu TAG_IGNORE
#define GA_HintInfo TAG_IGNORE
#define GAUGEIA_Level TAG_IGNORE
#define IA_InBorder TAG_IGNORE
@ -81,6 +82,7 @@
#define SBNA_Text TAG_IGNORE
#define TNA_CloseGadget TAG_IGNORE
#define TNA_HintInfo TAG_IGNORE
#define WA_ContextMenuHook TAG_IGNORE
#define WA_ToolBox TAG_IGNORE
#define WINDOW_BuiltInScroll TAG_IGNORE
#define WINDOW_NewMenu TAG_IGNORE

150
amiga/selectmenu.c Normal file
View File

@ -0,0 +1,150 @@
/*
* Copyright 2008 - 2011 Chris Young <chris@unsatisfactorysoftware.co.uk>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
* NetSurf is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* NetSurf is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __amigaos4__
#include <stdbool.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/popupmenu.h>
#include <proto/utility.h>
#include <reaction/reaction_macros.h>
#include "utils/errors.h"
#include "utils/log.h"
#include "render/form.h"
#include "desktop/mouse.h"
#include "amiga/gui.h"
#include "amiga/selectmenu.h"
#include "amiga/theme.h"
#include "amiga/utf8.h"
/* Maximum number of items for a popupmenu.class select menu.
* 50 is about the limit for my screen, and popupmenu doesn't scroll.
*/
#define AMI_SELECTMENU_MAX 50
/** Exported interface documented in selectmenu.h **/
BOOL ami_selectmenu_is_safe(void)
{
struct Library *PopupMenuBase;
BOOL popupmenu_lib_ok = FALSE;
if((PopupMenuBase = OpenLibrary("popupmenu.library", 53))) {
LOG("popupmenu.library v%d.%d", PopupMenuBase->lib_Version, PopupMenuBase->lib_Revision);
if(LIB_IS_AT_LEAST((struct Library *)PopupMenuBase, 53, 11))
popupmenu_lib_ok = TRUE;
CloseLibrary(PopupMenuBase);
}
return popupmenu_lib_ok;
}
HOOKF(uint32, ami_popup_hook, Object *, item, APTR)
{
uint32 itemid = 0;
struct gui_window *gwin = hook->h_Data;
if(GetAttr(PMIA_ID, item, &itemid)) {
form_select_process_selection(gwin->shared->control, itemid);
}
return itemid;
}
void gui_create_form_select_menu(struct gui_window *g,
struct form_control *control)
{
struct Library *PopupMenuBase = NULL;
struct PopupMenuIFace *IPopupMenu = NULL;
struct Hook selectmenuhook;
Object *selectmenuobj;
char *selectmenu_item[AMI_SELECTMENU_MAX];
struct form_option *opt = form_select_get_option(control, 0);
ULONG i = 0;
if(ami_selectmenu_is_safe() == FALSE) return;
if((PopupMenuBase = OpenLibrary("popupmenu.class", 0))) {
IPopupMenu = (struct PopupMenuIFace *)GetInterface(PopupMenuBase, "main", 1, NULL);
}
if(IPopupMenu == NULL) return;
ClearMem(selectmenu_item, AMI_SELECTMENU_MAX * 4);
selectmenuhook.h_Entry = ami_popup_hook;
selectmenuhook.h_SubEntry = NULL;
selectmenuhook.h_Data = g;
g->shared->control = control;
selectmenuobj = PMMENU(form_control_get_name(control)),
PMA_MenuHandler, &selectmenuhook, End;
while(opt) {
selectmenu_item[i] = ami_utf8_easy(opt->text);
IDoMethod(selectmenuobj, PM_INSERT,
NewObject(POPUPMENU_GetItemClass(), NULL,
PMIA_Title, (ULONG)selectmenu_item[i],
PMIA_ID, i,
PMIA_CheckIt, TRUE,
PMIA_Checked, opt->selected,
TAG_DONE),
~0);
opt = opt->next;
i++;
if(i >= AMI_SELECTMENU_MAX) break;
}
ami_set_pointer(g->shared, GUI_POINTER_DEFAULT, false); // Clear the menu-style pointer
IDoMethod(selectmenuobj, PM_OPEN, g->shared->win);
/* PM_OPEN is blocking, so dispose menu immediately... */
if(selectmenuobj) DisposeObject(selectmenuobj);
/* ...and get rid of popupmenu.class ASAP */
if(IPopupMenu) DropInterface((struct Interface *)IPopupMenu);
if(PopupMenuBase) CloseLibrary(PopupMenuBase);
/* Free the menu labels */
for(i = 0; i < AMI_SELECTMENU_MAX; i++) {
if(selectmenu_item[i] != NULL) {
ami_utf8_free(selectmenu_item[i]);
selectmenu_item[i] = NULL;
}
}
}
#else
#include "amiga/selectmenu.h"
void gui_create_form_select_menu(struct gui_window *g, struct form_control *control)
{
}
BOOL ami_selectmenu_is_safe()
{
return FALSE;
}
#endif

View File

@ -16,20 +16,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AMIGA_CONTEXT_MENU_H
#define AMIGA_CONTEXT_MENU_H
#ifndef AMIGA_SELECTMENU_H
#define AMIGA_SELECTMENU_H
struct tree;
struct gui_window;
struct gui_window_2;
struct form_control;
void ami_context_menu_init(void);
void ami_context_menu_free(void);
BOOL ami_context_menu_mouse_trap(struct gui_window_2 *gwin, BOOL trap);
void ami_context_menu_show(struct gui_window_2 *gwin, int x, int y);
BOOL popupmenu_lib_ok;
void gui_create_form_select_menu(struct gui_window *g, struct form_control *control);
/**
* Opens popupmenu.library to check the version.
* Versions older than 53.11 are dangerous!
*
* \returns TRUE if popupmenu is safe, FALSE otherwise.
*/
BOOL ami_selectmenu_is_safe(void);
#endif

View File

@ -63,6 +63,7 @@ struct hlcache_handle;
struct nsurl;
enum gui_pointer_shape;
enum nserror;
/**
* Graphical user interface window function table.

View File

@ -26,6 +26,7 @@
#define _NETSURF_RENDER_FORM_H_
struct form_control;
struct rect;
/** Option in a select. */
struct form_option {

View File

@ -6159,6 +6159,11 @@ de.ami.OptionDocky:In AmiDock zeigen
fr.ami.OptionDocky:Afficher dans AmiDock
it.ami.OptionDocky:Mostra icona di NetSurf su AmiDock
nl.ami.OptionDocky:Show in AmiDock
en.ami.PopupMenu:Use popupmenu for forms
de.ami.PopupMenu:Use popupmenu for forms
fr.ami.PopupMenu:Use popupmenu for forms
it.ami.PopupMenu:Use popupmenu for forms
nl.ami.PopupMenu:Use popupmenu for forms
en.all.Clipboard:Clipboard
de.all.Clipboard:Clipboard
fr.all.Clipboard:Presse-papiers