Name

EnterNotify,LeaveNotify — (generated event).

When Generated

EnterNotify and LeaveNotify events occur when the pointer enters or leaves a window.

When the pointer crosses a window border, a LeaveNotify event occurs in the window being left and an EnterNotify event occurs in the window being entered. Whether or not each event is queued for any application depends on whether any application selected the right event on the window in which it occurred.

In addition, EnterNotify and LeaveNotify events are delivered to windows that are virtually crossed. These are windows that are between the origin and destination windows in the hierarchy but not necessarily on the screen. Further explanation of virtual crossing is provided two pages following.

Select With

Each of these events can be selected separately with XEnterWindowMask and XLeaveWindowMask.

XEvent Structure Name

typedef union _XEvent {
   ...
   XCrossingEvent xcrossing;
   ...
} XEvent;

Event Structure

typedef struct {
   int type;                /* of event */
   unsigned long serial;    /* # of last request processed by server */
   Bool send_event;         /* True if this came from SendEvent request */
   Display *display;        /* Display the event was read from */
   Window window;           /* event window it is reported relative to */
   Window root;             /* root window that the event occurred on */
   Window subwindow;        /* child window */
   Time time;               /* milliseconds */
   int x, y;                /* pointer x,y coordinates in receiving 
                             * window */
   int x_root, y_root;      /* coordinates relative to root */
   int mode;                /* NotifyNormal, NotifyGrab, NotifyUngrab */
   int detail;              /* NotifyAncestor, NotifyInferior, 
                             * NotifyNonLinear, NotifyNonLinearVirtual, 
                             * NotifyVirtual */
   Bool same_screen;        /* same screen flag */
   Bool focus;              /* boolean focus */
   unsigned int state;      /* key or button mask */
} XCrossingEvent;
typedef XCrossingEvent XEnterWindowEvent;
typedef XCrossingEvent XLeaveWindowEvent;

Event Structure Members

The following list describes the members of the XCrossingEvent structure.

subwindow 

In a LeaveNotify event, if the pointer began in a child of the receiving window, then the child member is set to the window ID of the child. Otherwise, it is set to None. For an EnterNotify event, if the pointer ends up in a child of the receiving window, then the child member is set to the window ID of the child. Otherwise, it is set to None.

time 

The server time when the crossing event occurred, in milliseconds. Time is declared as unsigned long, so it wraps around when it reaches the maximum value of a 32-bit number (every 49.7 days).

x, y 

The point of entry or exit of the pointer relative to the event window.

x_root, y_root 

The point of entry or exit of the pointer relative to the root window.

mode 

Normal crossing events or those caused by pointer warps have mode NotifyNormal, events caused by a grab have mode NotifyGrab, and events caused by a released grab have mode NotifyUngrab.

detail 

The value of the detail member depends on the hierarchical relationship between the origin and destination windows and the direction of pointer transfer. Determining which windows receive events and with which detail members is quite complicated. This topic is described in the next section.

same_screen 

Indicates whether the pointer is currently on the same screen as this window. This is always True unless the pointer was actively grabbed before the automatic grab could take place.

focus 

If the receiving window is the focus window or a descendant of the focus window, the focus member is True; otherwise, it is False.

state 

The state of all the buttons and modifier keys just before the event, represented by a mask of the button and modifier key symbols: Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask, ControlMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, and ShiftMask.

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