I hate to say it, but one of the few things X-Windows got right (but extremely complicated and some would say over-engineered) was the EnterNotify/LeaveNotify event notification, which include esoteric "virtual crossings" with an event "detail" parameter that describes the exact type of enter/leave event.

 

It covers the cases where the cursor jumps between more than one level of window at once, or moves between different branches of the window tree. It ensures that every intermediate window (up to and including the common ancestor) gets notified about the cursor containment change, and its relationship to its new position (departures, arrivals, or just passing through).

 

So nested container windows with arbitrarily nested sub-windows can correctly track cursor containment, without becoming confused by all the edge cases that the designers of cheesy _javascript_ and Flash cursor tracking didn’t consider.  

 

Normal applications don’t usually use these features directly, but they’re useful for toolkit and widget and graphics editor implementers to get cursor tracking right, so application developers aren’t surprised by weird bugs and flakey tracking limitations (missed edge cases where they’re not notified).

 

Proper mouse tracking is tricky. I suppose Laszlo could implement detailed enter/leave notification, but is it worth the extra overhead of delivering detailed events to all the intermediate views, and complicating the api with the nuances of “details” and “virtual crossings”? It there a way detailed enter/exit tracking could be enabled only when needed?

 

      -Don

 

http://www.ac3.edu.au/SGI_Developer/books/XLib_PG/sgi_html/re10.html

 

Virtual Crossing and the detail Member

Virtual crossing occurs when the pointer moves between two windows that do not have a parent-child relationship. Windows between the origin and destination windows in the hierarchy receive EnterNotify and LeaveNotify events. The detail member of each of these events depends on the hierarchical relationship of the origin and destination windows and the direction of pointer transfer.

Virtual crossing is an advanced topic that you should not spend time figuring out unless you have an important reason to use it. We have never seen an application that uses this feature, and we know of no reason for its extreme complexity. With that word of warning, proceed.

Let's say the pointer has moved from one window, the origin, to another, the destination. First, we'll specify what types of events each window gets and then the detail member of each of those events.

The window of origin receives a LeaveNotify event and the destination window receives an EnterNotify event, if they have requested this type of event. If one is an inferior of the other, the detail member of the event received by the inferior is NotifyAncestor and the detail of the event received by the superior is NotifyInferior. If the crossing is between parent and child, these are the only events generated.

However, if the origin and destination windows are not parent and child, other windows are virtually crossed and also receive events. If neither window is an ancestor of the other, ancestors of each window, up to but not including the least common ancestor, receive LeaveNotify events, if they are in the same branch of the hierarchy as the origin, and EnterNotify events, if they are in the same branch as the destination. These events can be used to track the motion of the pointer through the hierarchy.

 

In the case of a crossing between a parent and a child of a child, the middle child receives a LeaveNotify with detail NotifyVirtual.

 

In the case of a crossing between a child and the parent of its parent, the middle child receives an EnterNotify with detail NotifyVirtual.

 

In a crossing between windows whose least common ancestor is two or more windows away, both the origin and destination windows receive events with detail NotifyNonlinear. The windows between the origin and the destination in the hierarchy, up to but not including their least common ancestor, receive events with detail NotifyNonlinearVirtual. The least common ancestor is the lowest window from which both are descendants.

 

If the origin and destination windows are on separate screens, the events and details generated are the same as for two windows not parent and child, except that the root windows of the two screens are considered the least common ancestor. Both root windows also receive events.

Table E-1 shows the event types generated by a pointer crossing from window A to window B when window C is the least common ancestor of A and B.

Table E-1. Border Crossing Events and Window Relationship

LeaveNotify

EnterNotify

Origin window (A)

Destination window (B)

Windows between A and B, exclusive, if A is inferior

Windows between A and B, exclusive, if B is inferior

Windows between A and C, exclusive

Windows between B and C, exclusive

Root window on screen of origin if different from screen of destination

Root window on screen of destination if different from screen of origin

Table E-2 lists the detail members in events generated by a pointer crossing from window A to window B.

Table E-2. Event detail Member and Window Relationship

detail Flag

Window Delivered To

NotifyAncestor

Origin or destination when either is descendant

NotifyInferior

Origin or destination when either is ancestor

NotifyVirtual

Windows between A and B, exclusive, if either is descendant

NotifyNonlinear

Origin and destination when A and B are two or more windows distant from least common ancestor C

NotifyNonlinearVirtual ancestor C; also on both root windows if A and B are on different screens

Windows between A and C, exclusive, and between B and C, exclusive, when A and B have least common

For example, Figure E-1 shows the events that are generated by a movement from a window (window A) to a child (window B1) of a sibling (window B). This would generate three events: a LeaveNotify with detail NotifyNonlinear for the window A, an EnterNotify with detail NotifyNonlinearVirtual for its sibling window B, and an EnterNotify with detail NotifyNonlinear for the child (window B1).

Figure E-1. Events generated by a move between windows

EnterNotify and LeaveNotify events are also generated when the pointer is grabbed, if the pointer was not already inside the grabbing window. In this case, the grabbing window receives an EnterNotify and the window containing the pointer receives a LeaveNotify event, both with mode NotifyUngrab. The pointer position in both events is the position before the grab. The result when the grab is released is exactly the same, except that the two windows receive EnterNotify instead of LeaveNotify and vice versa.

Figure E-2 demonstrates the events and details caused by various pointer transitions, indicated by heavy arrows.

Figure E-2. Border crossing events and detail member for pointer movement from window A to window B, for various window relationships

 

_______________________________________________
Laszlo-dev mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-dev

Reply via email to