Week 23 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License
"Eclipse Public License v1.0" which accompanies this distribution,
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
Nokia Corporation - initial contribution.
Contributors:
-->
<!DOCTYPE concept
PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-7C75642D-C0C9-5392-9354-711F42DC2C61" xml:lang="en"><title>Server-Initiated
vs. Application-Initiated Redrawing</title><shortdesc>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. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p> <b>Variant</b>: Both (ScreenPlay and non-ScreenPlay). <b>Target
audience</b>: Application developers. </p>
<section id="GUID-D5FE0214-ECEB-4C0F-84C9-2BB44C19E477"><title>Introduction</title> <p>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: </p> <ul>
<li id="GUID-017DF20B-5881-5B8A-A8A3-0019614535B7"><p>at direct application
request by an application drawing to a window through a <xref href="GUID-0AEE5955-C530-35F1-A904-69183331B294.dita"><apiname>CWindowGc</apiname></xref> </p> </li>
<li id="GUID-8B9CFD40-0ECB-5F0D-92BA-F8EB327B31CA"><p>due to regions of the
display becoming invalid </p> </li>
<li id="GUID-6F5C9D10-BCE4-5F60-9F85-BE69C4C58F2C"><p>due to actions internal
to the Window Server, such as pointer cursor movements. </p> </li>
</ul> <p>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: </p> <ul>
<li id="GUID-2FFC86C2-0971-539B-BD21-E95E9FEB4202"><p>for a region with no
window, the Window Server redraws the invalid region in the default background
color </p> </li>
<li id="GUID-B0289B7D-97E2-5FBD-9983-130A5109FDFF"><p>for a blank window,
the Window Server redraws the invalid region in the window's color </p> </li>
<li id="GUID-931BDE7B-4C56-5350-A26B-F89CCBA72DE6"><p>for a backed-up window,
the invalid region is redrawn from a backup bitmap maintained by the Window
Server </p> </li>
<li id="GUID-24155452-0F5D-508E-B04D-96E06FD0913F"><p>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 </p> </li>
<li id="GUID-2A5080AF-1415-5CBF-B775-D547D9C3F222"><p>for a normal <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita"><apiname>RWindow</apiname></xref>,
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. </p> </li>
</ul> </section>
<section id="GUID-50054B7B-FF18-40B2-A582-B90FE66D269F"><title>Window Server-initiated redrawing</title> <p>When the Window
Server needs to repaint a standard <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita"><apiname>RWindow</apiname></xref> window and it
is not possible to do this by replaying the drawing commands stored in the
redraw stores, it sends a <xref href="GUID-B5F16BF3-569D-3985-AAB7-439E3410468D.dita"><apiname>TWsRedrawEvent</apiname></xref> message to the
client. </p> <p>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 <b>redrawer</b>. 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 <xref href="GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9.dita#GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9/GUID-DADAFFD6-4B63-35EE-8F50-F397C119CC27"><apiname>RWsSession::RedrawReady()</apiname></xref> function. </p> <p>The
redrawer's <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> function (which handles the completed
request) calls <xref href="GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9.dita#GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9/GUID-6008C20D-AA95-3803-8B57-54948FA61616"><apiname>RWsSession::GetRedraw()</apiname></xref>. This gets the <xref href="GUID-B5F16BF3-569D-3985-AAB7-439E3410468D.dita"><apiname>TWsRedrawEvent</apiname></xref>,
which contains the handle of the window and the rectangle within it that needs
to be redrawn and then does the redraw. This involves: </p> <ol id="GUID-078DF0F5-E856-5FFF-ADEB-1A09B4BBDFB0">
<li id="GUID-75A15778-D570-5B5D-A07E-5660FFCAB00F"><p>Calling <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-9337538E-7A53-3153-A330-968B5E4F2FF2"><apiname>RWindow::BeginRedraw()</apiname></xref> on
the relevant window and passing in the rectangle. </p> </li>
<li id="GUID-C63A002A-B433-5054-BD73-0368E2FB6C1B"><p>Issuing the <xref href="GUID-0AEE5955-C530-35F1-A904-69183331B294.dita"><apiname>CWindowGc</apiname></xref> drawing
commands that define how to draw the area of the window specified by the rectangle
passed in the <xref href="GUID-B5F16BF3-569D-3985-AAB7-439E3410468D.dita"><apiname>TWsRedrawEvent</apiname></xref>. These drawing commands must
exactly match what was drawn originally, because the Window Server clips the
drawing to the passed rectangle. </p> </li>
<li id="GUID-AA03D7DD-0B8A-5241-87B1-D45BC8AAA369"><p>Calling <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-3DE16607-AD3B-3946-BEB3-88512EAAB9CE"><apiname>RWindow::EndRedraw()</apiname></xref>. </p> </li>
</ol> <p>At the end of the redrawer’s <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref>, a call is
made to <xref href="GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9.dita#GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9/GUID-DADAFFD6-4B63-35EE-8F50-F397C119CC27"><apiname>RWsSession::RedrawReady()</apiname></xref> to enable the client
to listen for further requests from the Window Server. </p> <p>The following
diagram demonstrates that typically the <xref href="GUID-12C281FF-546C-318D-8783-F26B0F619E11.dita"><apiname>RunL()</apiname></xref> starts with
a <xref href="GUID-C57CFECB-72CD-39EB-A83E-82A9E985F56B.dita"><apiname>GetRedraw()</apiname></xref> and ends with a call to <xref href="GUID-E3F0CB70-58E4-32FD-9828-71DF2F9976D3.dita"><apiname>RedrawReady()</apiname></xref>. </p> <fig id="GUID-B092D136-8C18-5237-A095-F8C3BBFFDDB4">
<title> Window Server-initiated redraw </title>
<image href="GUID-0528A294-AC1B-5CDD-B59C-A105F39D748F_d0e190203_href.png" placement="inline"/>
</fig> <p>A redrawer's <codeph>RunL()</codeph> function must <b>not</b> perform
any non-redraw drawing (that is, any drawing operations that are not bracketed
within the calls to <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph>).
If it does, this causes a panic with code 79 (<codeph>EWservPanicWindowBeginRedrawNotCalled</codeph>)
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 <codeph>RunL()</codeph> triggering
a Window Server-initiated redraw. </p> </section>
<section id="GUID-0238F737-3D2B-4811-8E46-561922210143"><title>Application-initiated redrawing</title> <p>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. </p> <p><b>The "draw now" scenario </b> </p> <p>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 <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-D5458F8C-E199-37DD-B821-050B749122C6"><apiname>CCoeControl::DrawNow()</apiname></xref>.
However, it is possible to achieve the same results using <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita"><apiname>RWindow</apiname></xref> and <xref href="GUID-0AEE5955-C530-35F1-A904-69183331B294.dita"><apiname>CWindowGc</apiname></xref> 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. </p> <p>The
application does the following: </p> <ol id="GUID-D9D43E2B-B29D-5C6F-A1AB-ABA192D3D562">
<li id="GUID-C59E802D-0D4F-595B-9F1C-BED1090EE7D7"><p>Calls <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-28202F81-52FE-30F5-8B8C-ABED0915822E"><apiname>RWindow::Invalidate()</apiname></xref>,
optionally passing in the bounding rectangle. When called without passing
in a rectangle, this function invalidates the entire window. </p> </li>
<li id="GUID-491CB745-6B47-5656-874E-A87DE1BE6254"><p>Calls <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-9337538E-7A53-3153-A330-968B5E4F2FF2"><apiname>RWindow::BeginRedraw()</apiname></xref>.
If the application passed a bounding rectangle to <codeph>Invalidate()</codeph>,
it must pass the same bounding rectangle to <codeph>BeginRedraw()</codeph>.
If the application did not pass a bounding rectangle to <codeph>Invalidate()</codeph>,
it must not pass one to BeginRedraw(). </p> </li>
<li id="GUID-8CA69A7D-0387-5604-9C10-983FB50514B5"><p>Issues the <xref href="GUID-0AEE5955-C530-35F1-A904-69183331B294.dita"><apiname>CWindowGc</apiname></xref> draw
commands. </p> </li>
<li id="GUID-B2474EE6-CC03-55A8-9972-071B76512B26"><p>Calls <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-3DE16607-AD3B-3946-BEB3-88512EAAB9CE"><apiname>RWindow::EndRedraw()</apiname></xref>. </p> </li>
</ol> <fig id="GUID-6E2637DC-F92A-56DE-BB07-F109F5CA681B">
<title> Application-initiated redrawing, "draw now" scenario
</title>
<image href="GUID-4BC95F70-2F3F-5CFE-B057-0C5A97430573_d0e190311_href.png" placement="inline"/>
</fig> <p><b>The "draw deferred" scenario </b> </p> <p>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 <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-9FB682AC-0209-302A-83F3-7BCB1162B998"><apiname>CCoeControl::DrawDeferred()</apiname></xref>.
However, it is also possible to do this by calling <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-28202F81-52FE-30F5-8B8C-ABED0915822E"><apiname>RWindow::Invalidate()</apiname></xref>. </p> <fig id="GUID-8B78CE09-EE92-50B3-8000-731BD9C20890">
<title> Application-initiated redrawing, "draw deferred" scenario
</title>
<image href="GUID-21EF9E6F-A0BF-5EB2-9E3F-CA6A011D4C89_d0e190335_href.png" placement="inline"/>
</fig> <p>This approach is useful when the data to be displayed might be updated
frequently but it is not necessary to update the display instantaneously. </p> <p>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. </p> <fig id="GUID-04BCFA21-8D44-5FEA-BE29-57B40AC9CF99">
<title> Icons displayed using the "draw now" approach
</title>
<image href="GUID-89185EBD-223F-5F52-B1CA-9F9692F7D21F_d0e190349_href.png" placement="inline"/>
</fig> <p>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. </p> <fig id="GUID-1E0E2A3C-1E63-58F6-940F-0D439FA6C721">
<title> Icons displayed using the "draw deferred" approach
</title>
<image href="GUID-EDC405DC-F222-59CD-836E-180F8E1D2D11_d0e190360_href.png" placement="inline"/>
</fig> <p>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. </p> </section>
</conbody><related-links>
<link href="GUID-484B51EC-2209-5492-8E9C-9D792AB0DF35.dita"><linktext>Graphics
and Drawing </linktext></link>
</related-links></concept>