pub struct BackendCaps {Show 19 fields
pub mouse: bool,
pub scroll: bool,
pub drag: bool,
pub text_selection: bool,
pub native_menu: bool,
pub window_chrome: bool,
pub pointer_cursor: bool,
pub ime: bool,
pub file_dialogs: bool,
pub folder_dialogs: bool,
pub native_dialogs: bool,
pub notifications: bool,
pub app_font_registration: bool,
pub window_control: bool,
pub tray: bool,
pub generic_font_families: bool,
pub color_depth: ColorDepth,
pub kitty_keyboard: bool,
pub sgr_pixel_mouse: bool,
}Expand description
What a backend actually implements, beyond the required trait surface.
Several Backend methods take a no-op (or false) default so a new
backend compiles before every optional feature is wired up. Each
backend’s Backend::backend_caps is the declared, honest answer —
“these are the optional surfaces I actually implement” — so the
conformance runner can skip a scenario that needs one, with a named
reason, instead of either silently passing or spuriously failing.
A plain bitflag-shaped struct — one bool field per capability — rather
than the bitflags crate: small enough that a dependency buys nothing
but the | operator. Every field maps to zero or more Backend /
PlatformServices methods (documented per field below) that a
BackendCaps field of true promises are overridden away from their
no-op default.
This struct’s fields are the only capability vocabulary: a scenario’s
requires list matches against exactly these fields, and BackendReg::caps
is Backend::backend_caps itself, so there is no second, hand-maintained
list to drift out of sync.
A true here is a claim about source, not a hope: tests/conformance/caps.rs
mechanically checks it for every backend in the tree (including Win/macOS,
which have no conformance driver yet) — a declared capability whose
methods are still the trait’s no-op default fails, and so does an
undeclared capability whose methods are overridden. Each field’s doc
comment below names the methods that check reads; a capability that
cannot be checked that way says so explicitly there and in CAP_CONTRACTS.
Construct with BackendCaps::empty (or ..BackendCaps::empty() in
struct-update syntax) plus the fields a given backend actually
implements — see TuiBackend::backend_caps / GtkBackend::backend_caps
for worked examples. #[non_exhaustive]-free on purpose: this is
in-tree-only (no external Backend implementors, BACKEND.md), so a new
field is a breaking change to every backend impl by design, the same
trade-off the Backend trait itself makes for a new draw_* method.
Fields§
§mouse: boolThis backend delivers pointer press/release events
(crate::UiEvent::MouseDown / crate::UiEvent::MouseUp) from
its native event source, so click-driven scenarios mean something
on it.
Not mechanically checkable: the methods that produce these
(Backend::poll_events / Backend::wait_events) are
required, so every backend “overrides” them — including the Win
stub, whose bodies are todo!(). See CAP_CONTRACTS.
scroll: boolThis backend delivers crate::UiEvent::Scroll from its native
event source (wheel, trackpad, or terminal scroll reporting).
Same non-checkability as Self::mouse.
drag: boolThis backend delivers crate::UiEvent::MouseMoved while a
button is held, so a press → move → release sequence is a real
drag rather than two unrelated clicks. Same non-checkability as
Self::mouse.
text_selection: boolBackend::register_text_region / Backend::cancel_text_selection_drag
are overridden — mouse-drag text selection highlighting is real,
not a silently-dropped registration.
Backend::install_menu_bar and/or Backend::show_context_menu
are overridden — this backend can paint a native OS menu.
window_chrome: boolAt least one of Backend::begin_window_drag,
Backend::toggle_window_maximize, Backend::begin_window_resize
is overridden — client-side-decoration window chrome (drag-to-move,
double-click-to-maximize, edge resize) is wired to a real window.
pointer_cursor: boolBackend::set_cursor is overridden — hinting the OS pointer
glyph actually changes what the user sees, rather than being a
false-returning no-op.
ime: boolThis backend positions a native IME composition window (preedit) at
the caret. false on every backend today — reserved for a future
Backend::set_ime_cursor_area method (see docs/IME_INPUT_PROPOSAL.md).
Composed text arrives pre-resolved from the OS regardless, so this
tracks positioning the IME candidate window, not whether typing
composed characters works at all.
file_dialogs: boolPlatformServices::show_file_open_dialog /
PlatformServices::show_file_save_dialog show a real native
dialog rather than unconditionally returning None. Unlike the
fields above these two PlatformServices methods have no no-op
default (the trait requires every backend to implement them), so
this flag distinguishes “returns None because the user
cancelled” from “returns None because there is no dialog at
all” — the same distinction §5a exists to make visible.
Not mechanically checkable for the same reason: every backend
implements both methods, so their presence proves nothing and
only running a native dialog would tell the two apart. See
CAP_CONTRACTS.
folder_dialogs: boolPlatformServices::show_folder_open_dialog shows a real native
directory chooser rather than unconditionally returning None.
Split out from Self::file_dialogs rather than
folded into it: a backend can plausibly have one native facility
without the other, and a host reading this flag needs the honest,
narrower answer — “can I open a directory chooser”, not “does
this backend have some file-picker facility”.
Not mechanically checkable for the same reason as
Self::file_dialogs: every backend implements the method, so its
presence proves nothing. See CAP_CONTRACTS.
native_dialogs: boolPlatformServices::show_message_dialog shows a real native
alert/message dialog rather than unconditionally returning
None. Same no-default, same None-is-ambiguous shape as
Self::file_dialogs — this flag is the caller’s only way to
tell “the user dismissed it” from “this backend has no native
alert facility”.
crate::primitives::dialog::native_dialog_options is the pure
mapping from a Dialog descriptor to MessageDialogOptions,
and returns None for a dialog carrying a
crate::primitives::dialog::DialogTable or
crate::primitives::dialog::DialogInput — no native alert
facility hosts either, so those dialogs stay in-canvas
(draw_dialog) even on a backend where this flag is true.
Not mechanically checkable for the same reason as
Self::file_dialogs: every backend implements the method, so
its presence proves nothing. See CAP_CONTRACTS.
notifications: boolPlatformServices::send_notification dispatches a real system
notification rather than silently discarding it. Not mechanically
checkable, same as Self::file_dialogs.
app_font_registration: boolBoth Backend::register_font_from_memory and
Backend::set_nerd_font_fallback are overridden — this backend
can register an app-supplied font’s raw bytes and resolve
Nerd-Font (or other PUA-codepoint) glyphs to a real fallback
family, instead of painting tofu. Requires both methods, not
either: a backend that wires only one half still leaves a gap this
flag must not paper over.
window_control: boolBackend::window is overridden and returns Some at least
sometimes — this backend has a real WindowControl surface
rather than the trait’s always-None default.
Doesn’t promise every WindowControl method succeeds — see
that trait’s own doc for why individual methods (GTK’s
always-on-top, notably) still fail honestly with
BackendError::Unsupported even on a backend that declares this
true.
tray: boolBackend::tray is overridden and returns Some at least
sometimes — this backend has a real TrayService surface rather
than the trait’s always-None default.
Doesn’t promise every TrayService method succeeds, same caveat
as Self::window_control. TUI declares this false
permanently — see Backend::tray’s doc for why that is a
structural fact, not a gap to close.
generic_font_families: boolBackend::set_editor_font and Backend::set_ui_font are both
overridden — this backend resolves CSS/Pango generic family tokens
(monospace, sans-serif, system-ui; see
crate::GenericFamily) to a real native font instead of
silently discarding whatever family/font_desc string a caller
handed it. false on TUI permanently — a terminal cell grid has
no font concept to resolve a family token into, the same
structural reason both methods take the trait’s no-op default
there (see each method’s own doc).
color_depth: ColorDepthThis render target’s actual colour fidelity — see ColorDepth.
Not part of the bool-capability vocabulary below (Self::names /
Self::has / Self::vocabulary / ALL_NAMES): those model
“does this backend implement optional surface X”, a static
per-backend fact tests/conformance/caps.rs can mechanically
check by asking whether a method was overridden. This field is a
runtime-detected (or test-overridden) property of the terminal
the process happens to be running in, so it has no “overridden
method” to check against and is exempt from that machinery —
see backend_caps_tests::all_names_lists_every_field_exactly_once’s
exhaustive destructure below for where it is still forced into
view.
kitty_keyboard: boolWhether the kitty keyboard protocol (progressive keyboard enhancement — unambiguous modifier keys, key-release events) is actually active on this backend right now.
Not part of the bool-capability vocabulary below, for the same
reason as Self::color_depth: a runtime-detected (or
test-overridden) property of the terminal a TUI session happens
to be running in, not a static “does this backend implement method
X” fact. false on every non-TUI backend (none speak a terminal
protocol). On TUI it is true only when crate::tui::run
actually pushed the protocol’s enhancement flags — see
crate::tui::caps::probe_kitty_keyboard for how that is decided,
and crate::tui::backend::TuiBackend::set_kitty_keyboard for where
the live answer lands here. Check this before relying on a gesture
that needs the protocol (e.g. Ctrl+Enter distinct from Enter) and
fall back to an always-available binding (Alt+Enter) when it’s
false — see docs/KITTY_KEYBOARD_PROTOCOL.md’s degrade table for
which real terminals land on which side.
sgr_pixel_mouse: boolWhether SGR-Pixels mouse mode (?1016h — pixel-resolution mouse
coordinates instead of whole-cell ones) is actually active on this
backend right now.
Not part of the bool-capability vocabulary below, for the same
reason as Self::kitty_keyboard. false on every non-TUI
backend. On TUI it is true only when both
crate::tui::caps::probe_sgr_pixel_mouse’s live DECRQM round trip
answered yes and the terminal’s real per-cell pixel size could be
determined — see
crate::tui::backend::TuiBackend::set_sgr_pixel_mouse for where the
live answer lands here, and
crate::tui::backend::TuiBackend::cell_pixel_size for the divisor a
gesture that wants pixel-accurate dragging (a scrollbar or minimap
thumb) needs alongside this flag — the coordinate itself is already
scaled by the time it reaches crate::UiEvent::MouseMoved/etc.,
but a caller computing its own drag delta in pixels rather than
cells still needs the cell size to convert back.
Implementations§
Source§impl BackendCaps
impl BackendCaps
Sourcepub const fn empty() -> Self
pub const fn empty() -> Self
No optional capability implemented. The honest starting point for
a new backend — every field defaults to false the same way the
Backend methods they mirror default to a no-op.
Sourcepub fn names(&self) -> Vec<&'static str>
pub fn names(&self) -> Vec<&'static str>
Every capability name this instance declares, in field-declaration
order — the vocabulary a conformance scenario’s requires list
matches capability names against, and what a skip row names as
missing.
Sourcepub fn has(&self, cap: &str) -> bool
pub fn has(&self, cap: &str) -> bool
Whether this instance declares cap (one of Self::vocabulary’s
names). Unknown names answer false rather than panicking, so a
typo’d requires entry reads as “missing”, not a crash — the
typo itself is caught separately, and by name, by
conformance::every_requires_names_a_known_capability, which
checks each requires entry against Self::vocabulary.
Sourcepub fn vocabulary() -> Vec<&'static str>
pub fn vocabulary() -> Vec<&'static str>
Every capability name that exists at all, declared or not, in field-declaration order.
This is the closed vocabulary a conformance scenario’s requires
list may draw from. Self::names is the subset one backend
answers true for; this is the whole alphabet, so a requires
entry outside it can be reported as a typo rather than silently
skipping every backend forever.
Trait Implementations§
Source§impl Clone for BackendCaps
impl Clone for BackendCaps
impl Copy for BackendCaps
Source§impl Debug for BackendCaps
impl Debug for BackendCaps
Source§impl Default for BackendCaps
impl Default for BackendCaps
impl Eq for BackendCaps
Source§impl PartialEq for BackendCaps
impl PartialEq for BackendCaps
impl StructuralPartialEq for BackendCaps
Auto Trait Implementations§
impl Freeze for BackendCaps
impl RefUnwindSafe for BackendCaps
impl Send for BackendCaps
impl Sync for BackendCaps
impl Unpin for BackendCaps
impl UnsafeUnpin for BackendCaps
impl UnwindSafe for BackendCaps
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more