Skip to content

Commit

Permalink
Begin to document the Nested Wimp optimisation.
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-fryatt committed Jun 18, 2022
1 parent 7d51cd8 commit 6e83491
Show file tree
Hide file tree
Showing 23 changed files with 212 additions and 2 deletions.
112 changes: 110 additions & 2 deletions Chapters/ch05-does-order-matter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,123 @@
<summary>The order in which we open our windows can have some surprising effects &ndash; at least on some systems.</summary>

<section>
<p>So far, we&rsquo;ve seen how we can manually create one or more panes on our window, and have then behave in a number of distinct ways. Throughout the examples, however, the <function>PROChandle_pane_windows()</function> procedure has always called <swi>Wimp_OpenWindow</swi> for the different windows in a very specific order.</p>
<p>So far, we&rsquo;ve seen how we can manually create one or more panes on our window, and have them behave in a number of distinct ways. Throughout the examples, however, the <function>PROChandle_pane_windows()</function> procedure has always called <swi>Wimp_OpenWindow</swi> for the different windows in a very specific order: first the pane, then the main window, and finally the pane again.</p>

<p>Back in <reference id="sect-side-box-unex"/> we stated that this order was necessary, but hinted that we might be able to simplify things in some circumstances. Now, with all of the main details covered, it seems like a good time to go back and fill in this missing information!</p>
</section>

<section>
<title>An optimisation?</title>

<p>If we go back to look at the code in <reference id="dl-col-head-2"/> again, we can see that when an <name>Open_Window_Request</name> event arrives for the main window, it is treated as special case by <function>PROCopen_window_request()</function>.</p>

<code lang="bbcbasic">DEF PROCopen_window_request(b%)
IF !b% = MainWindow% THEN
PROChandle_pane_windows(b%)
ELSE
SYS &quot;Wimp_OpenWindow&quot;,,b%
ENDIF
ENDPROC</code>

<p>Instead of just calling <swi>Wimp_OpenWindow</swi>, control is immediately passed to the <function>PROChandle_pane_windows()</function> procedure. This goes on to position and open the pane, then open the main window. Finally, it checks the position in which the main window opened, before re-opening the pane if it wasn&rsquo;t in the expected place.</p>

<p>Given that we need to go back and adjust the position of the toolbox pane after the main window has been opened, it would seem that we could save some effort by only doing it once: <em>after</em> opening the main window. We could even streamline the code in <function>PROCopen_window_request()</function> by always calling <swi>Wimp_OpenWindow</swi> for the target window, before calling <function>PROChandle_pane_windows()</function> if the target is the main window. This alternative approach can be seen in <reference id="list-order-poll-open"/>.</p>

<code id="list-order-poll-open" lang="bbcbasic" title="An alternative way to handle Open Window Requests">DEF PROCopen_window_request(b%)
SYS &quot;Wimp_OpenWindow&quot;,,b%
IF !b% = MainWindow% THEN PROChandle_pane_windows(b%)
ENDPROC</code>

<p>By the time <function>PROChandle_pane_windows()</function> is called, <swi>Wimp_OpenWindow</swi> will already have updated the window state block pointed to by <variable>main%</variable> with the coordinates of the actual visible area &ndash; we discussed why we can rely on this in <reference id="sect-side-box-unex"/>. As a result, <function>PROChandle_pane_windows()</function> can start by calling <function>PROCposition_toolbar()</function> to update the visible area of the toolbox.</p>

<code lang="bbcbasic">PROCposition_toolbar(main%, toolbar%)</code>

<p>In order to get the position in the stack correct, we can open the pane behind the same window that the main window has just been opened behind, which will have the effect of placing it in the required location directly in front of the main window.</p>

<code lang="bbcbasic">toolbox%!28 = main%!28

SYS &quot;Wimp_OpenWindow&quot;,,toolbox%</code>

<p>The full code for our new <function>PROChandle_pane_windows()</function> can be seen in <reference id="list-order-single-pane"/>, and it&rsquo;s a lot simpler than the version seen in <reference id="list-side-box-update"/>.</p>


<code id="list-order-single-pane" lang="bbcbasic" title="An alternative way to position the toolbox pane">DEF PROChandle_pane_windows(main%)
LOCAL toolbar%

REM Get the Window State block for the toolbar pane, using some of the
REM spare space above the data for the state of the main window.
REM
REM Note: ON RISC OS 5, we could more clearly use DIM toolbox% LOCAL 64
REM here to allocate the required memory from the stack.

toolbar% = main% + 64

!toolbar% = ToolBarWindow%
SYS &quot;Wimp_GetWindowState&quot;,,toolbar%

REM Move the toolbar pane so that it's in the correct X and Y position
REM relative to where the main window is to go.

PROCposition_toolbar(main%, toolbar%)

REM Open the toolbar pane behind the same window that the main window
REM was opened behind. This will place it directly in front of the
REM main window.

toolbar%!28 = main%!28

SYS &quot;Wimp_OpenWindow&quot;,,toolbar%
ENDPROC</code>

<p>A complete copy of the new application can be found in <reference id="dl-order-single-pane"/>. When run, it might perform in a very similar way to <reference id="dl-col-head-2"/> from the previous chapter... or it might not.</p>

<download id="dl-order-single-pane" file="ColHead3" title="Simplifying the pane handling" compatibility="armv7"/>
</section>


<section>
<title>Re-creating our toolbar</title>
<title>Order does matter... sometimes</title>

<p>If you download and run <reference id="dl-order-single-pane"/>, you will either find that it behaves identically to <reference id="dl-col-head-2"/>, or that it exhibits a very obvious flicker from the toolbar whenever the window is dragged around with <mouse>Select</mouse> on the title bar. Which it does will depend on the version of the Window Manager you have on your system.</p>

<p>To understand the differences, we&rsquo;ll consider what happens to the main window and its toolbar pane when they&rsquo;re dragged with <mouse>Select</mouse> at the top of the window stack. <reference id="fig-order-new-1"/> shows the initial positions of the two windows in the stack, at the point just before an <name>Open_Window_Request</name> event arrives to ask our application to open the main window at the top of the stack.</p>

<image id="fig-order-new-1" file="order-new-1.png" title="The initial window stack order"/>

<p>If we follow the new approach outlined in this chapter with <reference id="dl-order-single-pane"/>, the first thing that our application does is to call the <function>PROCopen_window_request()</function> procedure, which in turn calls <swi>Wimp_OpenWindow</swi> for the main window using all of the values supplied by the Wimp. This will result in the main window being inserted at the top of the window stack as shown in <reference id="fig-order-new-2"/> &ndash; pushing the toolbar pane down below it.</p>

<image id="fig-order-new-2" file="order-new-2.png" title="Opening the main window in the new approach"/>

<p>Since the event was for the main window, <function>PROCopen_window_request()</function> goes on to call <function>PROChandle_pane_windows()</function>, which positions the toolbar pane&rsquo;s visible area correctly and then opens it behind the same window that the main window is behind: in this case, at the top of the window stack. This results in the toolbar pane being inserted back at the top of the stack as seen in <reference id="fig-order-new-3"/>, pushing the main window down behind it again &ndash; back into its correct place.</p>

<image id="fig-order-new-3" file="order-new-3.png" title="Opening the toolbar pane in the new approach"/>

<p>Compare this to the approach taken by <reference id="dl-col-head-2"/> in <reference id="chap-col-head"/>. With the two windows once again starting in the relative positions shown in <reference id="fig-order-new-1"/>, an <name>Open_Window_Request</name> event arrives for the main window. This time, however, <function>PROCopen_window_request()</function> simply calls <function>PROChandle_pane_windows()</function> without calling <swi>Wimp_OpenWindow</swi> for either window.</p>

<p><function>PROChandle_pane_windows()</function> begins by positioning the toolbar pane as best it can, then opens it in the position in the stack which was supplied by the Wimp for the main window. This results in the pane opening behind the window above the main window&rsquo;s new position. In the case of a <mouse>Select</mouse> drag, this will leave the toolbar pane in front of the main window, as shown in <reference id="fig-order-old-2"/>.</p>

<image id="fig-order-old-2" file="order-old-2.png" title="Opening the main window in the old approach"/>

<p>Once the toolbar pane has been opened, the main window&rsquo;s position in the stack is adjusted to be <em>behind</em> the toolbar pane and it is then re-opened as well. This can be seen in <reference id="fig-order-old-3"/>.</p>

<image id="fig-order-old-3" file="order-old-3.png" title="Opening the toolbar pane in the old approach"/>

<p>If the main window moved during opening, then the last thing that <function>PROChandle_pane_windows()</function> will do is to re-position and re-open the toolbar pane &ndash; exactly as shown in <reference id="fig-order-old-2"/>.</p>

<p>The difference between the two approaches can be seen in <reference id="fig-order-new-2"/> and <reference id="fig-order-old-2"/>: in our new approach, the main window and its toolbar pane are briefly swapped over during the opening sequence, while in our original code, they are not.</p>
</section>


<section>
<title>A question of optimisation</title>

<p>The small difference described in the previous section matters, because of a small change introduced as part of the Nested Wimp. A couple of the changes documented in the <cite><link href="http://www.vigay.com/inet/acorn/nested.html">Nested Window Manager Functional Specification</link></cite> are &ldquo;Redraw Optimisation&rdquo; and improvements to the &ldquo;Invalid Rectangle Handling&rdquo;. Between them, these have a big impact on the handling of panes.</p>

<p>When an application calls <swi>Wimp_OpenWindow</swi>, the window in question isn&rsquo;t immediately opened. Instead, the details are logged in a list of pending updates along with any other windows to be opened or closed &ndash; which are all actioned after the application next calls <swi>Wimp_Poll</swi>. This means that when our application opens its main window and toolbar pane, both windows will be updated together after control has returned to the Wimp.</p>

<p>Prior to the Nested Wimp, all of these pending actions would be carried out in full, in the order that they were specified. In contrast, the Nested Wimp scans the whole list and optimises out any inefficiencies, before carrying out the minimum number of actions required to achieve the end result.</p>

<p>What this means in practice is that the Nested Wimp will notice that despite the toolbar pane ending up behind the main window in <reference id="fig-order-new-2"/>, it ends up back in from in <reference id="fig-order-new-3"/> &ndash; and so there&rsquo;s no point redrawing the main window during the short period that it is on top.</p>

</section>
</chapter>
Expand Down
Binary file modified Downloads/Chapter03/TopBar1/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter03/TopBar2/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter03/TopBar3/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter03/TopBar4/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter04/ColHead1/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter04/ColHead2/!PaneDemo/!RunImage,ffb
Binary file not shown.
24 changes: 24 additions & 0 deletions Downloads/Chapter05/ColHead3/!Boot,feb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
| >!Boot
|
| Copyright 2021-2022, Stephen Fryatt (info@stevefryatt.org.uk)
|
| This file is part of PaneDemo:
|
| http://www.stevefryatt.org.uk/risc-os/panes
|
| Permission is hereby granted, free of charge, to any person obtaining
| a copy of this software and associated documentation files (the
| "Software"), to deal in the Software without restriction, including
| without limitation the rights to use, copy, modify, merge, publish,
| distribute, sublicense, and/or sell copies of the Software, and to
| permit persons to whom the Software is furnished to do so.
|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

If "<PaneDemo$Dir>"="" Then Set PaneDemo$Dir <Obey$Dir>
24 changes: 24 additions & 0 deletions Downloads/Chapter05/ColHead3/!PaneDemo/!Boot,feb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
| >!Boot
|
| Copyright 2021-2022, Stephen Fryatt (info@stevefryatt.org.uk)
|
| This file is part of PaneDemo:
|
| http://www.stevefryatt.org.uk/risc-os/panes
|
| Permission is hereby granted, free of charge, to any person obtaining
| a copy of this software and associated documentation files (the
| "Software"), to deal in the Software without restriction, including
| without limitation the rights to use, copy, modify, merge, publish,
| distribute, sublicense, and/or sell copies of the Software, and to
| permit persons to whom the Software is furnished to do so.
|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

If "<PaneDemo$Dir>"="" Then Set PaneDemo$Dir <Obey$Dir>
27 changes: 27 additions & 0 deletions Downloads/Chapter05/ColHead3/!PaneDemo/!Run,feb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
| >!Run
|
| Copyright 2021-2022, Stephen Fryatt (info@stevefryatt.org.uk)
|
| This file is part of PaneDemo:
|
| http://www.stevefryatt.org.uk/risc-os/panes
|
| Permission is hereby granted, free of charge, to any person obtaining
| a copy of this software and associated documentation files (the
| "Software"), to deal in the Software without restriction, including
| without limitation the rights to use, copy, modify, merge, publish,
| distribute, sublicense, and/or sell copies of the Software, and to
| permit persons to whom the Software is furnished to do so.
|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Set PaneDemo$Dir <Obey$Dir>

WimpSlot -min 96K -max 96K
Run <PaneDemo$Dir>.!RunImage
Binary file not shown.
Binary file not shown.
27 changes: 27 additions & 0 deletions Downloads/Chapter05/ColHead3/!Run,feb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
| >!Run
|
| Copyright 2021-2022, Stephen Fryatt (info@stevefryatt.org.uk)
|
| This file is part of PaneDemo:
|
| http://www.stevefryatt.org.uk/risc-os/panes
|
| Permission is hereby granted, free of charge, to any person obtaining
| a copy of this software and associated documentation files (the
| "Software"), to deal in the Software without restriction, including
| without limitation the rights to use, copy, modify, merge, publish,
| distribute, sublicense, and/or sell copies of the Software, and to
| permit persons to whom the Software is furnished to do so.
|
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Set PaneDemo$Dir <Obey$Dir>

WimpSlot -min 96K -max 96K
Run <PaneDemo$Dir>.!RunImage
Binary file added Downloads/Chapter05/ColHead3/!RunImage,ffb
Binary file not shown.
Binary file added Downloads/Chapter05/ColHead3/Templates,fec
Binary file not shown.
Binary file modified Downloads/Chapter06/NestedFixed/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file modified Downloads/Chapter06/NestedScroll/!PaneDemo/!RunImage,ffb
Binary file not shown.
Binary file added Images/Chapter05/order-new-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/Chapter05/order-new-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/Chapter05/order-new-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/Chapter05/order-old-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/Chapter05/order-old-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Images/Chapter05/order-old-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6e83491

Please sign in to comment.