2ee739cc |
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] |