diff options
author | Steve Fryatt <steve@stevefryatt.org.uk> | 2011-02-20 23:16:33 +0000 |
---|---|---|
committer | Steve Fryatt <steve@stevefryatt.org.uk> | 2011-02-20 23:16:33 +0000 |
commit | cd9c0998e9849472473e577c4c04906e380896e1 (patch) | |
tree | 9bef19ebd3d56eccd03fa5613f1506c82762584b /riscos/wimp_event.c | |
parent | f54fc080c2a96ffdb713a9c8b5d0ccb604197c07 (diff) | |
download | netsurf-cd9c0998e9849472473e577c4c04906e380896e1.tar.gz netsurf-cd9c0998e9849472473e577c4c04906e380896e1.tar.bz2 |
Merge branches/stevef/toolbars to trunk.
svn path=/trunk/netsurf/; revision=11741
Diffstat (limited to 'riscos/wimp_event.c')
-rw-r--r-- | riscos/wimp_event.c | 424 |
1 files changed, 354 insertions, 70 deletions
diff --git a/riscos/wimp_event.c b/riscos/wimp_event.c index 43011a0e6..384a5258e 100644 --- a/riscos/wimp_event.c +++ b/riscos/wimp_event.c @@ -1,6 +1,6 @@ /* * Copyright 2005 Richard Wilson <info@tinct.net> - * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> + * Copyright 2010, 2011 Stephen Fryatt <stevef@netsurf-browser.org> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -95,16 +95,19 @@ struct event_window { void (*open_window)(wimp_open *open); void (*close_window)(wimp_w w); void (*redraw_window)(wimp_draw *redraw); - void (*menu_selection)(wimp_w w, wimp_i i); + bool (*menu_prepare)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_pointer *p); + bool (*menu_selection)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); + void (*menu_warning)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a); + void (*menu_close)(wimp_w w, wimp_i i, wimp_menu *m); wimp_menu *window_menu; bool window_menu_auto; - void (*window_menu_prepare)(wimp_w w, wimp_menu *m); - bool (*window_menu_selection)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action); - void (*window_menu_close)(wimp_w w, wimp_menu *m); - void (*window_menu_warning)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action); + bool window_menu_iconbar; const char *help_prefix; + const char *(*get_help_suffix)(wimp_w w, wimp_i i, os_coord *pos, + wimp_mouse_state buttons); void *user_data; struct icon_event *first; struct event_window *next; @@ -117,7 +120,7 @@ static struct event_window *ro_gui_wimp_event_get_window(wimp_w w); static struct event_window *ro_gui_wimp_event_find_window(wimp_w w); static struct icon_event *ro_gui_wimp_event_get_event(wimp_w w, wimp_i i, event_type type); -static void ro_gui_wimp_event_prepare_menu(wimp_w w, struct icon_event *event); +static void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event); static struct event_window *ro_gui_wimp_event_remove_window(wimp_w w); static struct event_window *ro_gui_wimp_event_windows[WIN_HASH_SIZE]; @@ -243,6 +246,40 @@ bool ro_gui_wimp_event_validate(wimp_w w) return true; } +/** + * Transfer event data from one window to another. This can be used as an + * alternative to ro_gui_wimp_event_finalise() and re-registering, if + * events need to continue across a change of window handle. + * + * All aspects of the registered events MUST remain the same in the new + * window! + * + * \param from The current window, which is to be deleted. + * \param to The window to which the events should transfer. + * \return true on success; false for an unknown window. + */ + +bool ro_gui_wimp_event_transfer(wimp_w from, wimp_w to) +{ + struct event_window *window; + int h; + + LOG(("Transferring all events from window 0x%x to window 0x%x", + (unsigned int) from, (unsigned int) to)); + + window = ro_gui_wimp_event_remove_window(from); + if (window == NULL || window->w != from) + return false; + + h = WIN_HASH(to); + window->w = to; + window->next = ro_gui_wimp_event_windows[h]; + ro_gui_wimp_event_windows[h] = window; + + ro_gui_menu_window_changed(from, to); + + return true; +} /** * Free any resources associated with a window. @@ -280,6 +317,61 @@ void ro_gui_wimp_event_finalise(wimp_w w) /** + * Free any resources associated with a specific icon in a window. + * + * \param w The window containing the icon. + * \param i The icon to free resources for. + */ + +void ro_gui_wimp_event_deregister(wimp_w w, wimp_i i) +{ + struct event_window *window; + struct icon_event *event, *parent, *child; + + LOG(("Removing all events for window 0x%x, icon %d", + (unsigned int)w, (int)i)); + window = ro_gui_wimp_event_get_window(w); + if (!window) + return; + + /* Remove any events that apply to the given icon. */ + + event = window->first; + parent = NULL; + + while (event != NULL) { + child = event->next; + + if (event->i == i) { + LOG(("Removing event 0x%x", (unsigned int) event)); + + if (parent == NULL) + window->first = child; + else + parent->next = child; + + switch (event->type) { + case EVENT_NUMERIC_FIELD: + case EVENT_TEXT_FIELD: + if (event->previous_value.textual) + free(event->previous_value.textual); + event->previous_value.textual = NULL; + break; + default: + break; + } + + free(event); + } else { + parent = event; + } + + event = child; + } +} + + +/** * Set the associated help prefix for a given window. * * \param w the window to get the prefix for @@ -316,6 +408,45 @@ const char *ro_gui_wimp_event_get_help_prefix(wimp_w w) /** + * Register a handler to decode help suffixes for a given window. + * + */ + +bool ro_gui_wimp_event_register_help_suffix(wimp_w w, + const char *(*get_help_suffix)(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->get_help_suffix = get_help_suffix; + return true; +} + + +/** + * Get the associated help suffix. + * + * \param w The window to get the suffix for + * \return The associated prefix, or NULL + */ + +const char *ro_gui_wimp_event_get_help_suffix(wimp_w w, wimp_i i, + os_coord *pos, wimp_mouse_state buttons) +{ + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window == NULL || window->get_help_suffix == NULL) + return NULL; + + return window->get_help_suffix(w, i, pos, buttons); +} + + +/** * Sets the user data associated with a window. * * \param w the window to associate the data with @@ -371,7 +502,8 @@ void *ro_gui_wimp_event_get_user_data(wimp_w w) * \param menu the menu that has been selected * \param selection the selection information * \param action the menu action info from menus.c - * \return true if the event was handled, false otherwise + * \return true if the menu is OK for an Adjust re-open; + * else false. */ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, wimp_selection *selection, menu_action action) @@ -384,32 +516,33 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, wimp_caret caret; wimp_icon_state ic; unsigned int button_type; + bool prepared; window = ro_gui_wimp_event_find_window(w); - if (!window) + if (window == NULL) return false; /* Start by looking for an icon event that matches. If there isn't one, - * then check to see if there is a window menu and associated - * selection handler available instead. + * then return details for an unconnected menu. It's up to the + * event recipient to sort out if this is a window menu or not, based + * on the menu handle passed back. */ for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; if (!event) { - if ((window->window_menu) && (window->window_menu == menu) - && (window->window_menu_selection)) { - window->window_menu_selection(w, menu, - selection, action); + if (window->menu_selection) + window->menu_selection(window->w, wimp_ICON_WINDOW, + menu, selection, action); + + /* Prepare the menu pending a possible Adjust click. */ + if (window->menu_prepare) + if (!window->menu_prepare(window->w, wimp_ICON_WINDOW, + menu, NULL)) + return false; - /* Prepare the menu pending a possible Adjust click. */ - if (window->window_menu_prepare) - window->window_menu_prepare(w, menu); - return true; - } else { - return false; - } + return true; } menu_entry = &menu->entries[selection->items[0]]; @@ -423,9 +556,15 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, ro_gui_set_icon_string(window->w, event->data.menu_gright.field, menu_entry->data.indirected_text.text, false); - ro_gui_wimp_event_prepare_menu(window->w, event); if (window->menu_selection) - window->menu_selection(window->w, event->i); + window->menu_selection(window->w, event->i, menu, + selection, action); + prepared = true; + if (window->menu_prepare) + prepared = window->menu_prepare(window->w, event->i, + menu, NULL); + if (prepared) + ro_gui_wimp_event_prepare_gright_menu(window->w, event); /* set the caret for writable icons and send a CTRL+U keypress to * stimulate activity if needed */ @@ -441,7 +580,7 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, button_type = (ic.icon.flags & wimp_ICON_BUTTON_TYPE) >> wimp_ICON_BUTTON_TYPE_SHIFT; if ((button_type != wimp_BUTTON_WRITABLE) && (button_type != wimp_BUTTON_WRITE_CLICK_DRAG)) - return true; + return prepared; error = xwimp_get_caret_position(&caret); if (error) { LOG(("xwimp_get_caret_position: 0x%x: %s", @@ -463,7 +602,7 @@ bool ro_gui_wimp_event_menu_selection(wimp_w w, wimp_i i, wimp_menu *menu, key.c = 21; // ctrl+u window->keypress(&key); } - return true; + return prepared; } @@ -493,6 +632,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) wimp_window_state open; wimp_caret caret; os_error *error; + bool prepared; w = pointer->w; window = ro_gui_wimp_event_find_window(w); @@ -500,7 +640,9 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) return false; /* Menu clicks take priority if there is an auto menu defined. */ - if ((window->window_menu) && (window->window_menu_auto)) { + if ((pointer->buttons == wimp_CLICK_MENU) && + (window->window_menu != NULL) && + (window->window_menu_auto)) { ro_gui_wimp_event_process_window_menu_click(pointer); return true; } @@ -574,7 +716,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) } ro_gui_dialog_add_persistent(current_menu_window, pointer->w); - ro_gui_menu_closed(false); + ro_gui_menu_closed(); gui_poll(true); error = xwimp_open_window(PTR_WIMP_OPEN(&open)); if (error) { @@ -596,8 +738,15 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) } } /* display the menu */ - ro_gui_wimp_event_prepare_menu(pointer->w, event); - ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i); + + prepared = true; + if (window->menu_prepare != NULL) + prepared = window->menu_prepare(pointer->w, pointer->i, + event->data.menu_gright.menu, pointer); + if (prepared) { + ro_gui_wimp_event_prepare_gright_menu(pointer->w, event); + ro_gui_popup_menu(event->data.menu_gright.menu, pointer->w, pointer->i); + } break; case EVENT_CHECKBOX: break; @@ -617,7 +766,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) if (pointer->buttons & wimp_CLICK_SELECT) { ro_gui_dialog_close(pointer->w); ro_gui_wimp_event_close_window(pointer->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); } else { ro_gui_wimp_event_restore(pointer->w); } @@ -636,7 +785,7 @@ bool ro_gui_wimp_event_mouse_click(wimp_pointer *pointer) * /param w the window owning the menu * /param event the icon event owning the menu */ -void ro_gui_wimp_event_prepare_menu(wimp_w w, struct icon_event *event) +void ro_gui_wimp_event_prepare_gright_menu(wimp_w w, struct icon_event *event) { int i; const char *text; @@ -699,7 +848,7 @@ void ro_gui_wimp_event_ok_click(struct event_window *window, if (state & wimp_CLICK_SELECT) { ro_gui_dialog_close(window->w); ro_gui_wimp_event_close_window(window->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); } else { ro_gui_wimp_event_memorise(window->w); } @@ -863,7 +1012,7 @@ bool ro_gui_wimp_event_keypress(wimp_key *key) } } } else { - k.c |= (1u<<31); + k.c |= IS_WIMP_KEY; } /* registered routines take priority */ @@ -894,7 +1043,7 @@ bool ro_gui_wimp_event_keypress(wimp_key *key) return false; ro_gui_dialog_close(key->w); ro_gui_wimp_event_close_window(key->w); - ro_gui_menu_closed(true); + ro_gui_menu_closed(); return true; /* Return performs the OK action */ case wimp_KEY_RETURN: @@ -975,23 +1124,102 @@ bool ro_gui_wimp_event_redraw_window(wimp_draw *redraw) bool ro_gui_wimp_event_process_window_menu_click(wimp_pointer *pointer) { - struct event_window *window; + struct event_window *window; + int xpos, ypos, line_height, gap_height, entry; window = ro_gui_wimp_event_find_window(pointer->w); if ((window) && (window->window_menu) && (pointer->buttons == wimp_CLICK_MENU)) { - if (window->window_menu_prepare) - window->window_menu_prepare(window->w, - window->window_menu); + if (window->menu_prepare) + if (!window->menu_prepare(window->w, wimp_ICON_WINDOW, + window->window_menu, pointer)) + return false; - ro_gui_menu_create(window->window_menu, - pointer->pos.x, pointer->pos.y, - window->w, false); + if (window->window_menu_iconbar) { + xpos = pointer->pos.x; + ypos = 96; + + line_height = window->window_menu->height + + window->window_menu->gap; + gap_height = 24; /* The fixed dotted line height */ + + entry = 0; + do { + ypos += line_height; + if ((window->window_menu-> + entries[entry].menu_flags & + wimp_MENU_SEPARATE) != 0) + ypos += gap_height; + } while ((window->window_menu-> + entries[entry++].menu_flags & + wimp_MENU_LAST) == 0); + } else { + xpos = pointer->pos.x; + ypos = pointer->pos.y; + } + + ro_gui_menu_create(window->window_menu, xpos, ypos, window->w); return true; } return false; } + +/** + * Trigger a window's Prepare Menu event. + * + * \param w The window to use. + * \param i The icon to use. + * \param *menu The menu handle to use. + * \return true if the affected menu was prepared OK; else + * false. + */ + +bool ro_gui_wimp_event_prepare_menu(wimp_w w, wimp_i i, wimp_menu *menu) +{ + struct event_window *window; + + window = ro_gui_wimp_event_find_window(w); + if (window == NULL) + return false; + + if (window->menu_prepare) + return window->menu_prepare(w, i, menu, NULL); + + /* The menu is always OK if there's no event handler. */ + + return true; +} + +/** + * Register a window menu to be (semi-)automatically handled. + * + * \param w The window to attach the menu to. + * \param *m The menu to be attached. + * \param menu_auto true if the menu should be opened autimatically + * on Menu clicks with no task intervention; false + * to pass clicks to the window's Mouse Event + * handler and leave that to pass the menu click + * back to us for handling and menu opening. + * \param bool_position_ibar true if the menu should open in an iconbar + * position; false to open at the pointer. + * \return true if the menu was registed ok; else false. + */ + +bool ro_gui_wimp_event_register_menu(wimp_w w, wimp_menu *m, + bool menu_auto, bool position_ibar) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->window_menu = m; + window->window_menu_auto = menu_auto; + window->window_menu_iconbar = position_ibar; + return true; +} + /** * Register a numeric field to be automatically handled */ @@ -1227,11 +1455,40 @@ bool ro_gui_wimp_event_register_redraw_window(wimp_w w, return true; } + +/** + * Register a function to be called before a menu is (re-)opened. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called beofre the menu is + * (re-)opened. + * \return true if the menu was registed ok; else false. + */ +bool ro_gui_wimp_event_register_menu_prepare(wimp_w w, + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_pointer *p)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->menu_prepare = callback; + return true; +} + + /** * Register a function to be called following a menu selection. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called when a selection is + * made. + * \return true if the menu was registed ok; else false. */ bool ro_gui_wimp_event_register_menu_selection(wimp_w w, - void (*callback)(wimp_w w, wimp_i i)) + bool (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)) { struct event_window *window; @@ -1242,32 +1499,45 @@ bool ro_gui_wimp_event_register_menu_selection(wimp_w w, return true; } + /** - * Register a set of functions to be called to handle a window menu. + * Register a function to be called when a sub-menu warning is received. * - * \param + * \param *w The window for which events should be returned. + * \param *callback A function to be called whenever a submenu + * warning is received for the menu. + * \return true if the menu was registed ok; else false. */ +bool ro_gui_wimp_event_register_menu_warning(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m, + wimp_selection *s, menu_action a)) +{ + struct event_window *window; + + window = ro_gui_wimp_event_get_window(w); + if (!window) + return false; + window->menu_warning = callback; + return true; +} -bool ro_gui_wimp_event_register_window_menu(wimp_w w, wimp_menu *m, - void (*callback_prepare)(wimp_w w, wimp_menu *m), - bool (*callback_selection)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - void (*callback_close)(wimp_w w, wimp_menu *m), - void (*callback_warning)(wimp_w w, wimp_menu *m, - wimp_selection *s, menu_action action), - bool menu_auto) + +/** + * Register a function to be called before a menu is finally closed. + * + * \param *w The window for which events should be returned. + * \param *callback A function to be called when the menu is closed. + * \return true if the menu was registed ok; else false. + */ +bool ro_gui_wimp_event_register_menu_close(wimp_w w, + void (*callback)(wimp_w w, wimp_i i, wimp_menu *m)) { struct event_window *window; window = ro_gui_wimp_event_get_window(w); if (!window) return false; - window->window_menu = m; - window->window_menu_prepare = callback_prepare; - window->window_menu_selection = callback_selection; - window->window_menu_close = callback_close; - window->window_menu_warning = callback_warning; - window->window_menu_auto = menu_auto; + window->menu_close = callback; return true; } @@ -1408,20 +1678,29 @@ bool ro_gui_wimp_event_submenu_warning(wimp_w w, wimp_i i, wimp_menu *menu, for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; - if (event) + if (event) { + if (window->menu_close != NULL && + event->type == EVENT_MENU_GRIGHT && + event->data.menu_gright.menu == menu) { + window->menu_close(w, i, menu); + return true; + } + return false; + } /* If the warning is for a window menu, then pass the event on to it. */ if ((window->window_menu) && (window->window_menu == menu)) { - if (window->window_menu_warning) { - window->window_menu_warning(w, menu, selection, action); + if (window->menu_warning) { + window->menu_warning(w, wimp_ICON_WINDOW, menu, + selection, action); return true; } } return false; -}
+} /** * Handle menus being closed. This is called from ro_gui_menu_closed(), in @@ -1440,8 +1719,8 @@ void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu) ro_gui_wimp_event_register_submenu(0); /* Process the event for any window menus. Find the window data, then - * try and match to an icon event. If we can, then there isn't anything - * to do. + * try and match to an icon event. If we can, then GRight menus are + * sent the event; otherwise, we do nothing. */ window = ro_gui_wimp_event_find_window(w); @@ -1451,14 +1730,19 @@ void ro_gui_wimp_event_menus_closed(wimp_w w, wimp_i i, wimp_menu *menu) for (event = window->first; event; event = event->next) if ((event->type == EVENT_MENU_GRIGHT) && (event->i == i)) break; - if (event) + if (event) { + if (window->menu_close != NULL && + event->type == EVENT_MENU_GRIGHT && + event->data.menu_gright.menu == menu) + window->menu_close(w, i, menu); return; + } /* If the close is for a window menu, then pass the event on to it. */ if ((window->window_menu) && (window->window_menu == menu) && - (window->window_menu_close)) - window->window_menu_close(w, menu); + (window->menu_close)) + window->menu_close(w, wimp_ICON_WINDOW, menu); } /** |