[Copyright status: portions of this file are derived from from the X11R4 protocol document, which is Copyright (c) 1986, 1987, 1988 Massachusetts Institute of Technology Permission to use, copy, modify, and distribute this document for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice are retained, and that the name of M.I.T. not be used in advertising or publicity pertaining to this document without specific, written prior permission. M.I.T. makes no representations about the suitability of this document or the protocol defined in this document for any purpose. It is provided ``as is'' without express or implied warranty. Anything herein which is not derived from the X11R4 protocol document is in the public domain.] Like most of liblx's facilities, events are handled through callbacks. Every LX_CONN has an event handler, which is a callback provided by the application. When the library receives an event on the wire, it unpacks it and calls the event handler, which then can inspect the event and do whatever is appropriate for the application (ignore it, use it, pass it off to other code, whatever). LX_EVENT is a struct containing an event type field (type) and a "came from SendEvent" flag (send_event), plus a union (u) with one arm for each event type. The core event types are ButtonPress Expose MappingNotify ButtonRelease FocusIn MotionNotify CirculateNotify FocusOut NoExposure CirculateRequest GraphicsExposure PropertyNotify ClientMessage GravityNotify ReparentNotify ColormapNotify KeyPress ResizeRequest ConfigureNotify KeyRelease SelectionClear ConfigureRequest KeymapNotify SelectionNotify CreateNotify LeaveNotify SelectionRequest DestroyNotify MapNotify UnmapNotify EnterNotify MapRequest VisibilityNotify Each of these has a type value LX_EV_(name) and an event-specific struct LX_EVENT_(name); the union field for each event type is the event type name. For example, for ButtonPress events events, type is set to LX_EV_ButtonPress and the LX_EVENT's .u.ButtonPress is an LX_EVENT_ButtonPress struct containing the ButtonPress-specific fields. Note that event handler callbacks must be prepared to deal with unexpected events. Some events are sent by the server with no way for the client to express lack of interest in them (MappingNotify is an example); also, SendEvent can be used to send an arbitrary event to any client which either has created a window or has keyboard focus. For example, if an application wants to exit upon receiving any ButtonPress event on a window whose ID is in a variable `quitwin' (this might be a user-interface "quit" button), its event handler could contain code like void event_handler(LX_CONN *conn, const LX_EVENT *ev) { switch (ev->type) { ... case LX_EV_ButtonPress: if (ev->u.ButtonPress.eventw == quitwin) exit(0); ... } } See extensions.txt for how extension events are handled. See the individual event descriptions, below, for full details on the core event structs and their members and meaning. Special processing occurs for ButtonPress events. When a button press is processed with no active pointer grab in progress and no applicable passive grab found, and there is a client which will receive the ButtonPress event (there can be at most one such client because at most one client per window can select for ButtonPress events), an active grab is automatically started for the client receiving the event. The effect is appxroximately equivalent to an immediately preceding lx_GrabButton with arguments btn The button pressed mods The current modifiers grabwin The window the pointer is in ownerevents True if the client has selected for OwnerGrabButton on the event window, else false mask The client's selected pointer events on the event window ptrmode Asynchronous kbdmode Asynchronous confineto None curs None except that no passive grab is actually established. Like an activated passive grab, the resulting grab is released automatically when the pointer has all buttons logically released. Also like an activated passive grab, UngrabPointer and ChangeActivePointerGrab can be used to modify the grab. Almost all events include a member `seq'. This is the low 16 bits of the sequence number of the last request received from the client the event is being sent to and is not described with the other event structure members below. KeyPress and KeyRelease events are generated even for keycodes mapped to modifier bits. They normally will have keysyms that do not map to strings in their mapping table entries (such as Control_L for a Control key), but nothing requires that. Two windows A B are said to be `unrelated' if they are not the same and neither is an ancestor of the other. KeyPress, KeyRelease, ButtonPress, ButtonRelease, MotionNotify -------- ---------- ----------- ------------- ------------ These events share many common attributes. The `source' window is always the window the pointer is in (this is a conceptual attribute, not actually present in the event structs). The event window is the window the event is reported with respect to; it is found by starting at the source window and walking up the window parenting hierarchy to the first window on which any client has selected interest, except that if a window which has that event type in its do-not-propagate mask is found, none of its ancestors are inspected. The window used for reporting can also be modified by grabs and, for keyboard events, using the focus window. The root window (rootw) is the root window of the screen the source window is on; rootx and rooty are the pointer coordinates relative to rootw's origin as of the moment of the event. eventw is, as described above, the event window. If eventw and rootw are on the same screen, eventx and eventy are the pointer coordinates relative to eventw; otherwise, they are zeros. If the source window is an inferior of eventw, childw is the child of the event window containing the pointer; otherwise, childw is LX_WINDOW_None. state is the state of the buttons and modifier keys immediately before the event. samescreen is a field which is not described by the protocol document; I believe it is a boolean, true iff eventw and rootw are on the same screen. EnterNotify, LeaveNotify ----------- ----------- mode is one of the LX_ENTERLEAVEMODE_* values. Routine pointer motion events have mode Normal. Pseudo-motion events due to grab activation have mode Grab; due to grab deactivation, Ungrab. detail gives more detail about the event; it is one of the LX_ENTERLEAVEDETAIL_* values. For events with mode Normal: * When the pointer moves from window A to its ancestor window B: - LeaveNotify with detail Ancestor on A. - LeaveNotify with detail Virtual on eacn window between A and B, exclusive, in that order. - EnterNotify with detail Inferior on B. * When the pointer moves from window A to its inferior window B: - LeaveNotify with detail Inferior on A. - EnterNotify with detail Virtual on each window between A and B, exclusive, in that order. - EnterNotify with detail Ancestor on B. * When the pointer moves from window A to unrelated window B, with window C being their least common ancestor: - LeaveNotify with detail Nonlinar on A. - LeaveNotify with detail NonlinearVirtual on each window between A and C, exclusive, in that order. - EnterNotify with detail NonlinearVirtual on each window between C and B, exclusive, in that order. - EnterNotify with detail Nonlinear in B. * The case of the pointer moving from window A to window B on different screens is treated as if all root windows were children of a (fictional) super-root window. When a grab activates, after any initial warp into a confine-to window, but before generating any applicable ButtonPress event, pointer events are generated with mode Grab, otherwise per the above description for mode Normal, as if for the pointer instantly moving from its initial position to some position in the grab window. The pointer does not actually move, though, and the same position is used as both the initial and the final position for the events. When a grab deactivates, after generating any applicable ButtonRelease event, events are generated, with mode Ungrab, otherwise per the above description for mode Normal, as if the pointer were to warp from some position in the grab window to its actual position, as determined by its location and the window hierarchy. The pointer does not actually move, though, and the same position is used as both the initial and the final position for the events. FocusIn, FocusOut ------- -------- These are generated when the input focus changes and are reported to clients selceting for FocusChange on the relevant window. mode is on of the LX_FOCUSMODE_* values and can be Normal, Grab, Ungrab, or WhileGrabbed; detail is one of the LX_FOCUSDETAIL_* values and can be Ancestor, Virtual, Inferior, Nonliear, NonliearVirtual, Pointer, PointerRoot, or None. Events generated for normal focus changes, ie, SetInputFocus when the keyboard is not grabbed, have mode Normal. Events generated for SetInputFocus while the keyboard is grabbed have mode WhileGrabbed. Events generated due to grab activation have mode Grab; events generated due to grab deactivation have mode Ungrab. All FocusOut events due to a window unmap are generated after any UnmapNotify, but the ordering of FocusOut with respect to EnterNotify, LeaveNotify, VisibilityNotify, and Expose events is not constrained. In the discussion of event genreation, A is the former focus setting, B is the new focus setting, and P is the window the pointer is in; if A and B are unrelated but have the same root, C is their least common ancestor. When A or B is PointerRoot or None and detail is described as being A or B, the detail value has the same textual name as the focus value, though the API values are different. For Normal and WhileGrabbed events: * If B is an ancestor of A: - FocusOut with detail Ancestor on A. - FocusOut with detial Virtual on each window between A and B, exclusive, in that order. - FocusIn with detail Inferior on B. - If P is an inferior of B, but P is unrelated to A, FocusIn with detail Pointer on each window from B (exclusive) down to P (inclusive), in that order. * If B is an inferior of A: - If P is an inferior of A but P is unrelated to B, FocusOut with detail Pointer on each window from P (inclusive) up to A (exclusive), in that order. - FocusOut with detail Inferior on A. - FocusIn with detail Virtual on each window from A to B, exclusive, in that order. - FocusIn with detail Ancestor on B. * If A and B are unrelated but have the same root: - If P is an inferior of A, FocusOut with detail Pointer on each window form P (inclusive) up to A (exclusive), in that order. - FocusOut with detail Nonlinear on A. - FocusOut with detial NonlinearVirtual on each window between A and C, exclusive, in that order. - FocusIn with detial NonlinearVirtual on each window between C and B, exclusive, in that order. - FocusIn with detail Nonlinear on B. - If P is an inferior of B, FocusIn with detail Pointer on each window from B (exclusive) to P (inclusive), in that order. * The case of focus moving from window A to window B on different screens is treated as if all root windows were children of a (fictional) super-root window. * If B is PointerRoot or None: - If P is an inferior of A, FocusOut with detail Pointer on each window from P (inclusive) to A (exclusive), in that order. - FocusOut with detail Nonlinear on A. - If A is not a root window, FocsuOut with detail NonlinearVirtual on each window from A (exclusive) up to its root (inclusive), in that order. - FocusIn with detail B, on all roots. - If B is PointerRoot, FocusIn with detail Pointer on each window from P's root down to P, inclusive, in that order. * If A is PointerRoot or None: - If A is PointerRoot, FocusOut with detail Pointer in each window from P up to its root, inclusive, in that order. - FocusOut with detail A, on all roots. - If A is not a root window, FocusIn with detail NonlinearVirtual on each window from A's root (inclusive) down to A (exclusive), in that order. - FocusIn with detail Nonlinear on A. - If P is an inferior of A, FocusIn with detail Pointer on each window from A (exclusive) down to P (inclusive), in that order. * If A is PointerRoot and B is None, or vice versa: - If A is PointerRoot, FocusOut with detail Pointer on each window from P up to its root, inclusive, in that order. - FocusOut with detail A, on all roots. - FocusIn with detail B, on all roots. - If B is PointerRoot, FocusIn with detail Pointer on each window from P's root down to P,p inclusive, in that order. When a keyboard grab activates, events are generated as described above (but before generating the applicable KeyPress, if any), except with mode Grab, as if A were the actual focus setting and B were the grab window. When a keyboard grab deactivates, events are generated as described above (but before generating the applicable KeyRelease, if any), except with mode Ungrab, as if A were the grab window and B were the actual focus setting. KeymapNotify ------------ This is the one event that does not include seq (there is no room for it in the on-wire format). The event contains a bitmap, which is just like the bitmap returned from QueryKeymap (see lx_QueryKeymap in core.txt), except that the [0] byte is not present. This is reported to clients selecting KeymapState on the relevant windows; it is generated immediately after every EnterNotify and FocusIn. Expose ------ This is reported to clients selecting for Exposure on the relevant window. It is generated whenever a region of the window either is visible or is being maintained in backing-store, but no contents are available for it. The region is tiled with the window's background (or, if the background is None, existing contents are unaffected); then it is decomposed into a set of rectangles (in a server-dependent manner) and an Expose event is generated for each resulting rectangle. But Expose events are never generated on InputOnly windows (they do not have any contents in this sense). For any particular occurrence which causes exposure generation, for any given window, all Expose events for that window and cause are guaranteed to be reported continguously. If count is zero, no more events follow; if count is nonzero, then at least that many, and possibly more, follow. x and y in the event specify the rectangle's upper-left corner relative to the window's origin; w and h specify its width and height. eventw is the affected window. All Expose events caused by a hierarchy change are generated after any hierarchy event due to the same cause (for example, Expose is generated after GravityNotify). On any particular window, Expose events are generated after VisibilityNotify, but there is no particular constraint between Expose events on one window and VisibilityNotify on another, different, window. The ordering of Expose events with respect to FocusOut, EnterNotify, and LeaveNotify events is not constrained. (The protocol document is silent on whether Expose is ordered with respect to FocusIn.) GraphicsExposure, NoExposure ---------------- ---------- These are unusual in that they are selected by a setting in a GC rather than a setting on a window. GraphicsExposure and NoExposure event generation in general is described under lx_CopyArea and lx_CopyPlane in core.txt. All the GraphicsExposures due to a given graphics request are guaranteed to be reported contiguously. If count is zero, no more GraphicsExposure events follow; if nonzero, at least that many (and possibly more) follow. The x, y, w, and h members of GraphicsExposure are as for Expose (NoExposure events of course have no x, y, w, and h members). drawable is the affected drawable (window or pixmap). minor_opc and major_opc identify the opcode of the request responsible for the operation; for events generated by core requests (as opposed to extension requests), major_opc is either 62 (for CopyArea) or 63 (for CopyPlane) and minor_opc is zero. At this writing, liblx does not export any definitions for these values; I intend to fix that. VisibilityNotify ---------------- These are reported to clients selecting for VisibilityCHange; they indicate a window's visibility. A window's subwindows are always ignored for purposes of VisibilityNotify events on it. state is one of the LX_VISIBILITYSTATE_* values and can be Unobscured, PartiallyObscured, or FullyObscured. Unobscured means the window is viewable and completely unobscured. PartiallyObscured means the window is viewable and partially, but not wholly, visible. FullyObscured means the window is viewable and fully obscured, or not viewable. When a window changes from one of the above states to another, an event with state set to the new state is generated. VisibilityNotify events are never generated on InputOnly windows. All VisibilityNotify events caused by a hieararchy change are generated after any hierarchly event caused by that change (eg, ConfigureNotify). On any particular window and cause, any VisibilityNotify due to that cause is generated before any Expose, but there is no particular constraint between VisibilityNotify on one window and Expose on another, different, window. The ordering of VisibilityNotify events with respect to FocusOut, EnterNotify, and LeaveNotify events is not constrained. (The protocol document is silent on whether VisibilityNotify is ordered with respect to FocusIn.) CreateNotify ------------ This is generated on a window whenever a child of it is created. window is the new window; parent is its parent. The other arguments are copied from the relevant CreateWindow request. This event is selected by requesting SubstructureNotify on the parent. pDestroyNotify ------------- This is generated on a window when it is destroyed. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. DestroyNotify is generated on a window's inferiors before it is generated on the window itself. Ordering is not otherwise constrainted between DestroyNotifys generated due to a single cause. UnmapNotify ----------- This is generated on a window whenever it changes state from mapped to unmapped. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. window is the window which was unmapped; eventw is the window on which the event was generated (window, for StructureNotify, or its parent, for SubstructureNotify). from_configure is true if the event was generated as a result of a window being unmapped due to its win-gravity being Unmap and its parent being resized; the protocol document is silent on when from_configure is false, though I suspect the intent is that it is false in all other cases. MapNotify --------- This is generated on a window whenever it changes state from unmapped to mapped. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. window is the window which was mapped; eventw is the window on which the event was generated (window, for StructureNotify, or its parent, for SubstructureNotify). override_redirect is the window's override-redirect attribute (see the discussions of override-redirect in core.txt). MapRequest ---------- This is generated when a MapWindow request on window W with parent P occurs, some client has selected SubstructureRedirect on P, and W's override-redirect attribute is false. See lx_MapWindow in core.txt. It is sent to the client which selected SubstructureRedirect on P. ReparentNotify -------------- This is generated when a window is reparented. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on either the old parent or the new parent. eventw is the window on which the event was generated, the window for StructureNotify or one of the parents for SubstructureNotify. window is the window which was reparented. parent is the new parent. (The old parent is not provided in the event.) The x and y coordinates in the event are the window's new location (the outer upper-left corner) relative to its new parent's oprigin. override_redirect in the event is the window's override-redirect setting. ConfigureNotify --------------- This is generated when a ConfigureWindow request actually changes the state of a window. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. eventw is the window on which the event was generated, the window for StructureNotify or the parent for SubstructureNotify. window is the window which was reconfigured. x, y, w, and h specify the new inside size and outside upper-left location (relative to its parent's origin) of the window. above_sibling is the sibling immediately below window in stacking order, or LX_WINDOW_None if window is on the bottom of its stacking order. override_redirect is the window's override-redirect setting. The protocol document is silent on the borderwidth value; I assume from the name that it is window's border width. GravityNotify ------------- This is generated when a window is moved because of a change in size of its parent. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. eventw is the window on which the event was generated, the window for StructureNotify or the parent for SubstructureNotify. window is the window which was moved. x and y are the new outside upper-left location of the window relative to its parent's origin. ResizeRequest ------------- This is generated when some client has selected ResizeRedirect on a window and some other client attempts to change its size with a ConfigureWindow request. window, w, and h are the window and the new size from the ConfigureWindow request. ConfigureRequest ---------------- This is generated when some client C has selected SubstructureRedirect on a window P and some other client issues a ConfigureRequest on a child window W of P. It is sent to C. parent is P and window is W. mask specifies which components wre specified in the request; other values are taken from the current window geometry, except for stackmode and sibling, which, if not given in the request, are (respectively) Above and None in the event. CirculateNotify --------------- This is generated when a window is actually restacked from a CirculateWindow request. It is reported to clients which have selected StructureNotify on the window or SubstructureNotify on its parent. eventw is the window on which the event was generated, the window for StructureNotify or the parent for SubstructureNotify. window is the window which was restacked. place reports where the window now is, is LX_CIRCULATEPLACE_Top if it is now above of all its siblings or LX_CIRCULATEPLACE_Bottom if it is now below of all its siblings. CirculateRequest ---------------- This is generated when a CirculateWindow request wouild normally actually restack a window, but some client has selected SubstructureRedirect on its parent. window is the restacked window, parent is its parent, and place is LX_CIRCULATEPLACE_Top or LX_CIRCULATEPLACE_Bottom according as the window would, except for the SubstructureRedirect, be placed on the top or bottom of the stacking order. PropertyNotify -------------- This is generated when a window's property value is changed (see lx_ChangeProperty and lx_RotateProperties in core.txt). A zero-length append counts as a change; so does replacing a property's vlaue with an identical value. It is also generated with a property is deleted with DeleteProperty or GetProperty (see lx_DeleteProperty and lx_GetProperty in core.txt). window and atom describe the property. time is the server time when the change occurred. state is LX_PROPERTYSTATE_NewValue for a changed value and LX_PROPERTYSTATE_Deleted for property deletion. SelectionClear -------------- This is generated when a SetSelectionOwner selection owner changes the owner of a selection; it is reported to the pre-change owner. owner is the window specified as the owner when the pre-change ownership was established; the protocol document is silent on the other two members, though I feel reasonably sure selection is the selection atom and time is the server time as of the change. SelectionRequest ---------------- This is generated when a client issues a ConvertSelection request; it is sent to the owner of the selection. owner is the owner window specified by the SetSelectionOwner that established selection ownership; the remaining arguments are copied from the ConvertSelection request (see lx_ConvertSelection in core.txt). By convention, this is a request to convert the selection to the specified target type and send a SelectionNotify back to the requestor. See the ICCCM for full details. SelectionNotify --------------- This is generated by the server when a client makes a ConvertSelection request and the specified selection has no owner. It is also, by convention, sent using SendEvent (see lx_SendEvent in core.txt) when the selection has an owner and the owning client has completed converting a selection as requested, or has failed to do so. See the ICCCM for full details. When generated by the server, property is LX_ATOM_None and the other values are taken from the ConvertSelection request. ColormapNotify -------------- This is generated when the colormap attribute of a window is changed, or when a window's colormap is installed or uninstalled. window is the affected window; colormap is the colormap (the protocol document does not state whether it is the former or new colormap when the window's colormap attribute is being changed; I would guess it's the new colormap). new is zero for colormap installation or uninstallation and nonzero for colormap attribute changes. state is LX_COLORMAPSTATE_Installed or LX_COLORMAPSTATE_Uninstalled according as the colormap is currently installed or not. MappingNotify ------------- This is sent to all clients; there is no mechanism to express lack of interest. Clients not interested in it should simply ignore it. It is generated with request LX_MAPPINGREQUEST_Modifier when SetModifierMapping succeeds, LX_MAPPINGREQUEST_Keyboard when ChangeKeyboardMapping succeeds, and LX_MAPPINGREQUEST_Pointer when SetPointerMapping succeeds. For Keyboard, first_keycode and count indicate the range of keycoes affected; for Modifier and Pointer those fields are meaningless. ClientMessage ------------- The server never generates this; it occurs only when generated by SendEvent (see lx_SendEvent in core.txt). type is an atom indicating how the receiver is expected to interpret the message. format is 8, 16, or 32 according as the data is u.data8, u.data16, or u.data32 (this is done so the server can byteswap between clients of differing endiannesses). The protocol document is silent on what window is; I think it is the window the event is being sent to (see lx_SendEvent in core.txt).