API — ICoreEssentials/UI/Backends/Web/Widgets
The public contract of 15 header(s) under ICoreEssentials/UI/Backends/Web/Widgets — 21 class/struct definition(s), 195 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.
ICoreWebAccessibility.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebAccessibility.h
The accessibility floor for the web backend: what a screen reader is told about a tree of ICoreWebNodes that is, to the browser, one opaque <canvas>.
⚠ THE SURFACE IS THE GTK4 FLOOR'S (UI/Backends/Gtk4/Widgets/ ICoreGtk4Accessibility.h), with the toolkit type taken out, so a web seat ported from a GTK4 seat keeps its accessibility calls line for line. The reasons for each rule a caller follows -- the empty-string reset, Undefined as a fourth tristate value, a checkable button being a CHECKBOX -- are in that header and are not repeated here.
⚠⚠ WHY A RECORD AND NOT A DOM CALL. A canvas has no children to put a role on. Every call below writes into a plain C++ record kept beside the node, and once per frame the DOM half (ICoreWebAccessibilityDom.cpp) turns the records under each window into ARIA elements INSIDE that window's <canvas> -- the
ICoreWebAccessibleElement#
ICoreWebAccessibility.h:124 · struct · 0 declaration(s)
One ARIA element.
struct ICoreWebAccessibleElement {
public:
unsigned long id = 0;
unsigned long parent = 0;
const ICoreWebNode* node = nullptr;
std::string text; // a Label's content
std::vector<std::pair<std::string, std::string>> attributes; // role, aria-*
};
};
File-scope declarations#
enum class ICoreWebAccessibleRole {
Presentation, // no element; children hoisted (ARIA, not GTK -- see above)
Generic, // the default of every node, and no element either
Group,
Button,
CheckBox,
Radio,
Switch,
Label, // text content, not a role
TextBox,
SearchBox,
SpinButton,
Slider,
ProgressBar,
ScrollBar,
Separator,
ToolBar,
List,
ListItem,
TreeGrid,
Row,
Tab,
TabList,
TabPanel,
Menu,
MenuBar,
MenuItem,
ComboBox,
Document,
Image,
Dialog,
Window,
};
enum class ICoreWebAccessibleTristate { False, True, Mixed, Undefined };
ICoreWebButtonPainter.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebButtonPainter.h
The web backend's copy of UI/Backends/Gtk4/Widgets/ICoreGtk4ButtonPainter.h, which names no toolkit; its reasoning is in that file.
Declares no class of its own — see the file.
ICoreWebEditorCore.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebEditorCore.h
ICoreWebEditorCore#
ICoreWebEditorCore.h:41 · class · pImpl · 38 declaration(s)
What ICoreTextEdit and ICoreRichTextEdit share on the web (web backend, WB5.3): one node, one painted text view (ICoreWebTextView over the WB5.1 document), one hidden input sink (ICoreWebInputSink)...
class ICoreWebEditorCore {
public:
enum class Chrome { Field, None };
explicit ICoreWebEditorCore(Chrome chrome);
~ICoreWebEditorCore();
ICoreWebEditorCore(const ICoreWebEditorCore&) = delete;
ICoreWebEditorCore& operator=(const ICoreWebEditorCore&) = delete;
[[nodiscard]] ICoreWebNode& node();
[[nodiscard]] ICoreWebTextView& view();
[[nodiscard]] Chrome chrome() const;
// ---- appearance ------------------------------------------------------------
void setFont(const ICoreFont& font);
[[nodiscard]] ICoreFont font() const; // the set font, or the theme's
void setEnabled(bool enabled);
[[nodiscard]] bool isEnabled() const;
void setReadOnly(bool readOnly);
void setPlaceholder(const ICoreString& text);
void setBorderOpacity(double opacity);
[[nodiscard]] double borderOpacity() const;
void setViewportMargins(int left, int top, int right, int bottom);
void setFixedHeight(int height);
void setMinimumHeight(int height);
// The height `lines` rows of the font take inside the field chrome.
void setVisibleLines(int lines);
[[nodiscard]] double lineSpacing() const;
// ---- geometry: node-local unless named otherwise ----------------------------
[[nodiscard]] ICoreRect textRect() const; // the text viewport
[[nodiscard]] ICoreRect toNode(const ICoreRect& content) const;
void toContent(double nodeX, double nodeY, double& contentX, double& contentY) const;
// ---- output: coloured chunks and sections (ICoreTextEdit's console) ---------
// Append at the end without recording undo; `colour` null = the ink.
// `startsSection` marks the chunk's first row for visibleSectionTops().
void appendChunk(const std::u16string& text, const ICoreColor* colour, bool startsSection);
// Node-local tops of the section rows that are on screen, down to bottomY.
[[nodiscard]] std::vector<double> visibleSectionTops(double bottomY) const;
void clearSections();
// ---- focus -----------------------------------------------------------------
void takeFocus();
[[nodiscard]] bool hasFocus() const;
void requestRepaint();
// ---- what the owning seat hooks ----------------------------------------------
// Offered every key first; true = the owner took it and the view never sees it.
std::function<bool(const ICoreWebKeyInput&)> keyFilter;
// Told after the view acted on a key the filter did not take.
std::function<void(const ICoreWebKeyInput&)> keyProcessed;
std::function<bool(const ICoreWebScrollInput&)> wheelFilter;
std::function<bool(const ICoreWebPointerInput&)> pressFilter;
std::function<bool(const ICoreWebPointerInput&)> contextMenuFilter;
std::function<void(const ICoreWebPointerInput&)> moveObserver;
std::function<void()> leftObserver;
std::function<void(ICorePainter&, const ICoreRect&)> paintUnder; // node-local bounds
std::function<void(ICorePainter&, const ICoreRect&)> paintOver;
std::function<void(int width, int height, int oldWidth, int oldHeight)> resizedObserver;
// ⚠ THE CORE OWNS THE VIEW'S CURSOR AND SCROLL HOOKS (a hook holds one
// callback, and the core needs both for the caret blink and the sink's
// placement). A seat observes through these instead of replacing them --
// the rich seat's first draft set the view's hooks itself and silently
// switched both off.
std::function<void()> cursorObserver;
std::function<void()> scrollObserver;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreWebFieldChrome.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebFieldChrome.h
Declares no class of its own — see the file.
ICoreWebInputSink.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebInputSink.h
The keyboard and input-method sink for the web backend's PAINTED text editors (web backend, WB5.3): one <textarea> that is never shown, placed at the caret, holding DOM focus while its editor has focus.
⚠ NOT ICoreWebTextEntry, AND THE DIFFERENCE IS THE CONTRACT. That seat's <input> IS the field's model and draws its value while focused (WB2.3). This element holds nothing: the editor's model is the WB5.1 document, painted on the canvas, and the textarea exists only because a page receives typed text, input-method compositions and clipboard events through a focused editable element and no other way. Its value is emptied after every event. Agreed with the WB2.3 text-entry work, so neither header carries a mode it does not need.
⚠⚠ THE CLIPBOARD ARRIVES AS DOM EVENTS, NOT AS KEYS. Ctrl/Cmd+C, X and V are
ICoreWebInputSink#
ICoreWebInputSink.h:37 · class · pImpl · 12 declaration(s)
class ICoreWebInputSink {
public:
ICoreWebInputSink();
~ICoreWebInputSink();
ICoreWebInputSink(const ICoreWebInputSink&) = delete;
ICoreWebInputSink& operator=(const ICoreWebInputSink&) = delete;
// A key went down (or up). `key`/`code` are the DOM's KeyboardEvent.key and
// .code; flags bit 1 Shift, 2 Ctrl, 4 Alt, 8 Meta. Return true when handled:
// the browser's default is then prevented.
void setKeyHook(std::function<bool(bool down, const std::string& key, const std::string& code,
unsigned int flags, bool repeat)> hook);
// Text the textarea received that no key hook consumed: a committed
// composition, a dictation, a character the key path did not type.
void setTextHook(std::function<void(const std::u16string& text)> hook);
// The composition's current preedit; empty when it ends or is cancelled.
void setCompositionHook(std::function<void(const std::u16string& preedit)> hook);
// copy/cut: return the text to put on the clipboard (empty = nothing). The
// hook deletes the selection itself for a cut.
void setCopyHook(std::function<std::u16string(bool cut)> hook);
void setPasteHook(std::function<void(const std::u16string& text)> hook);
// DOM focus left the sink (another element or another app took it).
void setBlurHook(std::function<void()> hook);
void focus();
void blur();
// Put the element at the caret, in page (CSS) pixels, in front of the window
// canvas `canvasHandle` (ICoreWebWindow::canvas()) -- the input method's
// candidate window opens where the element is.
void place(int canvasHandle, double pageX, double pageY, double lineHeight);
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreWebItemDelegateAccess.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebItemDelegateAccess.h
Web backend, WB2.4 -- the delegate's Impl, shared by the tree, ported from UI/Backends/Gtk4/Widgets/ICoreGtk4ItemDelegateAccess.h onto ICoreWebNode. The reasons for the behaviour are in that file's comments and are not repeated here; a behaviour change in one belongs in both.
ICoreItemDelegateHooks#
ICoreWebItemDelegateAccess.h:11 · class · 4 declaration(s)
class ICoreItemDelegateHooks {
public:
virtual ~ICoreItemDelegateHooks() = default;
virtual bool paint(ICorePainter& painter, const ICoreItemRenderContext& context) = 0;
virtual ICoreSizeF sizeHint(const ICoreItemRenderContext& context) = 0;
virtual ICoreColor selectedTextColorFor(const ICoreItemRenderContext& context) = 0;
};
};
ICoreItemDelegate#
ICoreWebItemDelegateAccess.h:21 · class · bases :Impl : public ICoreItemDelegateHooks · 4 declaration(s)
class ICoreItemDelegate : :Impl : public ICoreItemDelegateHooks {
public:
explicit Impl(ICoreItemDelegate& owner);
bool paint(ICorePainter& painter, const ICoreItemRenderContext& context) override;
ICoreSizeF sizeHint(const ICoreItemRenderContext& context) override;
ICoreColor selectedTextColorFor(const ICoreItemRenderContext& context) override;
ICoreItemDelegate* m_owner;
};
};
ICoreWebItemViewPainter.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebItemViewPainter.h
Web backend, WB2.4 -- the item-view ink and row painter, ported from UI/Backends/Gtk4/Widgets/ICoreGtk4ItemViewPainter.h onto ICoreWebNode. The reasons for the behaviour are in that file's comments and are not repeated here; a behaviour change in one belongs in both.
ICoreWebItemRowInk#
ICoreWebItemViewPainter.h:15 · struct · 0 declaration(s)
struct ICoreWebItemRowInk {
public:
ICoreRgba wash;
ICoreRgba ink;
bool spansRow = false;
ICoreRgba leftEdge;
double leftEdgeWidth = 0.0;
ICoreRgba hairline;
double hairlineWidth = 0.0;
double radius = -1.0;
double paddingLeft = 0.0;
};
};
ICoreWebItemHeaderInk#
ICoreWebItemViewPainter.h:38 · struct · 0 declaration(s)
struct ICoreWebItemHeaderInk {
public:
ICoreRgba background;
ICoreRgba ink;
ICoreRgba underline; // borderBottom -- "no frame, one hairline"
double underlineWidth = 0.0;
double paddingLeft = 0.0;
};
};
ICoreWebNode.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebNode.h
The web backend's native widget: a node in a retained tree that is painted into one canvas per window.
⚠ THERE IS NO TOOLKIT WIDGET UNDER AN ICoreWidget IN A BROWSER. Every desktop seat forwards to an object its toolkit owns -- a GtkWidget, an NSView, a XAML element -- and that object does the picking, the focus, the enter/leave and the clipping. A <canvas> does none of it, so this class does. Its surface is deliberately the GTK4 seat's native object's (UI/Backends/Gtk4/Widgets/ ICoreGtk4Widget.h) with the toolkit types taken out: the web ICoreWidget seat is that seat's logic, and it should read the same.
⚠ NO EMSCRIPTEN HERE. The tree, the picking and the routing are plain C++, so they are tested under node with no page at all. What reaches the browser is the window seat that owns a root (it implements ICoreWebNodeHost) and the
ICoreWebPointerInput#
ICoreWebNode.h:45 · struct · 0 declaration(s)
What a pointer hook is handed.
struct ICoreWebPointerInput {
public:
double x = 0.0;
double y = 0.0;
double rootX = 0.0;
double rootY = 0.0;
unsigned int button = 0; // ICoreMouseButton bit of the button that changed; 0 for a move
unsigned int buttons = 0; // ICoreMouseButton bits held
unsigned int modifiers = 0; // ICoreKeyModifier bits
int pressCount = 0; // 2 is a double click
bool firstDelivery = false; // the first node this event reached
};
};
ICoreWebKeyInput#
ICoreWebNode.h:57 · struct · 0 declaration(s)
struct ICoreWebKeyInput {
public:
int key = 0; // ICoreKey
unsigned int modifiers = 0; // ICoreKeyModifier bits
std::string text; // UTF-8; empty for a non-printing key
};
};
ICoreWebScrollInput#
ICoreWebNode.h:63 · struct · 1 declaration(s)
struct ICoreWebScrollInput {
public:
double x = 0.0; // node-local
double y = 0.0;
double deltaX = 0.0; // ICoreWheelEvent units (120 per notch)
double deltaY = 0.0;
unsigned int modifiers = 0;
};
};
ICoreWebAppliedGround#
ICoreWebNode.h:74 · struct · 0 declaration(s)
A ground a style spec asked for (icoreApplyStyleSpec): painted under the node's own paint hook, as AppKit's view paints its applied ground under its content.
struct ICoreWebAppliedGround {
public:
bool hasFill = false;
double fillR = 0.0, fillG = 0.0, fillB = 0.0, fillA = 0.0;
bool hasBorder = false;
double borderR = 0.0, borderG = 0.0, borderB = 0.0, borderA = 0.0;
double borderWidth = 0.0;
double cornerRadius = 0.0;
};
};
ICoreWebShadowSpec#
ICoreWebNode.h:83 · struct · 0 declaration(s)
struct ICoreWebShadowSpec {
public:
bool enabled = false;
double blur = 0.0;
double dx = 0.0;
double dy = 0.0;
double cornerRadius = 0.0;
double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
};
};
ICoreWebNodeHost#
ICoreWebNode.h:93 · class · 6 declaration(s)
What a ROOT node reports to, which is the window seat.
class ICoreWebNodeHost {
public:
virtual ~ICoreWebNodeHost() = default;
// Part of the tree under `root` needs painting; `area` is in root space.
virtual void nodeNeedsRepaint(ICoreWebNode* root, const ICoreRect& area) = 0;
virtual double devicePixelRatio() const = 0;
// Where the root's (0, 0) is in page coordinates.
virtual void rootOrigin(double& x, double& y) const = 0;
// The CSS cursor the node under the pointer asks for changed.
virtual void cursorChanged(const std::string& css) = 0;
virtual void tooltipChanged(const std::string& text) = 0;
};
};
ICoreWebNode#
ICoreWebNode.h:106 · class · pImpl · 83 declaration(s)
class ICoreWebNode {
public:
ICoreWebNode();
// Detaches from the parent and from every child; deletes nothing. The
// ICoreWidget seat owns its children, as it does on every native backend.
~ICoreWebNode();
ICoreWebNode(const ICoreWebNode&) = delete;
ICoreWebNode& operator=(const ICoreWebNode&) = delete;
// ---- the tree ----------------------------------------------------------
void addChild(ICoreWebNode* child); // on top of its siblings
void removeChild(ICoreWebNode* child);
[[nodiscard]] ICoreWebNode* parentNode() const;
[[nodiscard]] const std::vector<ICoreWebNode*>& children() const;
[[nodiscard]] ICoreWebNode* root();
[[nodiscard]] bool isAncestorOf(const ICoreWebNode* descendant) const;
void raiseAboveSiblings();
// A root reports repaints, the cursor and the tooltip to its host. A node
// with no host and no parent is a tree nobody shows.
void setHost(ICoreWebNodeHost* host);
[[nodiscard]] ICoreWebNodeHost* host() const; // the ROOT's host
// The ICoreWidget seat that owns this node, for the routing that has to get
// back from a node to a wrapper.
void setSeat(void* seat);
[[nodiscard]] void* seat() const;
// ---- geometry, in the parent's space -----------------------------------
void setFrame(int x, int y, int width, int height);
void frame(int& x, int& y, int& width, int& height) const;
void setSizeLimits(int minimumWidth, int minimumHeight, int maximumWidth, int maximumHeight);
void sizeLimits(int& minimumWidth, int& minimumHeight, int& maximumWidth,
int& maximumHeight) const;
void setContentsMargins(int left, int top, int right, int bottom);
void contentsMargins(int& left, int& top, int& right, int& bottom) const;
void setNaturalSize(int width, int height);
// GTK4's measure, rule for rule: natural is max(minimum, stated natural,
// own frame, the extent of the visible children's frames); minimum is the
// stated minimum. contentNaturalSize is the same WITHOUT the own-frame term
// and without children marked hosted-fill -- the answer a layout asks for
// when the frame it wrote must not come back as a preference.
void naturalSize(int& width, int& height) const;
void minimumSize(int& width, int& height) const;
void contentNaturalSize(int& width, int& height) const;
void setHostedFill(bool hostedFill);
void setStretch(int horizontal, int vertical);
void stretch(int& horizontal, int& vertical) const;
void setGroundRadius(double radius);
[[nodiscard]] double groundRadius() const;
// The layout tier's single slot, and any number of observers keyed by an
// owner pointer; both fire from notifyResized(). The ONE content-hint slot
// is a scroll pane's, as on GTK4.
void setLayoutResizedHook(std::function<void(int width, int height)> hook);
void addResizeObserver(const void* key, std::function<void(int, int)> observer);
void removeResizeObserver(const void* key);
void notifyLayoutResized(int width, int height);
void notifyResizeObservers(int width, int height);
void setContentHintChangedHook(std::function<void()> hook);
void notifyContentHintChanged();
// The seat-LESS wrapper (an ICoreLabel, a button -- not an ICoreWidget) that
// owns this node. Whichever node it is parented into DELETES it when that
// node dies, as GTK4's area does (icoreGtk4AttachOwnedWrapper): an
// ICoreWidget parent only deletes the ICoreWidget children on its own list.
void setOwnedWrapper(ICoreNativeWidget* wrapper);
// Something this node owns and releases when it is destroyed -- a layout
// installed on it, as GTK parks one on the widget with a destroy notify.
// Released in the order they were given, after the node has left the tree.
void ownUntilDestroyed(std::function<void()> release);
// GTK's queue_resize: re-run this node's layout on the next frame rather
// than now. flushPendingLayouts() runs every pending layout with the
// node's current size, in the order they were asked for; the window host
// calls it at the end of each frame, before it paints.
void requestRelayout();
static void flushPendingLayouts();
// Whether `address` is a node that is alive now -- the web's GTK_IS_WIDGET,
// for a nativeWidgetHandle() that may belong to something else.
[[nodiscard]] static bool isLive(const void* address);
void mapToRoot(double localX, double localY, double& rootX, double& rootY) const;
void mapFromRoot(double rootX, double rootY, double& localX, double& localY) const;
[[nodiscard]] double devicePixelRatio() const;
// ---- state -------------------------------------------------------------
void setVisible(bool visible);
[[nodiscard]] bool isVisible() const; // this node's own flag
[[nodiscard]] bool isVisibleInTree() const; // and every ancestor's
void setEnabled(bool enabled);
[[nodiscard]] bool isEnabledInTree() const;
void setFocusable(bool focusable);
[[nodiscard]] bool isFocusable() const;
[[nodiscard]] bool hasFocus() const;
// False when the node cannot take focus: not focusable, hidden, disabled.
bool takeFocus();
void setPointerTransparent(bool transparent);
[[nodiscard]] bool isPointerTransparent() const;
// A node that claims the keyboard gets every key while it has focus, before
// any shortcut does -- a text field's Ctrl+Z is its own undo, not the
// window's. ICoreWidget::setClaimsKeyboard sets it.
void setClaimsKeyboard(bool claims);
[[nodiscard]] bool claimsKeyboard() const;
void setClipsChildren(bool clip);
[[nodiscard]] bool clipsChildren() const;
void setOpacity(double opacity);
[[nodiscard]] double opacity() const;
// The subtree drawn SCALED about the node's own origin: the frame stays in
// the parent's units, while the node's paint, its children and its input are
// in units the parent multiplies by `scale`. GTK4's child transform reduced to
// the uniform scale a proxy overlay needs (WB4.3). 1 is none; a non-positive
// or non-finite value is ignored. A root's scale is not used.
void setContentScale(double scale);
[[nodiscard]] double contentScale() const;
void setAppliedGround(const ICoreWebAppliedGround& ground);
[[nodiscard]] ICoreWebAppliedGround appliedGround() const;
void setShadow(const ICoreWebShadowSpec& spec);
[[nodiscard]] ICoreWebShadowSpec shadow() const;
void setCursorCss(const std::string& css); // empty inherits the parent's
[[nodiscard]] std::string effectiveCursorCss() const;
void setTooltip(const std::string& text);
// The node's own tooltip; empty when it has none (a parent's does not count).
[[nodiscard]] std::string tooltip() const;
[[nodiscard]] bool isUnderPointer() const;
void requestRepaint();
void requestRepaint(int x, int y, int width, int height);
// ---- painting ----------------------------------------------------------
// The body hook paints before the children, the overlay hook after them.
void setPaintHook(std::function<void(ICorePainter&, int width, int height)> hook);
void setOverlayPaintHook(std::function<void(ICorePainter&, int width, int height)> hook);
// Paints this node and its subtree with the node's (0, 0) at the painter's
// current origin. A hidden node paints nothing.
void renderTo(ICorePainter& painter) const;
// ---- hooks -------------------------------------------------------------
void setResizedHook(std::function<void(int width, int height)> hook);
void setHoverHook(std::function<void(bool inside)> hook);
void setFocusHook(std::function<void(bool focused)> hook);
void setPointerPressedHook(std::function<bool(const ICoreWebPointerInput&)> hook);
void setPointerReleasedHook(std::function<bool(const ICoreWebPointerInput&)> hook);
void setPointerMovedHook(std::function<bool(const ICoreWebPointerInput&)> hook);
void setKeyPressedHook(std::function<bool(const ICoreWebKeyInput&)> hook);
void setKeyReleasedHook(std::function<bool(const ICoreWebKeyInput&)> hook);
void setScrollHook(std::function<bool(const ICoreWebScrollInput&)> hook);
// The press this node took will not be completed: no release follows
// (ICoreWidget::mouseGestureCancelled; ICoreWebInputRouter::pointerCancelled).
void setPointerCancelledHook(std::function<void()> hook);
// The deepest pickable node at a ROOT-space point, or null.
[[nodiscard]] ICoreWebNode* pick(double rootX, double rootY);
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreWebInputRouter#
ICoreWebNode.h:272 · class · 10 declaration(s)
Routes input for one ROOT: picking, implicit pointer capture, enter/leave, click-to-focus and bubbling.
class ICoreWebInputRouter {
public:
// Coordinates are ROOT space. `button` is the ICoreMouseButton bit that
// changed; `buttons` the bits held after the change.
static bool pointerPressed(ICoreWebNode* root, double x, double y, unsigned int button,
unsigned int buttons, unsigned int modifiers, int pressCount);
static bool pointerReleased(ICoreWebNode* root, double x, double y, unsigned int button,
unsigned int buttons, unsigned int modifiers);
static bool pointerMoved(ICoreWebNode* root, double x, double y, unsigned int buttons,
unsigned int modifiers);
// The pointer left the root altogether: every hovered node is left.
static void pointerLeftRoot(ICoreWebNode* root);
// The press in progress will not be completed (a finger's long press that
// showed a tooltip, TB1.7): the node holding the capture hears its
// cancelled hook, the capture is dropped, and no release is delivered.
static void pointerCancelled(ICoreWebNode* root);
// Moves the hover to `node` and its ancestors (null: nothing hovered), with
// the enter and leave crossings a pointer move would deliver -- for a
// hover that no pointer is producing, a finger's long press (TB1.7).
static void setHover(ICoreWebNode* root, ICoreWebNode* node);
[[nodiscard]] static bool isHovered(ICoreWebNode* root, const ICoreWebNode* node);
static bool scrolled(ICoreWebNode* root, double x, double y, double deltaX, double deltaY,
unsigned int modifiers);
static bool keyPressed(ICoreWebNode* root, const ICoreWebKeyInput& key);
static bool keyReleased(ICoreWebNode* root, const ICoreWebKeyInput& key);
// The node that holds the pointer capture, the one under the pointer, the
// focused one -- null when none.
static ICoreWebNode* captured(ICoreWebNode* root);
static ICoreWebNode* hovered(ICoreWebNode* root);
static ICoreWebNode* focused(ICoreWebNode* root);
// Called with every node a press lands in, before routing -- the GTK4 seat's
// press observer, which "click outside a popup" is built on.
static void setPressObserver(std::function<void(ICoreWebNode* pressed)> observer);
};
};
ICoreWebScrollBarPainter.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebScrollBarPainter.h
The web backend's copy of UI/Backends/Gtk4/Widgets/ICoreGtk4ScrollBarPainter.h (web backend, WB2.5).
⚠ THIS FILE NAMES NO TOOLKIT, AND IT IS THE GTK4 PAINTER WITH THE BACKEND NAME CHANGED: it draws through ICorePainter from the theme's ICoreStyleSpec. The reasoning behind every line is in that file's comments and is not repeated here (one fact, one place). A change to the shared behaviour belongs in BOTH copies.
ICoreWebScrollBarInk#
ICoreWebScrollBarPainter.h:19 · struct · 0 declaration(s)
struct ICoreWebScrollBarInk {
public:
ICoreRgba track;
ICoreRgba thumb;
ICoreRgba thumbBorder;
double thumbBorderWidth = -1.0; // < 0 is unset, per ICoreStyleEdge
double radius = -1.0;
};
};
File-scope declarations#
enum class ICoreWebScrollThumbState { Idle, Hover, Pressed };
ICoreWebSpinBoxPainter.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebSpinBoxPainter.h
The web backend's copy of UI/Backends/Gtk4/Widgets/ICoreGtk4SpinBoxPainter.h, which names no toolkit; its reasoning is in that file (web backend, WB2.2).
Declares no class of its own — see the file.
ICoreWebSplitterPainter.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebSplitterPainter.h
The web backend's splitter divider painter (WB2.6): UI/Backends/Gtk4/Widgets/ICoreGtk4SplitterPainter.h with the backend renamed. It draws through ICorePainter and names no toolkit, so the reasoning for every rule in it -- the Normal rule first and the state rule as an overlay, the half-pen inset, pressed before hover -- is on the original's banner, which stays the authority. A behaviour change in one belongs in both.
Backend-private: include it from a .cpp inside UI/Backends/Web/ and nowhere else.
ICoreWebSplitterHandleInk#
ICoreWebSplitterPainter.h:22 · struct · 0 declaration(s)
struct ICoreWebSplitterHandleInk {
public:
ICoreRgba background;
ICoreRgba border;
double borderWidth = -1.0; // < 0 is unset, per ICoreStyleEdge
};
};
File-scope declarations#
enum class ICoreWebSplitterHandleState { Idle, Hover, Pressed };
ICoreWebStandardItemAccess.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebStandardItemAccess.h
Web backend, WB2.4 -- the standard item's Impl, shared by the model and the view, ported from UI/Backends/Gtk4/Widgets/ICoreGtk4StandardItemAccess.h onto ICoreWebNode. The reasons for the behaviour are in that file's comments and are not repeated here; a behaviour change in one belongs in both.
ICoreStandardItem#
ICoreWebStandardItemAccess.h:17 · class · bases :Impl · 10 declaration(s)
class ICoreStandardItem : :Impl {
public:
explicit Impl(ICoreStandardItem& owner);
Impl(ICoreStandardItem& owner, const ICoreString& text);
~Impl();
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
void detachOwner();
ICoreStandardItem* owner() const;
void setRoleText(int role, const ICoreString& value);
void setRoleInt(int role, int value);
ICoreString roleAsText(int role) const;
ICoreString label;
ICoreIcon icon;
bool hasIcon = false;
bool editable = true;
std::map<int, ICoreString> textRoles;
std::map<int, int> intRoles;
std::vector<std::shared_ptr<Impl>> children;
std::vector<std::shared_ptr<Impl>> cells;
Impl* parentNode = nullptr;
std::weak_ptr<Impl> selfWeak;
ICoreStandardItem* m_owner = nullptr;
};
};
ICoreWebTextEntry.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebTextEntry.h
The web backend's text-entry seat (WB2.3): one DOM <input> that holds a field's VALUE -- the text, the caret, the selection -- and that is shown over the field while the field has focus.
It is what the GtkText is to the GTK4 line edit: the editable core, owned by the platform, with the chrome drawn around it by this tree. The browser gives it the caret, the selection, the input method, the mobile keyboard, autofill, the clipboard, undo and the accessibility tree, which is why a painted field is the one control this tree says not to build (the GTK4 seat's banner).
⚠ SHOWN ONLY WHILE EDITING. A DOM element cannot be under anything painted on its window's canvas, so an input left up on every field would float over a painted popup and escape a scroll pane's clip. While a field is not focused the canvas paints its value like any other text; show() puts the input over
ICoreWebTextEntry#
ICoreWebTextEntry.h:35 · class · pImpl · 23 declaration(s)
class ICoreWebTextEntry {
public:
enum class Echo { Normal, Password, None };
ICoreWebTextEntry();
~ICoreWebTextEntry();
ICoreWebTextEntry(const ICoreWebTextEntry&) = delete;
ICoreWebTextEntry& operator=(const ICoreWebTextEntry&) = delete;
// ---- what the element reports (all delivered synchronously from the DOM
// event, which is sound because the browser owns the loop -- WB0.10) ------
// The value changed by the USER (typing, paste, cut, undo, a committed
// composition). Not raised for setText(), and not raised during an IME
// composition: the composition's text is not the field's value until it is
// committed, as on every desktop toolkit.
void setChangedHook(std::function<void()> hook);
// A key went down in the element. Return true to consume it (the browser's
// default is then prevented). `editing` says whether the element would act
// on the key itself -- a printable character, an arrow, Backspace, Ctrl+A
// and the clipboard and undo chords -- so a caller forwards only the rest
// (Tab, Escape, shortcut chords) to the window.
void setKeyHook(std::function<bool(const ICoreWebKeyInput& key, bool editing,
const std::string& domKey, const std::string& domCode,
unsigned int domFlags)> hook);
// Return was pressed and not consumed by the key hook.
void setActivateHook(std::function<void()> hook);
// The element lost DOM focus while shown -- the page lost the keyboard to
// something outside the canvas (another tab, the address bar).
void setBlurHook(std::function<void()> hook);
// ---- the value ------------------------------------------------------------
[[nodiscard]] std::string text() const;
void setText(const std::string& text); // silent: no changed hook
[[nodiscard]] int cursorPosition() const; // in UTF-16 units, as the DOM counts
void setCursorPosition(int position);
void select(int start, int end); // end -1 = to the end
[[nodiscard]] bool hasSelection() const;
// ---- how it behaves -----------------------------------------------------------
void setPlaceholder(const std::string& text);
void setReadOnly(bool readOnly);
[[nodiscard]] bool isReadOnly() const;
void setEcho(Echo echo);
void setSpellCheck(bool enabled);
void setAlignment(int horizontal); // 0 left, 1 centre, 2 right
void setAccessibleName(const std::string& name);
// ---- how it looks: the canvas paints the field around it --------------------
void setFontCss(const std::string& css);
void setInk(const std::string& textCss, const std::string& selectionCss,
const std::string& selectionTextCss, const std::string& placeholderCss);
// ---- where it is ------------------------------------------------------------
// Shows the element over `node`'s rect (x, y, width, height) in node-local
// coordinates, and keeps it there every frame until hide().
void show(ICoreWebNode* node, int x, int y, int width, int height);
void setRect(int x, int y, int width, int height);
void hide();
[[nodiscard]] bool isShown() const;
void focus();
// The index in the value nearest a node-local x inside the shown rect, for
// placing the caret where a press that SHOWED the element landed.
[[nodiscard]] int indexAt(double localX) const;
private:
class Impl; // the two-line residue; state lives here
std::unique_ptr<Impl> impl;
};
ICoreWebTreeModelAccess.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebTreeModelAccess.h
Web backend, WB2.4 -- the model's Impl, shared by the view, ported from UI/Backends/Gtk4/Widgets/ICoreGtk4TreeModelAccess.h onto ICoreWebNode. The reasons for the behaviour are in that file's comments and are not repeated here; a behaviour change in one belongs in both.
ICoreTreeViewModel#
ICoreWebTreeModelAccess.h:16 · class · bases :State · 0 declaration(s)
class ICoreTreeViewModel : :State {
public:
bool alive = true;
};
};
ICoreTreeViewModel#
ICoreWebTreeModelAccess.h:21 · class · bases :Impl · 4 declaration(s)
class ICoreTreeViewModel : :Impl {
public:
explicit Impl(ICoreTreeViewModel& owner);
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
void detachOwner();
std::vector<std::shared_ptr<ICoreStandardItem::Impl>> rows;
std::vector<ICoreString> headers;
ICoreNativeWidget* parent = nullptr;
ICoreTreeViewModel* m_owner = nullptr;
};
};
ICoreWebWidgetAccess.h#
ICoreEssentials/UI/Backends/Web/Widgets/ICoreWebWidgetAccess.h
The free functions the widget, layout and window seats reach a native widget through -- the web backend's copy of the free-function half of UI/Backends/Gtk4/Widgets/ICoreGtk4Widget.h, over ICoreWebNode* where that header takes GtkWidget*.
⚠ SAME NAMES, SAME CONTRACTS, ON PURPOSE. The widget and layout seats of this backend are the GTK4 seats' logic, and keeping the call sites spelled alike is what keeps the two readable side by side. The reasoning for each function is on its GTK4 declaration; each one here is a forward to ICoreWebNode.
⚠ NOTHING ABOVE THE BACKEND ZONE MAY INCLUDE THIS.
Declares no class of its own — see the file.