| 1 | Tearoff Menu System |
| 2 | ~~~~~~~~~~~~~~~~~~~ |
| 3 | |
| 4 | A while ago, as Tim was leaving after a hacking session, I mentioned how |
| 5 | nice it would be if only RISC OS allowed menus to be tearoffable, like |
| 6 | OpenLook menus are. He pointed out that impossibility shouldn't be much |
| 7 | of a barrier to us, and we got coding. |
| 8 | |
| 9 | Tearoff menus look just like normal menus, except there's a grey bar |
| 10 | along the top, just below the title, with a `Tear' button in it. When |
| 11 | the user clicks the `Tear' button, the rest of the menu tree goes away, |
| 12 | leaving the tornoff menu behind, so that options can be chosen from it |
| 13 | whenever the user needs to. Tornoff menus have two buttons in their |
| 14 | grey bar area: `Close' closes the menu, and `Fold' hides the menu part |
| 15 | away, leaving just the title behind, a bit like Corel's rollups (only |
| 16 | without the irritating animation). |
| 17 | |
| 18 | The main support code was written as part of STEEL, in C. It handles |
| 19 | the obvious (but quite difficult) stuff related to highlighting the |
| 20 | right items, opening the right submenus, and drawing the windows, and |
| 21 | Tim wrote it all. (He later wrote the corresponding Sapphire code -- |
| 22 | the user- and programmer-visible bits of our tearoff support are |
| 23 | entirely written by him.) |
| 24 | |
| 25 | There's one aspect of tearoff handling which can't be handled from an |
| 26 | application: making the main menu tree `transient'. There are three |
| 27 | times when the Wimp closes a transient window `silently': |
| 28 | |
| 29 | * when the user clicks outside of the menu tree; |
| 30 | * when the user presses the `Escape' key; and |
| 31 | * when an application calls Wimp_CreateMenu. |
| 32 | |
| 33 | In the first case, the mouse click is passed on to the receiving window; |
| 34 | in the second, the keypress is swallowed by the Wimp. |
| 35 | |
| 36 | These three cases are handled by some vector interceptions. Normally |
| 37 | this would be done by a module. Tim wanted the vector traps to be hard |
| 38 | to extract, though, and a small module would be easy for other |
| 39 | programmers to reverse engineer and implement their own tearoffs. The |
| 40 | `tearoff support code' is statically linked into the application which |
| 41 | uses it, and copied into an RMA block if it's not there already. |
| 42 | |
| 43 | The interface to the TearSupt code is simple: |
| 44 | |
| 45 | * ts_init initialises the support code. |
| 46 | |
| 47 | * ts_opened says that the application has opened a transient window, |
| 48 | and wants to be notified about events which might cause it to be |
| 49 | closed. |
| 50 | |
| 51 | * ts_closed says that the transient window has been closed. |
| 52 | |
| 53 | * ts_switch switches Wimp_CreateMenu trapping on and off (an |
| 54 | implemention detail requires this). |
| 55 | |
| 56 | * ts_unload removes the tearoff support code from memory. |
| 57 | |
| 58 | Tearoff Support traps several vectors. One is trapped all the time: |
| 59 | |
| 60 | * ChangeEnvironmentV is trapped, as part of a particularly hacky way |
| 61 | of communicating with the TearSupt code. It traps a call with R0 = |
| 62 | -1 and returns its address and version number. This is very nasty. |
| 63 | |
| 64 | Others are only trapped while there's a `fake transient' open, and cause |
| 65 | Wimp messages to be sent to the owner of the window: |
| 66 | |
| 67 | * MouseV is trapped: all mouse clicks are picked up, and passed on as |
| 68 | messages. |
| 69 | |
| 70 | * InsV is trapped: insertion of an `escape' keypress into the keyboard |
| 71 | buffer causes a message to be sent. |
| 72 | |
| 73 | * The hardware SWI vector is trapped: a call to Wimp_CreateMenu causes |
| 74 | a message to be sent. |
| 75 | |
| 76 | Just to make life more awkward, the code is encrypted (very weakly: it's |
| 77 | not worth the effort and code space of doing it properly). I considered |
| 78 | removing the encryption code, but (a) I preferred to leave everything |
| 79 | the way it was (more or less) as a record of the nasty things Straylight |
| 80 | sometimes do, and (b) I couldn't be bothered. |
| 81 | |
| 82 | Anyway, all the code is really nasty. I'd recommend that you avoid |
| 83 | reading it too closely. Oh, the SWI patch may be instructive to those |
| 84 | who've not seen the job done before: I think it works properly in all |
| 85 | circumstances. |
| 86 | |
| 87 | Of course, anyone's allowed to use tearoff menus. You're even allowed |
| 88 | to use our code to implement them, as long as you stick to the GPL. And |
| 89 | finally, if someone comes up with a SWI chunk, I may be convinced to |
| 90 | permit binary distribution of a tearoff support module using our code. |
| 91 | -- |
| 92 | [mdw] |