Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 93
Текст из файла (страница 93)
Starting with top-levelclient windows, it finds the foremost window at that level that containsthe point on which the user clicked. Then it goes on to check each of thiswindow’s children, and so it continues, until there are no more childrenor none of the children contain the point. Then WSERV analyses thewindows in the same way again, but this time it checks the capturing flagof each window to see if it should be capturing the event.440THE WINDOW SERVERWhen WSERV adds a move or a drag event to the client queue, itchecks the event that is currently at the end of the client queue, and ifthis is an identical event apart from the co-ordinates, then WSERV willjust replace the old event with the new one. This means that the clientwon’t get very fine-grained information on pen or mouse moves.
Thisis no problem, indeed it is beneficial, for most applications, but for adrawing application it is not ideal. So, for such applications, WSERV canalternatively store all the events that it gets from the kernel in a buffer,and the client will then get a block of them delivered at once.11.6Client queuesWSERV uses client queues to store events while they are waiting to bedelivered to the client. There are three different queues for each client;each of these stores a different type of event:• Redraw events• Priority key events• All other events (main queue).We designed priority key events initially for the OPL programminglanguage and this is the only application to use them to date.
Whilean OPL program was running, the user could press Ctrl+Esc and thiswould immediately terminate the program. This was because this keywas delivered via the priority key queue and so could by-pass all otherevents.More generally, we have three queues so that the client can treatdifferent events with different active-object priorities. In general, a clientwants to receive pointer and key events before any redraw events that arealready queued, so it sets the priority on its active objects for the redrawqueue to be lower than those for the main queue.When WSERV has an event for the client, it places the event in thequeue and completes the request status that client has supplied for thatqueue, so the client knows that there is at least one event waiting.
But thesystem may be busy and WSERV may generate many events before theclient has the chance to ask for an event. This means that WSERV has todeal with the problem of the queues overflowing.11.6.1 Overflow in the priority key queueWe designed this queue to take a single key press instructing the application to close; this means that in this queue we are not interested inmultiple occurrences of that key press. So the queue only ever holds theCLIENT QUEUES441last key press that has the relevant special status – if a new event comesalong before the old one is delivered, then the old one is overwritten.11.6.2 Overflow in the redraw queueThe redraw queue is an array that lists all of the client’s windows currentlyneeding a redraw.
The array is ordered from front to back so that thewindow to be redrawn first is the foremost one. If there is enough memoryavailable, the array could expand indefinitely – except that each windowcan only appear in it once.If at any time the array cannot be extended, then the redraw queuesets a flag to say that the array is not complete. When the array becomesempty and the flag is set, WSERV scans all the client’s windows to findone that needs a redraw. Only when it has scanned all the windows willit clear the flag.11.6.3 Overflow in the event queueWSERV uses many tactics to avoid or reduce the effect of overflow in thisqueue. However, they are not foolproof – it might happen that, in veryextreme situations, an event could be lost. However, this has not, to ourknowledge, happened in practice, or if it has, it has shown no side effects!The event queue is a global heap cell – there is only one event queuefor the whole system.
WSERV grows and shrinks this cell as the number ofclients changes. The size of the queue is about 48+2*(number of clients)entries and each entry is 40 bytes, the size of a TWsEvent.The heap cell is divided into sections and each client is allocated asection. WSERV also has the freedom to change the size of each clientsection within the cell, growing or shrinking the other clients’ sections inresponse. A particular client’s section can have between 2 and 32 entries.If WSERV needs to queue an event, and there isn’t room in the client’ssection, then obviously it will first try to expand the client’s section upto its maximum size of 32 entries.
(If the client’s section already has 32entries, then WSERV tries to purge that client’s queue – in other words,it tries to find an event that it can delete.) To do this, WSERV first triesto find other clients that have room in their sections and shrink thosesections. If this fails, then WSERV makes an attempt to purge an eventfrom one of the other clients’ queues. The focused client is the last to bechosen for this operation – WSERV will only purge the focused client’squeue if none of the other queues have events that can be purged. If thepurge fails then the event will be discarded.To purge events from a client queue, WSERV will try a variety oftactics, including:• Deleting an associated pair of up and down pointer events.
(If theassociated up event hasn’t been received yet, it will even delete adown event and later delete the next matching up event)442THE WINDOW SERVER• Deleting key up or down events from the non-focused client queue• Deleting matched pairs of key up and down events from the focusedclient queue. (Most applications ignore these events)• Merging two modifier change events and deleting one of them• Deleting matched pairs of focused lost and gained events• Deleting repeated switch on events• Deleting these events: key events, pointer enter and exit events, dragdrop events, pointer buffer ready events and the following pointerevents: drag, move, button repeat and switch on.11.7A simple handwriting animation DLLIn this section, I will develop a simple handwriting animation DLL. I won’tattempt real character recognition, but I will show all the surroundingframework, including getting the pointer events, drawing the ink on thescreen and sending a character event to the application.
My intention isto explain the basics of anim DLLs, and especially to show how they candeal with events.We originally designed anim DLLs for clocks in Symbian OS v5. Atthis time they provided two main features:• Accurate timing information. Simple use of a relative CTimer, forexample, would provide a clock that would update slower than realtime• The ability for user code to draw to a window while executing insidethe same thread as WSERV, thus avoiding delays caused by IPC.11.7.1 Creating an anim DLLThere are two parts to an anim DLL: the anim DLL itself, which is aplug-in to WSERV, and the client-side code that loads the anim DLL, andcontrols it.It is possible to give an anim DLL the standard type ‘‘DLL’’ in the MMPbuild file, but then you would need to do more work to set it up correctly.It is better to define it with type ANI:TARGETTYPEANIThe client-side code then calls the following function to load the animDLL:TInt RAnimDll::Load(const TDesC &aFileName)A SIMPLE HANDWRITING ANIMATION DLL443WSERV then responds by calling ordinal 1 in the anim DLL.
This functionshould return a sub-class of CAnimDll to the server:EXPORT_C CAnimDll* CreateCAnimDllL(){return new(ELeave) CHandWritingAnimDll();}This CAnimDll sub-class normally has only one function, which createsthe anim DLL plug-in object:class CHandWritingAnimDll : public CAnimDll{public: //Pure virtual function from CAnimDLLCAnim* CreateInstanceL(TInt aType);};Each anim DLL can supply many different sorts of anim DLL objects, andeach one can be instantiated many times.
But my example handwritinganim DLL will only provide one such object, so the implementation ofthis function is quite simple:CAnim* CHandWritingAnimDll::CreateInstanceL(TInt ){return new(ELeave) CHandWritingAnim();}CreateInstanceL() is called in response to one of the four overloadsof the RAnim::Construct() client-side functions:TInt Construct(const RWindowBase &aDevice, TInt aType,const TDesC8 &aParams);TInt Construct(const RWindowBase &aDevice, TInt aType,const TDesC8 &aParams, const TIpcArgs& aIpcArgs);TInt Construct(const RWsSprite &aDevice, TInt aType,const TDesC8 &aParams);TInt Construct(const RWsSprite &aDevice, TInt aType,const TDesC8 &aParams, const TIpcArgs& aIpcArgs);11.7.2 The two types of anim DLLOriginally, anim DLLs only provided the ability to draw to a singlewindow per anim object.