pub struct ShellCaps(/* private fields */);Expand description
What a shell backend supports.
Each flag names a behaviour a consumer would otherwise have to guess from the platform. A flag that no consumer would branch on does not belong here.
Implementations§
Source§impl ShellCaps
impl ShellCaps
Sourcepub const HW_UPSCALE: Self
pub const HW_UPSCALE: Self
The compositor can scale a smaller buffer to the window’s size in display hardware, so borderless render-scale costs no shader work.
Wayland’s wp_viewporter; the browser’s CSS-sized canvas. Absent on
X11, where the renderer must do an upscale blit instead. This is the
exact decision the windowing rules call out as the reason caps
exist. Nothing asks for it: the engine does its own upscale on every
platform (docs/backlog.md, The engine owns scaling).
Sourcepub const ASPECT_HINT_HONORED: Self
pub const ASPECT_HINT_HONORED: Self
The window system will enforce an aspect ratio during an interactive resize.
X11 WM_NORMAL_HINTS, Win32 WM_SIZING, macOS
setContentAspectRatio. Wayland has no aspect hint, so a
Wayland backend clears this bit and the renderer letterboxes.
Letterboxing must work regardless — a tiling window manager ignores
the hint on every backend that has one — so this flag chooses
between “good” and “correct”, never between “works” and “broken”.
Sourcepub const POINTER_WARP: Self
pub const POINTER_WARP: Self
Shell::warp_pointer moves the
pointer.
X11 XWarpPointer, Win32 SetCursorPos. Wayland deliberately
forbids it (a client that can move the cursor can spoof clicks); the
engine’s answer there is pointer lock plus relative motion, which is
what a camera wanted anyway.
Sourcepub const POINTER_LOCK: Self
pub const POINTER_LOCK: Self
PointerMode::Locked is available: the
pointer can be hidden and pinned while relative motion keeps
flowing.
Wayland pointer-constraints + relative-pointer, X11 pointer
grab, Win32 clip-and-recentre, the browser’s Pointer Lock API.
The browser is the one that cannot take the lock when asked: it
grants requestPointerLock only inside a user gesture, so
set_pointer_mode there records
the request and the player’s next click completes it. The bit still
means what it says — the mode is available — and a consumer that
needs to know whether the pointer is pinned now reads the shape of
the motion events, as
PointerMode::Locked describes.
Sourcepub const POINTER_CONFINE: Self
pub const POINTER_CONFINE: Self
PointerMode::Confined is available: the
pointer stays inside the window but keeps moving visibly.
A separate bit from POINTER_LOCK because
Wayland’s pointer-constraints advertises lock and confine
independently, and a strategy game wants confine specifically.
Sourcepub const RAW_POINTER_MOTION: Self
pub const RAW_POINTER_MOTION: Self
Relative pointer motion is delivered separately from absolute position, unaccelerated and unclamped by the screen edge.
This is what a first-person camera must read;
the windowing rules make raw motion a P0 feature, not an
afterthought, on the grounds that an esports-grade engine cannot
derive aim from clamped absolute positions. Without this bit,
ShellEvent::PointerMotion
carries raw_delta: None and the camera has to difference absolute
positions — which is wrong at the screen edge and wrong under
pointer acceleration.
§The one platform that can decline the bypass
On the desktop backends the unaccelerated stream is a separate
device interface and either exists or does not. In a browser it is
an option on the lock — requestPointerLock({ unadjustedMovement: true }) — and a browser that does not implement it hands back the
OS-adjusted deltas instead, either by ignoring the key or by
rejecting with NotSupportedError and being asked again without it.
The web backend sets this bit because it reads a relative stream and
asks for it unadjusted, which is the decision a camera branches on:
differencing absolute positions is wrong there whatever the browser
answered. It is not a promise that every browser granted the bypass;
the web backend’s module docs name which browsers do.
Sourcepub const TEXT_IME: Self
pub const TEXT_IME: Self
The backend is wired to the platform’s input method, the framework CJK and other complex-script input runs through, end to end.
For a window that named a field with
Shell::set_text_input, the
composition in progress arrives as
ShellEvent::TextPreedit, the
conversion the user picks as
ShellEvent::TextCommit, and
Shell::set_text_input_area
is passed on so the input method can place its candidate window.
Whether the user runs an input method is not the shell’s to know;
the bit says one would reach the engine.
Wayland sets it when the compositor offers text-input-v3, Win32
through imm32, and AppKit through NSTextInputClient. Clear on
X11, which has no XIM, IBus or Fcitx client, and on the web. Dead keys and Compose sequences are
TEXT_COMPOSE, which a backend can have
without this.
Sourcepub const CLIPBOARD: Self
pub const CLIPBOARD: Self
Clipboard get/set works. See
clipboard.
Explicitly a capability because the browser gates clipboard reads behind a permission prompt and a user gesture, which the windowing rules call out by name: the editor UI has to degrade gracefully in-browser rather than offering a paste button that cannot work.
Sourcepub const DRAG_DROP: Self
pub const DRAG_DROP: Self
Files dragged onto a window arrive as
ShellEvent::DroppedFile.
Sourcepub const MULTI_WINDOW: Self
pub const MULTI_WINDOW: Self
The shell can create more than one window.
The MVP editor is single-window, and a canvas backend has exactly one canvas, so this is not universal. A consumer that wants a tear-off panel checks this rather than assuming.
Sourcepub const WINDOW_POSITION: Self
pub const WINDOW_POSITION: Self
Window position in desktop coordinates can be read and set.
Wayland cannot do either — a client is not told where it is and cannot ask to be moved. Anything that wants to restore a window’s position across sessions (the editor, topic 14’s settings store) must check this bit and degrade to “the compositor decides”.
Sourcepub const SERVER_DECORATIONS: Self
pub const SERVER_DECORATIONS: Self
The window system draws the title bar and borders.
Wayland with xdg-decoration and a compositor that opts in, and
every other desktop platform. Without it the UI layer has to draw
its own decorations, which is a layout decision, not a rendering
detail — so it belongs in caps rather than being discovered by
noticing the window looks wrong.
Sourcepub const FRACTIONAL_SCALE: Self
pub const FRACTIONAL_SCALE: Self
Scale factors other than whole integers are reported.
Wayland fractional-scale-v1 (in 1/120ths), Win32 per-monitor-v2,
browser devicePixelRatio. Without it the shell reports integer
scales only, and a 125% desktop shows up as 1.0 or 2.0 — which the
UI needs to know before it decides whether to snap its layout to a
pixel grid.
Sourcepub const EVENT_WAIT: Self
pub const EVENT_WAIT: Self
Shell::wait_events genuinely blocks.
An editor idling at zero frames per second on battery depends on
it; a game never calls it. Backends that cannot block — the browser
above all, where blocking the main thread is not a thing that
happens — leave this clear and their wait_events returns
immediately, which is always a correct implementation.
Sourcepub const TOUCH: Self
pub const TOUCH: Self
Fingers arrive as ShellEvent::Touch,
with a contact id and a phase, so more than one can be tracked at a
time.
Win32 is the one desktop backend that sets it (WM_POINTER*),
beside the browser. Clear on the others, and that is a statement
about the backends rather than about the platforms: a Linux tablet
has a touchscreen, and X11 (XInput2 XI_TouchBegin), Wayland
(wl_touch) and AppKit (NSTouch) all have a way to deliver one.
None of those paths is written, so a game on them sees no contacts
at all — an input that is absent, which is a different thing from
one that silently fails.
A backend that does set it owes the emulated pointer stream for the
primary contact as well; ShellEvent::Touch
says why, and that obligation is what stops a backend turning this on
from breaking every game that binds only the pointer.
Sourcepub const PANEL: Self
pub const PANEL: Self
WindowRole::Panel can be created:
desktop furniture held against a monitor’s edges.
Sourcepub const PANEL_RESERVE: Self
pub const PANEL_RESERVE: Self
A panel’s Reserve::OwnExtent is
honoured: maximised windows stop at the panel.
Separate from PANEL because a window system can
have panels and still give nothing but its own furniture reserved
space — macOS, where the panel is created and overlaps what is
behind it.
Sourcepub const POPUP: Self
pub const POPUP: Self
WindowRole::Popup can be created:
a window anchored to another’s rectangle.
Sourcepub const TRANSPARENT: Self
pub const TRANSPARENT: Self
WindowDesc::transparent is
honoured: where the frame’s alpha is below one, the desktop shows
through.
The window system’s half. The frame’s half is a swapchain that
carries alpha, premultiplied — which the HAL’s surface caps say
whether the driver offers, and which crcbl::engine::GpuContext
asks for when the window’s surface target says it is transparent
— and a renderer that clears to alpha zero. See
WindowDesc::transparent for the
whole recipe.
Sourcepub const POPUP_REPOSITION: Self
pub const POPUP_REPOSITION: Self
Shell::reposition_popup moves
and resizes a live popup.
Separate from POPUP because Wayland’s
xdg_popup.reposition arrived in xdg_wm_base 3, and a compositor
offering only 1 or 2 has popups that stay where they opened.
Sourcepub const ACCESSIBILITY: Self
pub const ACCESSIBILITY: Self
Shell::update_accessibility reaches the platform’s assistive
technologies, and the Accessibility* events are raised.
Set only by a backend built with the accesskit feature, which is
where that method and those events are, and an adapter for its
platform.
Sourcepub const TEXT_COMPOSE: Self
pub const TEXT_COMPOSE: Self
Dead keys and Compose sequences compose: a dead accent and the next
key, or a Compose-key sequence, arrive as one
ShellEvent::TextCommit carrying
the composed text.
libxkbcommon’s compose module on Wayland and X11, with the user’s
locale’s table; TranslateMessage on Win32; interpretKeyEvents:
on AppKit. Without it a backend may still commit plain typing, but
an accent typed through a dead key never lands on its letter. It
says nothing about an input method, which is
TEXT_IME: X11 composes and has none.
Sourcepub const PANEL_EXCLUSIVE_KEYBOARD: Self
pub const PANEL_EXCLUSIVE_KEYBOARD: Self
A panel with
PanelKeyboard::Exclusive
keeps the keyboard while it is mapped: the window system will not
give it to another window, whatever the user clicks.
Wayland’s layer-shell enforces it in the compositor, on the
Top and
Overlay layers; the protocol lets a
compositor use ordinary focus on the lower two. Clear on Win32 and
AppKit, where an exclusive panel takes the keyboard when it is
shown (or hears
FocusRefused) and the user
can click it away, which arrives as
Focus with focused: false. A
launcher that should close when it loses the keyboard closes on
that event; a lock screen cannot be built without this bit.
Sourcepub const CURSOR_SHAPE: Self
pub const CURSOR_SHAPE: Self
Shell::set_cursor with a shape
changes the cursor the user sees, to the platform’s own themed
cursor for that CursorIcon.
Win32’s stock user32 cursors, AppKit’s NSCursor, and the
canvas’s CSS cursor on the web; on Wayland, cursor-shape-v1
where the compositor offers it, which hands the compositor the
shape’s name and lets it draw the user’s theme; on X11, the user’s
XCursor theme loaded through libxcb-cursor, where that library is
installed. Without it, set_cursor still
accepts and records a shape — a UI calls it on every hover, and an
error there would be one every caller had to handle — and hiding
with None works everywhere; only the shape goes unseen.
Sourcepub const INPUT_REGION: Self
pub const INPUT_REGION: Self
Shell::set_input_region is
acted on: the pointer outside the region goes to whatever is behind
the window, another program’s window included.
Wayland’s wl_surface.set_input_region; X11’s SHAPE input region,
where libxcb-shape is installed and the server has SHAPE 1.1; a
window region on Win32, which also clips what the window draws.
Clear on AppKit, where an NSWindow has no input region, and on the
web, whose one canvas has nothing behind it to reach. Without it the
region is accepted and the whole window keeps the pointer, so a
launcher’s transparent corners stay its own.
Sourcepub const FRAME_CALLBACK: Self
pub const FRAME_CALLBACK: Self
ShellEvent::FrameReady is paced
by the compositor: it comes when the compositor wants the window’s
next frame, and is held back while nothing of the window is shown.
Wayland’s wl_surface.frame, which a compositor does not answer
for a surface on an output it has turned off — the case where a
FIFO present can block forever. Clear everywhere else, where
FrameReady comes at the next pump after
the request whatever is on screen, so the loop that waits for it
runs unchanged and the pacing is the present mode’s.
Sourcepub const IDLE_INHIBIT: Self
pub const IDLE_INHIBIT: Self
Shell::set_idle_inhibit is
acted on: while a window asks, the display stays on and the
screensaver does not start, however long nobody touches the
keyboard or the mouse.
What a gamepad-only player and a cutscene need, since neither moves
the input the system counts as activity. Win32 holds
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED) on the loop thread while any window asks.
Clear on Wayland (zwp_idle_inhibit_manager_v1), X11
(XScreenSaverSuspend), AppKit (IOPMAssertionCreateWithName) and
the web (Screen Wake Lock), none of which is wired; there the call
answers ShellError::Unsupported
and the display sleeps on the user’s schedule.
Sourcepub const OPEN_URL: Self
pub const OPEN_URL: Self
Shell::open_url is acted on: the
WebUrl is handed to the user’s web browser.
Win32 passes it to ShellExecuteW, which starts whatever is
registered for http and https. Clear on Wayland and X11
(org.freedesktop.portal.OpenURI or xdg-open), AppKit
(NSWorkspace openURL:) and the web (window.open), none of which
is wired; there the call answers
ShellError::Unsupported, and a
game can show the address for the player to copy instead.
Source§impl ShellCaps
impl ShellCaps
Sourcepub const fn bits(&self) -> u32
pub const fn bits(&self) -> u32
Get the underlying bits value.
The returned value is exactly the bits set in this flags value.
Sourcepub const fn from_bits(bits: u32) -> Option<Self>
pub const fn from_bits(bits: u32) -> Option<Self>
Convert from a bits value.
This method will return None if any unknown bits are set.
Sourcepub const fn from_bits_truncate(bits: u32) -> Self
pub const fn from_bits_truncate(bits: u32) -> Self
Convert from a bits value, unsetting any unknown bits.
Sourcepub const fn from_bits_retain(bits: u32) -> Self
pub const fn from_bits_retain(bits: u32) -> Self
Convert from a bits value exactly.
Sourcepub fn from_name(name: &str) -> Option<Self>
pub fn from_name(name: &str) -> Option<Self>
Get a flags value with the bits of a flag with the given name set.
This method will return None if name is empty or doesn’t
correspond to any named flag.
Sourcepub const fn intersects(&self, other: Self) -> bool
pub const fn intersects(&self, other: Self) -> bool
Whether any set bits in other are also set in self.
Sourcepub const fn contains(&self, other: Self) -> bool
pub const fn contains(&self, other: Self) -> bool
Whether all set bits in other are also set in self.
Sourcepub fn remove(&mut self, other: Self)
pub fn remove(&mut self, other: Self)
The intersection of self with the complement of other (&!).
This method is not equivalent to self & !other when other has unknown bits set.
remove won’t truncate other, but the ! operator will.
Sourcepub fn toggle(&mut self, other: Self)
pub fn toggle(&mut self, other: Self)
The bitwise exclusive-or (^) of the bits in self and other.
Sourcepub fn set(&mut self, other: Self, value: bool)
pub fn set(&mut self, other: Self, value: bool)
Call insert when value is true or remove when value is false.
Sourcepub const fn intersection(self, other: Self) -> Self
pub const fn intersection(self, other: Self) -> Self
The bitwise and (&) of the bits in self and other.
Sourcepub const fn union(self, other: Self) -> Self
pub const fn union(self, other: Self) -> Self
The bitwise or (|) of the bits in self and other.
Sourcepub const fn difference(self, other: Self) -> Self
pub const fn difference(self, other: Self) -> Self
The intersection of self with the complement of other (&!).
This method is not equivalent to self & !other when other has unknown bits set.
difference won’t truncate other, but the ! operator will.
Sourcepub const fn symmetric_difference(self, other: Self) -> Self
pub const fn symmetric_difference(self, other: Self) -> Self
The bitwise exclusive-or (^) of the bits in self and other.
Sourcepub const fn complement(self) -> Self
pub const fn complement(self) -> Self
The bitwise negation (!) of the bits in self, truncating the result.
Source§impl ShellCaps
impl ShellCaps
Source§impl ShellCaps
impl ShellCaps
Sourcepub const DESKTOP: Self
pub const DESKTOP: Self
The set a full-featured desktop backend is expected to report.
Not a promise about any particular platform — it is the reference point
tests and HeadlessShell start from, and the
value a doc example can name without pretending to know what the machine
running it supports.
Sourcepub const fn has_pointer_capture(self) -> bool
pub const fn has_pointer_capture(self) -> bool
Whether pointer capture in either form is available.
Sourcepub const fn has_mouselook(self) -> bool
pub const fn has_mouselook(self) -> bool
Whether a first-person camera can get trustworthy aim input: the pointer can be locked and relative motion is delivered.
Both halves are required, and this helper exists because forgetting the second one produces a camera that works until the pointer reaches the edge of the screen.
Trait Implementations§
Source§impl BitAndAssign for ShellCaps
impl BitAndAssign for ShellCaps
Source§fn bitand_assign(&mut self, other: Self)
fn bitand_assign(&mut self, other: Self)
The bitwise and (&) of the bits in self and other.
Source§impl BitOrAssign for ShellCaps
impl BitOrAssign for ShellCaps
Source§fn bitor_assign(&mut self, other: Self)
fn bitor_assign(&mut self, other: Self)
The bitwise or (|) of the bits in self and other.
Source§impl BitXorAssign for ShellCaps
impl BitXorAssign for ShellCaps
Source§fn bitxor_assign(&mut self, other: Self)
fn bitxor_assign(&mut self, other: Self)
The bitwise exclusive-or (^) of the bits in self and other.
impl Copy for ShellCaps
impl Eq for ShellCaps
Source§impl Extend<ShellCaps> for ShellCaps
impl Extend<ShellCaps> for ShellCaps
Source§fn extend<T: IntoIterator<Item = Self>>(&mut self, iterator: T)
fn extend<T: IntoIterator<Item = Self>>(&mut self, iterator: T)
The bitwise or (|) of the bits in each flags value.
Source§fn extend_one(&mut self, item: T)
fn extend_one(&mut self, item: T)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§impl Flags for ShellCaps
impl Flags for ShellCaps
Source§fn from_bits_retain(bits: u32) -> ShellCaps
fn from_bits_retain(bits: u32) -> ShellCaps
Source§fn known_bits(&self) -> Self::Bits
fn known_bits(&self) -> Self::Bits
Source§fn unknown_bits(&self) -> Self::Bits
fn unknown_bits(&self) -> Self::Bits
Source§fn contains_unknown_bits(&self) -> bool
fn contains_unknown_bits(&self) -> bool
true if any unknown bits are set.Source§fn from_bits_truncate(bits: Self::Bits) -> Self
fn from_bits_truncate(bits: Self::Bits) -> Self
Source§fn from_name(name: &str) -> Option<Self>
fn from_name(name: &str) -> Option<Self>
Source§fn iter_names(&self) -> IterNames<Self> ⓘ
fn iter_names(&self) -> IterNames<Self> ⓘ
Source§fn iter_defined_names() -> IterDefinedNames<Self> ⓘ
fn iter_defined_names() -> IterDefinedNames<Self> ⓘ
Self::FLAGS.Source§fn iter_equal_names(&self) -> IterEqualNames<Self> ⓘ
fn iter_equal_names(&self) -> IterEqualNames<Self> ⓘ
Source§fn intersects(&self, other: Self) -> boolwhere
Self: Sized,
fn intersects(&self, other: Self) -> boolwhere
Self: Sized,
other are also set in self.Source§fn contains(&self, other: Self) -> boolwhere
Self: Sized,
fn contains(&self, other: Self) -> boolwhere
Self: Sized,
other are also set in self.Source§fn insert(&mut self, other: Self)where
Self: Sized,
fn insert(&mut self, other: Self)where
Self: Sized,
|) of the bits in self and other.Source§fn toggle(&mut self, other: Self)where
Self: Sized,
fn toggle(&mut self, other: Self)where
Self: Sized,
^) of the bits in self and other.Source§fn intersection(self, other: Self) -> Self
fn intersection(self, other: Self) -> Self
&) of the bits in self and other.Source§fn difference(self, other: Self) -> Self
fn difference(self, other: Self) -> Self
Source§fn symmetric_difference(self, other: Self) -> Self
fn symmetric_difference(self, other: Self) -> Self
^) of the bits in self and other.Source§fn complement(self) -> Self
fn complement(self) -> Self
!) of the bits in self, truncating the result.Source§impl FromIterator<ShellCaps> for ShellCaps
impl FromIterator<ShellCaps> for ShellCaps
Source§fn from_iter<T: IntoIterator<Item = Self>>(iterator: T) -> Self
fn from_iter<T: IntoIterator<Item = Self>>(iterator: T) -> Self
The bitwise or (|) of the bits in each flags value.