This topic introduces the reasons that the screen display may need to be updated and the difference between redrawing that is initiated by an application and that initiated by the Window Server.
Variant: Both (ScreenPlay and non-ScreenPlay). Target audience: Application developers.
The Window Server maintains the UI display taking into account the region, ordinal position and visibility requirements of all displayable windows. The UI may be updated for several reasons:
at direct application
request by an application drawing to a window through a CWindowGc
due to regions of the display becoming invalid
due to actions internal to the Window Server, such as pointer cursor movements.
When a window is moved, resized, or otherwise manipulated by an application, it may cause parts of other windows to become invalid so that they must be redrawn. The Window Server maintains a list of all invalid regions and causes them to be redrawn in one of several ways:
for a region with no window, the Window Server redraws the invalid region in the default background color
for a blank window, the Window Server redraws the invalid region in the window's color
for a backed-up window, the invalid region is redrawn from a backup bitmap maintained by the Window Server
if the invalid region is owned by an animation DLL, the Window Server invokes the animation DLL directly to redraw the area: the region is then valid again
for a normal RWindow
,
whenever possible, the Window Server replays the sequence of drawing commands
stored in the redraw stores. However, sometimes this is not possible, because,
for example, the redraw stores have been lost due to low memory conditions.
In these circumstances, the Window Server generates a redraw event and sends
it to the application. This is described in more detail below.
When the Window
Server needs to repaint a standard RWindow
window and it
is not possible to do this by replaying the drawing commands stored in the
redraw stores, it sends a TWsRedrawEvent message to the
client.
It is part of the client's contract with the Window Server
to listen for these events and respond to them by performing a redraw. The
normal way for a client application to do this is through an active object,
which is sometimes called a redrawer. This is normally provided by
the application framework and should have a lower priority than the active
objects for standard events. The client issues an asynchronous request for
the next redraw event, calling the RWsSession::RedrawReady()
function.
The
redrawer's RunL() function (which handles the completed
request) calls RWsSession::GetRedraw()
. This gets the TWsRedrawEvent,
which contains the handle of the window and the rectangle within it that needs
to be redrawn and then does the redraw. This involves:
Calling RWindow::BeginRedraw()
on
the relevant window and passing in the rectangle.
Issuing the CWindowGc
drawing
commands that define how to draw the area of the window specified by the rectangle
passed in the TWsRedrawEvent. These drawing commands must
exactly match what was drawn originally, because the Window Server clips the
drawing to the passed rectangle.
Calling RWindow::EndRedraw()
.
At the end of the redrawer’s RunL(), a call is
made to RWsSession::RedrawReady()
to enable the client
to listen for further requests from the Window Server.
The following diagram demonstrates that typically the RunL() starts with a GetRedraw() and ends with a call to RedrawReady().
Figure: Window Server-initiated redraw
A redrawer's RunL()
function must not perform
any non-redraw drawing (that is, any drawing operations that are not bracketed
within the calls to BeginRedraw()
and EndRedraw()
).
If it does, this causes a panic with code 79 (EWservPanicWindowBeginRedrawNotCalled
)
in the ScreenPlay variant. This is to avoid the infinite loop that would otherwise
be caused by an endless cycle of the non-redraw drawing within the RunL()
triggering
a Window Server-initiated redraw.
An application initiates redrawing when it wants to update the UI to reflect a change of state. There are two scenarios, which we describe under separate headings below.
The "draw now" scenario
The "draw now" redraw scenario is
when an application wants to push a state change to a window immediately.
Typically the application does this by calling CCoeControl::DrawNow()
.
However, it is possible to achieve the same results using RWindow
and CWindowGc
calls
directly. To illustrate how to do this, consider a digital clock application
that updates the time displayed in the window from 12:02 to 12:03.
The application does the following:
Calls RWindow::Invalidate()
,
optionally passing in the bounding rectangle. When called without passing
in a rectangle, this function invalidates the entire window.
Calls RWindow::BeginRedraw()
.
If the application passed a bounding rectangle to Invalidate()
,
it must pass the same bounding rectangle to BeginRedraw()
.
If the application did not pass a bounding rectangle to Invalidate()
,
it must not pass one to BeginRedraw().
Issues the CWindowGc
draw
commands.
Calls RWindow::EndRedraw()
.
Figure: Application-initiated redrawing, "draw now" scenario
The "draw deferred" scenario
The "draw deferred" redraw scenario
is when an application simply marks a window or a rectangle within a window
as invalid. This eventually triggers a Window Server-initiated redraw. Typically
the application does this by calling CCoeControl::DrawDeferred()
.
However, it is also possible to do this by calling RWindow::Invalidate()
.
Figure: Application-initiated redrawing, "draw deferred" scenario
This approach is useful when the data to be displayed might be updated frequently but it is not necessary to update the display instantaneously.
To illustrate how it works, consider a window that has a rectangle that is used to display icons (a star, a cross and a triangle) that represent three different events that can occur in the application. Suppose the events can occur in quick succession. If you use the "draw now" approach when each event occurs, the Window Server updates the display separately for each one, as shown in the following diagram.
Figure: Icons displayed using the "draw now" approach
However, if you use the "draw deferred" approach when each event occurs, the Window Server may not update the display for each one. For example, the Window Server does not update the display when it is superceded by a later call.
Figure: Icons displayed using the "draw deferred" approach
If it is important that the display is updated immediately, you would generally use the "draw now" approach. However, if a short delay in the display being updated is unlikely to inconvenience the user, the "draw deferred" approach might be appropriate and has a performance advantage.