Interface WindowPeer

All Superinterfaces:
AutoCloseable, NativeWindow
All Known Implementing Classes:
HeadlessWindow, StubWindow

public non-sealed interface WindowPeer extends NativeWindow
What the toolkit asks of a window below the application's view of it: the input it delivers, the frames it asks for, the input method, the popups it owns and whether it is a modal. Every NativeWindow is one, so the toolkit reaches this with of(NativeWindow); a backend implements it.

Incubating, as the rest of this package: it may change in a minor release.

  • Method Details

    • of

      static WindowPeer of(NativeWindow window)
      Parameters:
      window - any window
      Returns:
      the same window as a peer; every window is one, since NativeWindow permits no other implementation
    • setTextInput

      void setTextInput(TextInput input)
      Says what text this window wants from the platform: none, typed characters with the input method off, or characters and the input method's composition. The scene asks for composition while a text-editing widget holds focus and for characters otherwise, so composition keys never leak into a control that is not text, and a list's type-ahead still hears letters. UI thread only.

      No default, nor for the two IME methods below: a backend that ignored them broke Chinese, Japanese and Korean input without a word. A backend with no input method (headless) implements them as no-ops, on purpose and in writing.

      Parameters:
      input - what the window wants; never null
    • setPreeditCaretRect

      void setPreeditCaretRect(float x, float y, float width, float height)
      Positions the IME candidate/composition window at the caret, so it follows the text being edited. x/y/width/height are in logical points relative to the window's content area (the scene feeds the focused widget's caretRect). UI thread only.
    • resetPreedit

      void resetPreedit()
      Cancels any in-progress IME composition held by the platform for this window. The scene calls it when focus leaves a text-editing widget, so a composition started there can never commit into whatever is focused next. A no-op when nothing is being composed. UI thread only.
    • isModal

      boolean isModal()
      Returns:
      whether this window is itself an active modal: one the backend registered through BackendPeer.pushModal(limn.backend.NativeWindow, limn.backend.NativeWindow), blocking the window it was opened over, or every other window when it was opened over none. The other end of NativeWindow.isModalBlocked(): that is the owner's bit and this is the dialog's, and it is this one an accessible tree publishes on the window's own node, because a client asks a window whether it blocks what it owns and never whether something else blocks it
    • registerChildPopup

      default void registerChildPopup(NativeWindow child)
      Registers a child popup to be closed automatically when this window closes, so a combo/menu popup can never outlive its parent.

      Registers it as WindowPeer.PopupKind.TRANSIENT, which is what a dropdown or a menu is. A window of its own has to say so: see registerChildPopup(NativeWindow, PopupKind).

    • registerChildPopup

      void registerChildPopup(NativeWindow child, WindowPeer.PopupKind kind)
      Registers a child popup and says what it is; see WindowPeer.PopupKind, which is the whole reason this overload exists.
    • unregisterChildPopup

      void unregisterChildPopup(NativeWindow child)
      Unregisters a child popup that closed on its own.
    • setFrameCallback

      void setFrameCallback(FrameCallback callback)
      Registers the per-frame render callback.
    • setInput

      void setInput(WindowInput input)
      Registers the input sink (usually the scene). See WindowInput.
    • supportsAbsolutePositioning

      boolean supportsAbsolutePositioning()
      Whether NativeWindow.screenX(), NativeWindow.screenY() and NativeWindow.setScreenPosition(int, int) actually work on this platform. When false the getters report a placeholder and the setter is ignored: a window is placed by the desktop and never learns where it went.

      Ask this before drawing anything outside a window that has to line up with something inside it: a dropdown's list, a menu cascade, a tooltip. Those are not windows in their own right; they are the owner's content, escaping the frame because most desktops offer no other way to overflow it. Where the answer is false there is no such way, and the content has to be drawn in the scene instead, clipped to the owner.

      A window that is genuinely a window (a document, a dialog, a palette) needs no such check. It has no position to agree with, so letting the desktop place it is the right outcome rather than a fallback.

      No default. It answered true until 2026-09-22, which is the unsafe answer: a backend that said nothing claimed a power Wayland does not have, and a popup that trusted it opened wherever the compositor put it. Absolute window position is absent from that protocol by design, so a backend has to say.

    • publishAccessibilityElsewhere

      default void publishAccessibilityElsewhere()
      Says this window's contents are published in another window's accessible tree: a popup the scene that opened it grafted into its own tree, as a native drop-down list is its field's child. The window then opens no bridge of its own, and where the platform would tell an assistive technology that a window appeared, it is kept out of that too: VoiceOver said "has a new window" a few seconds after every opening of a combo's list. Called before the window is shown.

      default and doing nothing, which is right for a window with no accessibility.

    • supportsDrag

      default boolean supportsDrag()
      Returns:
      whether this window can hand a drag to the system, so that it leaves the window: startDrag(limn.backend.spi.DragRequest) is worth preparing a picture for
    • startDrag

      default boolean startDrag(DragRequest request)
      Hands a drag to the system, while a mouse button is down in this window. From here until request.ended() is told, the pointer is the system's: the window hears no pointer events, and what is under the pointer in this window or another is asked through WindowInput.dragOver(limn.transfer.Offer, java.util.Set<limn.transfer.DropAction>, float, float).
      Parameters:
      request - what is dragged and who hears the end
      Returns:
      whether the system took it; false leaves the drag to the scene
    • dragAnswerChanged

      default void dragAnswerChanged(@Nullable DropAction action)
      The answer this window gave the drag the system drives over it changed while the pointer stood still: the content scrolled under the pointer, and another widget, or none, takes the drag there now. Said once per change, for a drag from another program and for one this window handed over; never for a drag the scene drives itself. UI thread.

      A system that asks WindowInput.dragOver(limn.transfer.Offer, java.util.Set<limn.transfer.DropAction>, float, float) again only when the pointer moves is to be told now, as the answer to its own ask would have told it, or a drop let go without a move is decided by the answer before the scroll. One that asks again on its own while the pointer rests hears the new answer then, and can leave this as it is: default and doing nothing.

      Parameters:
      action - the action a widget under the pointer would carry out now, or null when none takes the drag there