7 Errors
dxtr edited this page 2026-10-18 16:23:22 +02:00

Errors

Conditions

Every error cl-windowing signals is a windowing-error:

error
└── windowing-error
    ├── window-system-error   the window system cannot be reached, or the connection failed
    ├── no-backend-error      the backend asked for, or the platform's, is not loaded
    ├── popup-error           a popup breaks the window system's rules
    ├── dialog-error          a dialog cannot be made
    ├── unsupported-error     the window system cannot do what was asked
    └── closed-error          a closed window system or a destroyed window was used

Arguments of the wrong type signal a standard type-error at the public function they were passed to. Every public function declares its arguments' types, which SBCL checks as the function is entered, so the error names the declared type, with the library's types expanded:

The value :NONSENSE is not of type (MEMBER :NUM-LOCK :CAPS-LOCK :SUPER
:ALT :CONTROL :SHIFT) when binding CL-WINDOWING:MODIFIER

A call with a constant of the wrong type makes SBCL warn as it compiles the call.

window-system-error

The window system cannot be reached, or the connection to it failed:

  • open-window-system finds no compositor, or one that lacks what cl-windowing needs;
  • the compositor closes the connection;
  • the compositor reports a protocol error.

(window-system-error-message condition) returns the message, which says what went wrong and what to check:

Cannot connect to the Wayland compositor "no-such-socket": Could not
connect to the Wayland display "no-such-socket".  Is a compositor running,
and is $WAYLAND_DISPLAY or :DISPLAY-NAME right?
The Wayland compositor does not offer xdg_wm_base, which cl-windowing
needs to open windows.
The Wayland compositor reported a protocol error: The compositor raised
protocol error 3 on xdg_surface 8.

After a window-system-error from process-events, the connection is gone, and the window system cannot be used again. Release its windows and close it, as the with- macros do on the way out: releasing succeeds on a failed connection, so the error that broke it is the one that propagates. To recover, open a new window system.

no-backend-error

open-window-system was asked for a backend that is not loaded, or none was asked for and the platform's, :win32 on Windows and :wayland elsewhere, is not loaded. (no-backend-error-backend condition) returns that backend, a keyword.

The window system backend :WIN32 is not loaded.  Load the system
cl-windowing/win32 first.  Loaded backends: :WAYLAND.

popup-error

create-popup and reposition-popup were asked for a popup that breaks the window system's rules: a popup that grabs made on a top-level window while another popup grabs, on a popup that does not grab, or on a popup that grabs but is not the newest one that does; or moving a popup on a Wayland compositor whose xdg_wm_base is older than version 3. Setting window-fullscreen-p on a popup signals it too. (popup-error-message condition) returns the message. See Popups.

dialog-error

create-window was asked for a dialog it cannot make: a modal window without a :parent, or a :parent that is a popup or belongs to another window system. A dialog opened from a popup, as from a menu, is made on the top-level window the popup is on. (dialog-error-message condition) returns the message. See Dialogs.

unsupported-error

The window system cannot do what was asked, as confining or capturing the pointer on a Wayland compositor without pointer-constraints-v1 and relative-pointer-v1. (unsupported-error-message condition) returns the message. window-system-capabilities says beforehand what it can do: here, :pointer-capture.

closed-error

A window system was used after close-window-system, or a window after destroy-window. (closed-error-object condition) returns it.

#<WAYLAND-WINDOW "" 800x600 (destroyed)> has been closed and cannot be used.

Functions that act on the platform signal it:

On a closed window system On a destroyed window
process-events, create-window, window-system-capabilities, close-window-system destroy-window, (setf window-title), adopt-window-size, create-vulkan-surface

Functions that only read what the object knows keep working, such as window-size, window-title and poll-event, so that code that handles the last queued events of a destroyed window does not fail. Check window-alive-p and window-system-open-p when you need to know.

Warnings

On Wayland, a keymap the compositor sends that libxkbcommon cannot compile is ignored with a warning, and the previous keymap stays.

Handling errors on the event thread

An event thread should stop when the window system fails:

(handler-case
    (loop until *stop*
          do (win:process-events window-system :timeout 0.05)
             (loop while (win:poll-event window-system event)
                   do (handle event)))
  (win:windowing-error (condition)
    (warn "The window system failed, stopping: ~A" condition)
    (setf *stop* t)))

Lifetimes

Made by Released by Macro
open-window-system close-window-system with-window-system
create-window destroy-window with-window
create-popup destroy-window, or with its parent
create-vulkan-surface cl-vk:destroy-surface

Release in the reverse order of making: surfaces before their windows, windows before their window system. close-window-system destroys the windows that are still alive, but not their Vulkan surfaces.

The with- macros release on any exit, by a non-local exit or an error included, and do nothing if the object was released already in the body. Releasing never fails because the connection has: when the compositor has gone, the window and the window system are still released, and the next process-events reports the failure.