Class FocusTracker

java.lang.Object
com.vaadin.swingbridge.surrogates.FocusTracker

public final class FocusTracker extends Object
The Vaadin component that currently has browser focus, per UI (SD_focus_tracker) — the "who has focus" fact both layers need, cached where both can reach it:
FocusTracker.install();          // once per UI, from SwingBridgeEmulatorsBootstrap's UI-init leg
Component focused = FocusTracker.getFocusOwner();   // null when nothing of ours has it

Fed by one focusin listener on the UI's own element, which covers every peer regardless of type — a per-peer FocusNotifier subscription would miss everything sitting on a bare Div. The focused peer is identified by FOCUS_HOST, whose caveat is worth reading before touching this wiring.

Per UI, not per session: a browser tab has its own DOM and its own activeElement, so focus cannot be shared across tabs — deliberately the opposite call from D_session_scoped_pools's session-scoped Timer / SwingWorker pools.

Never throws: an unpopulated pointer means "nothing focused", a legitimate state rather than the wiring mistake BrowserTimeZone.get() fails loud on.

UI-thread-confined.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Notified when this UI's focus pointer moves, so a layer above can turn the move into events of its own — vaadinx.awt.KeyboardFocusManager's bound properties are the one consumer shape this was built for.
  • Method Summary

    Modifier and Type
    Method
    Description
    static com.vaadin.flow.shared.Registration
    Subscribes to the current UI's focus transitions:
    static com.vaadin.flow.component.Component
    The focused Vaadin component in the current UI, or null when nothing our side owns has focus (including: no current UI, or install() was never called because the app skipped SwingBridgeEmulatorsBootstrap).
    static void
    Installs this UI's focusin / focusout listeners.
    static void
    noteFocusGained(com.vaadin.flow.component.Component owner)
    A peer's own Vaadin focus event moved focus to owner.
    static void
    noteFocusLost(com.vaadin.flow.component.Component loser)
    A peer's own Vaadin blur event: focus left loser.
    static void
    setFocusOwner(com.vaadin.flow.component.Component owner)
    Moves the pointer without waiting for the browser, so a requestFocus and a getFocusOwner() read in the same round trip agree.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • install

      public static void install()
      Installs this UI's focusin / focusout listeners. Idempotent; a no-op without a current UI.

      Registered browser or browserless — the registration is inert under Karibu, which never dispatches DOM events, so gating it would only make production and test wiring diverge.

    • getFocusOwner

      public static com.vaadin.flow.component.Component getFocusOwner()
      The focused Vaadin component in the current UI, or null when nothing our side owns has focus (including: no current UI, or install() was never called because the app skipped SwingBridgeEmulatorsBootstrap).
    • setFocusOwner

      public static void setFocusOwner(com.vaadin.flow.component.Component owner)
      Moves the pointer without waiting for the browser, so a requestFocus and a getFocusOwner() read in the same round trip agree. No-op without a current UI.

      Best-effort: if the browser refuses the focus (hidden element, not focusable) the next real focusin corrects us.

    • addFocusOwnerListener

      public static com.vaadin.flow.shared.Registration addFocusOwnerListener(FocusTracker.FocusOwnerListener listener)
      Subscribes to the current UI's focus transitions:
      Registration r = FocusTracker.addFocusOwnerListener(
              (oldOwner, newOwner) -> fireFocusProperties(oldOwner, newOwner));
      

      Per UI, like the pointer itself — a listener registered from one tab never hears another's. Registering without a current UI returns a no-op registration rather than throwing, matching getFocusOwner()'s stance on the same situation.

      Returns:
      the handle that unsubscribes; never null
    • noteFocusGained

      public static void noteFocusGained(com.vaadin.flow.component.Component owner)
      A peer's own Vaadin focus event moved focus to owner. Same effect as setFocusOwner(Component), named apart because the caller is reporting a browser fact rather than requesting a move.

      Additive to the focusin bridge, not a replacement: it fires only for peers something subscribed to, where the pointer has to answer for every component. Free on a round trip the peer was already making — and the only path a browserless test can drive.

    • noteFocusLost

      public static void noteFocusLost(com.vaadin.flow.component.Component loser)
      A peer's own Vaadin blur event: focus left loser. Clears the pointer only if loser still holds it — the browser fires focusout on the old element before focusin on the new one, so an unconditional clear here would wipe a pointer the newer event has already moved on.