Wimp (Nested Windows) Functional Specification


    Distribution: COMPANY CONFIDENTIAL

    Project:      NC Model 1
    Issue:        0.01
    Author(s):    Neil Raine
    Date:         30-Jul-96
    Last Issue:   
  


Contents.


History

        0.01 NRaine 30-Jul-96 Created.

Outstanding issues

The following features do not form part of the proposed enhancements in this specification, but are worthy of later consideration:


Overview

The Window Manager is to be extended to allow nested (or 'child' windows), with the following behaviour:


Technical background

Window stacks

The global window stack retains its original meaning, but now indicates the open top-level windows,and not the child windows. Each window has a list of child windows which are open within it, which works exactly as the global list works for top-level windows.

Window coordinates

All window coordinates are screen-relative, including those of child windows (ie. they're not relative to the work area of the parent). There are two reasons for this:

  1. Code for redrawing a child window need not take the coordinates of the parent into account
  2. Child windows can be attached in many different ways to their parents, not just relative to the work area origin (see below)

Wimp_OpenWindow API extension

Wimp_GetWindowState API extension

Entry:
Exit:

Redrawing windows

The global invalid rectangle list is still used for redrawing, but the algorithm for stepping through the windows is extended as follows:

Wimp_RedrawWindow now does the following:

Note that visibleouterportion does not subtract any children of the window in question, but does have extra code to deal with this window itself being a child window (this affects a direct call of Wimp_RedrawWindow for a child window):

Note also that invalidouterportion is only ever called for top-level windows, and it can stay the same, while invalidinnerportion is never called anyway.

Mouse clicks

This is pretty simple, but must be slightly extended to cope with child windows:

Note that once the mouse handling is dealt with, the Wimp's handling of the system areas (eg. scrollbars) should generate the correct results for child windows, as long as the Wimp_OpenWindow code can deal with reopening the child windows as required. Note that if you call the old version of Wimp_OpenWindow, the child window's parent and alignment flags will remain the same (which is what we want).

Opening windows

This is where it all gets a bit tricky!

Several things have to be dealt with at once:

Note that the automatic reopening of child windows according to their alignment flags takes place when the parent window is reopened, so if you want to perform your own adjustment of child windows, you should open the parent first (which will adjust the children as well), followed by reopening the child windows as required. Note also that the restriction that only the owner of a window can call OpenWindow on it has been removed, to allow the owner of the parent window to directly reopen the child windows,even if some of them are owned by another task. This applies to Wimp_ForceRedraw as well.

The result of a Wimp_OpenWindow, besides altering the current stack position and coordinates of a window, is to update the screen display by performing a series of block-copy operations where possible, and adding rectangles to the invalid list (to be redrawn later) where it wasn't possible to copy the contents from the old visible area of the window.

For efficiency reasons, it is important to 'collect up' a series of Wimp_OpenWindow calls so we can decide where the child windows are moving in relation to the parent (and in relation to their siblings). There are several reasons for this:

On the other hand, the problem when you've got a whole series of windows to move at the same time is that you'll end up with a set of rectangles to copy by different x,y offsets. Ideally these must all be copied simultaneously, so that you don't obscure portions of other source rectangles when copying to a destination rectangle. Effectively we must build up a list of all required block-copy rectangles, and copy them in an order which avoids trashing other rectangles. The problem then is that, since the x,y offset is not the same for all rectangles, it's possible to have a circular set of rectangles for which there is no copy order that doesn't trash one or other of the rectangles. In this case we must just copy the 'least damaging' rectangle, and subtract the destination rectangle from the list of source rectangles.

So, the fancy new Wimp_OpenWindow looks like this:

  1. Round coordinates to pixel boundaries, and restrict window coordinates and scroll offsets to valid ranges
  2. Update 'current' window position (but leave a copy of the most-recently-displayed position)
  3. Deal with stacking order changes - we need to get a visible area list for each window prior to the stack order change
  4. For all children of this window, inspect alignment flags and call Wimp_OpenWindow recursively (without flushing)
  5. If 'flushing' (on Wimp_Poll, or Wimp_OpenWindow with R4 bit 0 set):
    1. For all top-level windows:
      1. (Note that oldwindowrects is generated from the 'displayed' coordinates of all windows, not the 'current' ones)
      2. (This is crucial, as it allows butted siblings to move simultaneously without knobbling each other's visible areas)
      3. (NOTE: unfortunately we also require the old stacking order of the windows, which could be a bit tricky!)
      4. If window is moving/scrolling/resizing:
        1. If window isn't being resized or scrolled:
          1. Include border regions in oldwindowrects
        2. else
          1. If border regions are to be moved or resized, invalidate them
          2. Include only the work area in oldwindowrects
        3. For all child windows of this parent:
          1. Recurse on the child, generating oldwindowrects from its work area and borders
          2. Invalidate other child border areas if resizing or moving relative to parent's work area
          3. If the child's work area rectangles are moving by a different x,y offset from the parent's work area:
            1. Remove child rectangles from parent's oldwindowrects list
            2. Add child rectangles to the moving list, with the appropriate x,y offset for the child
        4. Clip parent's oldwindowrects to the (new) visible portion of the parent (with or without borders)
          1. (Note that the 'visible portion' may or may not include the children, depending on whether the children are moving with the parent)
        5. Add remaining parent's oldwindowrects to the moving list, with the appropriate x,y offset for the parent
    2. Perform a block-copy of the rectangle list (where each rectangle can have a different x,y offset)
    3. Update all windows' most-recently-displayed coordinates to their current positions

It would also be nice if the most-recently-displayed and current window positions could be used to fix the problem of having two 'linked' top-level windows moving together, so that they avoid temporarily overlapping each other and generating an unnecessary redraw. This is in fact the same problem as that of ensuring that child windows don't temporarily overlap their siblings when being moved together.


Implementation plan

Due to the lack of adequate debugging and tracing facilities, it is advisable to proceed with caution! This means that the best plan involves a step-by-step approach which avoids 'breaking' the existing code as far as possible.

So, the plan is:

  1. Get the test platform set up:
    1. Build the WindowManager from the existing sources, and get it working on the RISC PC.
    2. Bracket all changes with the new ChildWindows option flag
    3. Write a test program that opens a window, and arrange for this to be the only task which runs under the Wimp
  2. Minimal extension to Wimp_OpenWindow for child windows:
    1. Add data structures for child window stacks
    2. Extend Wimp_OpenWindow so it can open child windows (but ignore update code for now)
    3. Implement Wimp_GetWindowState extensions (easy)
  3. Implement redraw code for child window stacks:
    1. Recursive method of redrawing, clipping child windows to the parent's work area
    2. Extend test program so it opens a single child window
    3. Test with a single child window
    4. Extend test program so it opens another (overlapping) child window - partly outside the parent window's work area
    5. Test redraw code for the new case
  4. Implement mouse click detection for child windows
    1. Recurse down child window stack to find the correct window
    2. Check that the Wimp's system border handling works (eg. for dragging and resizing child windows)
  5. Implement full Wimp_OpenWindow functionality
    1. Defer Wimp_OpenWindow flushing until the next Wimp_Poll (or when explicitly requested)
    2. Get Wimp_OpenWindow update code working (not necessarily optimized)
    3. Implement alignment flags for child windows
    4. Extend test program so it opens child windows with all combinations of alignment flags
    5. Optimize Wimp_OpenWindow to avoid flicker and unnecessary redraws
    6. Test reopening at different stack depths
    7. Test reopening in a different stack altogether (swapping from child window to top-level and vice-versa)
    8. Test child window which is owned by a different task from the parent
  6. Implement other window-redraw related stuff:
    1. Check that Wimp_UpdateWindow works on child windows, and within a parent containing children
    2. Check that Wimp_ForceRedraw works in similar circumstances
    3. Check that icon redraw works in child windows and parents containing children
    4. Check the above where the parent and/or child is partially off-screen


Acceptance test

To be determined.


Development test strategy

To be determined.


Product organisation

The WindowManager sources will form part of the NC model 1 ROM build.


Future enhancements

None planned at present.