2 Pointer
dxtr edited this page 2026-10-14 04:26:09 +02:00

Pointer

The pointer is the mouse, or a touchpad acting as one.

Entering, moving and leaving

Event Meaning
:pointer-enter The pointer came into the window.
:pointer-motion The pointer moved over the window.
:pointer-leave The pointer left the window.

All pointer events go to the window under the pointer, between its :pointer-enter and its :pointer-leave. event-x and event-y are the pointer's position at the time of the event:

  • in the window's units, the same units as window-size, not pixels;
  • relative to the window's top left, with y growing downwards;
  • as single-floats, with fractions: a precise mouse or a scaled display gives positions between whole units.

The window does not know where it is on the screen, so there are no screen coordinates. See Concepts.

To turn a position into pixels, for picking in a framebuffer, multiply by the window's scale:

(let ((scale (win:window-scale window)))
  (values (floor (* (win:event-x event) scale))
          (floor (* (win:event-y event) scale))))

:pointer-leave reports where the pointer was last seen in the window.

A :pointer-motion event also says how far the pointer moved since the last motion, event-dx and event-dy, in the window's units. While the window captures the pointer, event-x and event-y stay put and event-dx and event-dy are the device's own motion; see Cursors and Pointer Modes.

Buttons

Event Meaning
:button-press A button went down.
:button-release A button came up.

event-button is a button:

Button Meaning
:left The primary button.
:right The secondary button.
:middle The middle button, or pressing the wheel.
:back The side button for going back.
:forward The side button for going forward.
an integer Any other button, by the platform's number. On Linux, the evdev button code.

Button events carry event-x and event-y too, so a click needs no separate motion event. Left-handed settings swap the buttons before cl-windowing sees them: :left is always the primary button.

A press inside a window and a release outside it: both go to the window, because the window system keeps the pointer with the window while a button is held, on Wayland and on Windows alike.

(case (win:event-type event)
  (:button-press
   (when (eq (win:event-button event) :left)
     (start-drag (win:event-x event) (win:event-y event))))
  (:pointer-motion
   (when *dragging*
     (drag-to (win:event-x event) (win:event-y event))))
  (:button-release
   (when (eq (win:event-button event) :left)
     (end-drag))))

Scrolling

A :scroll event says how far to scroll, in steps:

  • event-scroll-y: positive down, negative up;
  • event-scroll-x: positive right, negative left.

Both can be non-zero in one event, as when a touchpad scrolls diagonally.

Device Steps
A wheel with notches 1.0 per notch.
A high-resolution wheel Fractions of a notch, such as 0.25, that add up to 1.0 per notch.
A touchpad, or anything that scrolls continuously 1.0 per 10 units of finger movement.

So a program that scrolls a list by three lines per notch scrolls by (* 3 (win:event-scroll-y event)) lines, and that works for touchpads too.

The user's settings, such as natural scrolling, are applied by the platform before cl-windowing sees the scroll. Scroll events carry the pointer's position and the modifiers held, so Control+wheel can zoom at the pointer.

Modifiers

Every pointer event carries the modifiers in effect:

(when (and (eq (win:event-type event) :button-press)
           (win:event-modifier-p event :shift))
  (extend-selection (win:event-x event) (win:event-y event)))

See Keyboard.

The cursor and holding the pointer

Each window sets the pointer's look over it with window-cursor, and holds the pointer, confined or captured for a game's camera, with window-pointer-mode. See Cursors and Pointer Modes.

Not supported yet

  • Touchscreens and drawing tablets as such. They may still act as a pointer, depending on the platform.

On Wayland

Input comes from the compositor's first seat. :pointer is in window-system-capabilities while that seat has a pointer. Pointer events are gathered in the protocol's frames, version 5 and later, so each frame gives at most one :scroll event with both axes.

On Windows

:pointer is in window-system-capabilities while a mouse is present. A wheel notch is 1.0, and the finer steps of precise wheels and touchpads come as fractions of it.