AWT peer event handling (Important)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,
Our Choice impl was pretty screwed-up; The index of the selected item
was not getting updated (unless you had an ItemListener attached).
That's pretty terrible. And looking at the history of the thing,
it's pretty clear there's a lot of confusion about how this stuff is
supposed to work. 

So I took it upon myself to do a proper investigation
and get this stuff sorted out once and for all. (Note that while I
belive the following to be true for most peer properties, painting
is not one of them.)

First off, some observations: 
1) When a property of a Component changes, the corresponding setProperty
method of the Component object IS called. E.g. selecting Choice item
WILL result in a call to Choice.select(index) method.
(Test: Overload the setProperty method)

2) The above call is done from the event dispatch thread.
(Test: Print Toolkit.getSystemEventQueue().isDispatchThread() )

3) The call is from the peer handleEvent and NOT from the peer
dispatchEventImpl. The latter must also always call
super.dispatchEventImpl for the former to be called.
(Test: Construct your own event and send it to EventQueue.postEvent(ie)
fake events are passed on to listeners but do not change the state of
the Component or its peer.)
An example of where this is wrong is the current version of Checkbox.

4) The Component-subclass's processEvent/processXXXEvent methods are
only called if the class has listeners (this much we seem to do right)
(Test: Overload processEvent)

5) The initial setting-up of the native state (on creating the peer)
does not trigger any events. (Test: Add a listener). (the obvious
paint events, etc are exceptions of course)

So, how this works is that the peer keeps track of the native state,
and what happens is:

Case 1: The user clicks on something, changing the native state. A
callback to the peer occurs, and if the state has changed, the peer
updates its state and posts an event. This event is then executed
by the event dispatch thread, calling the peer handleEvent() method. 
The peer handleEvent method checks if it's an event specific
to its peer type (or delegates it to super.handleEvent), and then, if
the owner's state needs updating, it calls its setProperty() method. 

Case 2: The program calls Component.setProperty(). If the property
isn't changed, do nothing. Otherwise, set the property and call the peer
setProperty() method. This triggers a callback and posts an event, but
in this case the peer handleEvent() method does NOT call the owner's
setProperty() method a second time since the owner's state does not need
updating.

Case 3: Somebody sticks in a bogus event in the event queue. The peer
handleEvent() method does not call its owner's setProperty() method
because its state does not need updating.

So our behaviour here goes from broken, to almost-right to completely
wrong (although a bit functional). But we need to strive to do this
stuff the Right way. All this behaviour is testable, and by testable
I mean you can write a program that relys on it. Which means that this
is a compatibility problem.

/Sven



[Index of Archives]     [Linux Kernel]     [Linux Cryptography]     [Fedora]     [Fedora Directory]     [Red Hat Development]

  Powered by Linux