8.1 Input Protocol

  • 8.1.1 Input Protocol Functions
  • 8.1.2 Input Protocol Classes
  • CLIM's windowing substrate provides an input architecture and standard functionality for notifying clients of input that is distributed to their sheets. Input includes such events as the pointer entering and exiting sheets, pointer motion (whose granularity is defined by performance limitations), and pointer button and keyboard events. At this level, input is represented as event objects. [annotate]

    Sheets either participate fully in the input protocol or are mute for input. If any functions in the input protocol are called on a sheet that is mute for input, the sheet-is-mute-for-input error will be signalled. [annotate]

    In addition to handling input event, a sheet is also responsible for providing other input services, such as controlling the pointer's appearance, and polling for current pointer and keyboard state. [annotate]

    Input is processed on a per-port basis by the function process-next-event. In multiprocessing environments, a process that calls process-next-event in a loop is created for each port. In single-process Lisps, process-next-event is called whenever the user would go blocked for input. [annotate]

    process-next-event has three main tasks when it receives an event. First, it must determine to which client the event is addressed; this process is called distributing. Typically, the client is a sheet, but there are other special-purpose clients to which events can also be dispatched. Next, process-next-event formats the event into a standard format, and finally it dispatches the event to the client. A client may then either handle the event synchronously, or it may queue it for later handling by another process. [annotate]

    Input events can be broadly categorized into pointer events and keyboard events. By default, pointer events are dispatched to the lowest sheet in the hierarchy whose region contains the location of the pointer. Keyboard events are dispatched to the port's keyboard input focus; the accessor port-keyboard-input-focus contains the event client that receives the port's keyboard events. [annotate]

    8.1.1 Input Protocol Functions

    In the functions below, the client argument is typically a sheet, but it may be another object that supports event distribution, dispatching, and handling. [annotate]

    sheet-event-queue  sheet [Generic Function]
              

    Any sheet that can process events will have an event queue from which the events are gotten. sheet-event-queue returns the object that acts as the event queue. The exact representation of an event queue is explicitly unspecified. [annotate]

    [annotate]

    process-next-event  port &key wait-function timeout [Generic Function]
              

    This function provides a standard interface for one pass through a port's event processing loop. wait-function is either nil or a function of no arguments that acts as a predicate; it has dynamic extent. The predicate should wait until one of three conditions occurs: [annotate]

    Note: In this description, "the predicate" seems to sometimes refer to the wait function and sometimes to process-next-event itself. Perhaps someone could rephrase this description in a way that I can make sense of it. [edit]-- Robert Strandh 2005-04-30 13:55Z
     

    • If an event if received and processed, the predicate should return true. [annotate]
      Note: The second "if" should be "is" [edit]-- David 2009-03-22 03:54Z
       
    • If a timeout occurs, the predicate should return false. [annotate]
    • If the wait function returns true, the predicate should return the two values false and :timeout. [annotate]
      Note:

      This is all jumbled up. it should be:

      * If an event is received and processed, the predicate should return true.

      * If a timeout occurs, the process-next-event should return the two values false and :timeout.

      * If the wait function returns true, the predicate should return the two values false and :wait-function.

      Also to avoid busy looping it should be specified, that wait-function may be called only after certain port events occur (not necessarily "CLIM events").

      [edit]-- Daniel Kochmanski 2019-03-26 09:00Z
       

    A port implementation must provide a method for this function that reads the next window server-specific device event, blocking if necessary, and then invokes the event distributor. [annotate]

    [annotate]

    port-keyboard-input-focus  port [Generic Function]
    (setf port-keyboard-input-focus)  focus port [Generic Function]
              

    Returns the client to which keyboard events are to be dispatched. [annotate]

    Minor issue: Should this accessor be called keyboard-input-focus? It may be that we want to be able to call it on a frame in order to implement some sort of per-frame input focus. --- RSL [annotate]

    Note:

    True.

    Input focus should be managed per frame. Every frame has a sheet, which has the input focus and then the frame manager (your window manager) dispatches keyboard input to one of the frames. Each frame then dispatches possible keyboard events to its focus sheet.

    Therefore I propose we have an accessor like:

    frame-manager-frame-keyboard-input-focus frame-manager frame

    (setf frame-manager-frame-keyboard-input-focus) sheet frame-manager frame

    We need the frame manager in the game, since the frame class does not include any port-specific class in its class precedence list, while the frame manager has and altering input focus may be port-specific.

    Though for convenience I also propose the following two functions:

    frame-keyboard-input-focus frame

    (setf frame-keyboard-input-focus) sheet frame

    [edit]-- Gilbert Baumann 2016-05-15 17:07Z
     

    [annotate]

    Note:

    Keep in mind that you can't rely on a fact, that port-keyboard-input-focus knows anything about frames (for all we know client may work on bare sheets), so this should be implemented like:

    (setf port-keyboard-input-focus) specialized on pane should delegate it to (setf frame-keyboard-input-focus)

    while default sheet method should simply assign the sheet.

    Unless you want to throw into the dump whole separation of windowing substrate and CLIM higher level concepts.

    [edit]-- Daniel Kochmanski 2019-07-18 08:59Z
     
    Note: To follow up on the focus issue. We also would need some focus events or NOTE-FRAME-FOCUS callbacks. [edit]-- Gilbert Baumann 2022-03-05 18:53Z
     
    Note:

    We (that is McCLIM) specified the function

    (CLIM-EXTENSIONS:NOTE-INPUT-FOCUS-CHANGED sheet focusedp)

    [edit]-- DK 2023-09-12 11:01Z
     

    distribute-event  port event [Generic Function]
              

    The event is distributed to the port's proper client. In general, this will be the keyboard input focus for keyboard events, and the lowest sheet under the pointer for pointer events. [annotate]

    Minor issue: Do we just want to call this function dispatch-event and have it called on the port first? --- RSL [annotate]

    [annotate]

    dispatch-event  client event [Generic Function]
              

    This function is called by process-next-event to inform a client about an event of interest. It is invoked synchronously by whatever process called process-next-event, so many methods for this function will simply queue the event for later handling. Certain classes of clients and events may cause this function immediately to call either queue-event or handle-event, or to ignore the event entirely. [annotate]

    [annotate]

    queue-event  client event [Generic Function]
    handle-event  client event [Generic Function]
              

    Implements the client's policy with respect to the event. For example, if the programmer wishes to highlight a sheet in response to an event that informs it that the pointer has entered its territory, there would be a method to carry out the policy that specializes the appropriate sheet and event classes. [annotate]

    In addition to queue-event, the queued input protocol handles the following generic functions. The client argument to these functions is typically a sheet. [annotate]

    [annotate]

    event-read  client [Generic Function]
              

    Takes the next event out of the queue of events for this client. [annotate]

    [annotate]

    event-read-no-hang  client [Generic Function]
              

    Takes the next event out of the queue of events for this client. It returns nil if there are no events in the queue. [annotate]

    [annotate]

    event-peek  client &optional event-type [Generic Function]
              

    Returns the next event in the queue without removing it from the queue. If event-type is supplied, events that are not of that type are first removed and discarded. [annotate]

    [annotate]

    Note:

    This event-type argument is sure meant for implementing stream-peek-char. However an event type might not be suffice, if we would allow for *abort-gestures* processing.

    A more general interface like event-peek-if might be needed. Look at CLX for inspiration.

    [edit]-- Gilbert Baumann 2022-01-23 20:01Z
     

    event-unread  client event [Generic Function]
              

    Places the event at the head of the client's event queue, so as to be the next event read. [annotate]

    [annotate]

    event-listen  client [Generic Function]
              

    Returns true if there are any events queued for client, otherwise returns false. [annotate]

    [annotate]

    8.1.2 Input Protocol Classes

    Most classes of sheets will have one of the following input protocol classes mixed in. Of course, a sheet can always have a specialized method for a specific class of event that will override the default. For example, a sheet may need to have only pointer click events dispatched to itself, and may delegate all other events to some other input client. Such a sheet should have delegate-sheet-input-mixin as a superclass, and have a more specific method for dispatch-event on its class and pointer-button-click-event. [annotate]

    None of the five following classes is instantiable. [annotate]

    standard-sheet-input-mixin   [Class]
              

    This class of sheet provides a method for dispatch-event that calls queue-event on each device event. Note that configuration events invoke handle-event immediately. [annotate]

    The standard-sheet-input-mixin class will also provide a sheet-event-queue method, describe above. [annotate]

    [annotate]

    immediate-sheet-input-mixin   [Class]
              

    This class of sheet provides a method for dispatch-event that calls handle-event immediately for all events. [annotate]

    The immediate-sheet-input-mixin class will also provide a sheet-event-queue method, describe above. [annotate]

    [annotate]

    sheet-mute-input-mixin   [Class]
              

    This is mixed in to any sheet class the does not handle any input events. [annotate]

    [annotate]

    delegate-sheet-input-mixin   [Class]
              

    This class of sheet provides a method for dispatch-event that calls dispatch-event on a designated substitute recipient and the event. The initarg :delegate or the accessor delegate-sheet-delegate may be used to set the recipient of dispatched events. [annotate]

    [annotate]

    delegate-sheet-delegate  sheet [Generic Function]
    (setf delegate-sheet-delegate)  delegate sheet [Generic Function]
              

    This may be set to another recipient of events dispatched to a sheet of class delegate-sheet-input-mixin. delegate is the object to which events will be dispatched, and is usually another sheet. If the delegate is nil, events are discarded. [annotate]

    [annotate]