Introduction and Overview
This section documents the ad hoc mechanism used by the Toolbox module to notify the Window module that a sub-menu is about to open (before delivery of a Wimp MenuWarning message), the necessity of this mechanism, and the way in which it has been extended to all object classes in Toolbox 1.86.
It also describes the method used to update Wimp sub-menu pointers when showing objects of the FontMenu, Menu and ColourMenu classes, the flaws in this system, and a more robust mechanism to replace it (which requires support from Menu 0.51).
Technical Details
Existing sub-menu warning mechanism
When the Toolbox module's post-filter for Wimp events catches a MenuWarning (&400C0) message (event code 17 or 18), it calls SWI SWI Window_PreSubMenuShow and then re-sends the message to the client task (thus deferring it). The initial message is intercepted so that neither client nor object modules see it. When the MenuWarning message returns it can be distinguished by the fact that its 'your ref' field is now non-zero.
The reason for this SWI is to give the Window module a chance to hide any Window object that is showing transiently and more importantly raise a Window_HasBeenHidden event that will be delivered before the MenuWarning message. (When the latter is received by the Menu module it will show the object attached at that point in the menu tree, potentially causing an AboutToBeShown-type event.)
This is not for the benefit of the Window module, since it can easily ensure that it generates a Window_HasBeenHidden event for any existing transient Window object before showing another one. The real reason is to give those object classes implemented using an underlying Window object (e.g. SaveAs) a chance to raise their own events (e.g. SaveAs_DialogueCompleted) in response to Window_HasBeenHidden, before the sub-menu object is shown.
The Toolbox module also calls SWI Window_PreSubMenuShow before the relevant class SWI when showing an object as a sub-menu.
Need for wider sub-menu warning
The mechanism outlined above is exclusive to the Window module; other object class modules do not receive notification before a MenuWarning message is deferred. The requirement to be able to deliver a HasBeenHidden-type event before a MenuWarning message is specific to object classes on top of which other classes are implemented (and only Window falls into this category).
However, forewarning of MenuWarning messages is also required in order to deduce that objects of any class have been hidden when an alternative sub-menu is about to open (not currently implemented, but desirable). In this case the notification could be immediately before the MenuWarning message is passed around the class modules, but it is simplest to combine this with the more stringent requirements of the Window class.
Forewarning is required because there is no guarantee of the order in which filters are called for a Wimp message. For example if the Menu module's filter receives a MenuWarning message first then it will call SWI Toolbox_ShowObject to show any attached object, potentially raising an AboutToBeShown-type event. When the message arrives at another class module's filter, it will raise HasBeenHidden-type events if it believes any of its objects to be showing as a sub-menu.
It can be seen that the event ordering is wrong. Worse, if the object about to be shown and the object deduced to have been hidden are the same then the class module is likely to become confused.
The additional notification prior to calling the class SWI to show an object as sub-menu is redundant because SWI Window_PreSubMenuShow should already have been called on receipt of a MenuWarning message.
Sub-menu pointers in Wimp menu data structures
The Wimp interpretation of sub-menu pointers is as follows:
| Value | Meaning |
|---|---|
| -1 | No sub-menu arrow |
| 1 - &7FFF | Wimp window handle (has sub-menu arrow) |
| >= &8000 | Pointer to another Wimp menu block (has sub-menu arrow) |
To stop sub-menus from disappearing when a menu tree is re-opened after an ADJUST-click selection we must ensure that the Wimp sub-menu pointer is valid for the selected menu entry on each level.
Currently the Wimp sub-menu pointer is only filled in after a submenu-show object attached to a menu entry has been auto-shown in response to a MenuWarning message. The value of R0 returned by SWI Toolbox_ShowObject (officially undefined, except in case of error) is implicitly treated as a Wimp window handle or pointer to a Wimp menu data structure. However this assumption is flawed since only the FontMenu, Menu and ColourMenu classes return a meaningful value in R0!
The Wimp sub-menu pointer is never filled in for objects shown as sub-menu by the client task (e.g. in response to a Menu_SubMenu event). This is because clients are not aware of the significance of the value of R0 returned by SWI Toolbox_ShowObject when showing certain object classes as sub-menu. Also they do not know the address of the Wimp data structure for the parent menu.
Finally, if a menu is re-built by a client task before being shown (e.g. upon receiving a Menu_AboutToBeShown event) then the Wimp sub-menu pointer will be invalidated if the base address of the Wimp menu data changes. The problem is that the sub-menu data pointer is returned immediately by the class SWI - before the object has actually been shown.