Generated reference › API — ICoreEssentials/UI/Events
kind: generated#api#icoreessentials-ui-events

API — ICoreEssentials/UI/Events

The public contract of 13 header(s) under ICoreEssentials/UI/Events — 13 class/struct definition(s), 122 declaration(s). Each section shows the header's banner and its public (and protected-virtual) surface exactly as the file writes it.

ICoreDragEvent.h#

ICoreEssentials/UI/Events/ICoreDragEvent.h

ICoreDragEvent#

ICoreDragEvent.h:8 · struct · 0 declaration(s)

What a widget hook learns about a drag entering, moving over, or dropping on it.

struct ICoreDragEvent {
public:
    // Position in the receiving widget's own coordinates.
    ICorePoint pos;

    ICoreMimePayload payload;
};
};

ICoreFocusEvent.h#

ICoreEssentials/UI/Events/ICoreFocusEvent.h

ICoreFocusEvent#

ICoreFocusEvent.h:15 · struct · 3 declaration(s)

What a focus hook learns.

struct ICoreFocusEvent {
public:
    ICoreFocusReason reason = ICoreFocusReason::Other;

    // Arriving by keyboard is the distinction almost every caller actually
    // wants; spelling it once here keeps the three-way switch out of the hooks.
    [[nodiscard]] bool isKeyboardDriven() const;

    // ------------------------------------------------------------------
    // ⚠ THE SAME TWO-AXIS PAIR ICoreKeyEvent AND ICoreMouseEvent CARRY, ADDED
    // FOR THE SAME REASON (P2.10b-4) AND USED BY focusGaining ALONE. A `bool
    // focusGaining` hook can say "do not run the toolkit base"; it cannot say
    // what to tell the event. ICorePortViewDescriptionLabel needs both: a label
    // that is not user-editable clears the focus it just got AND ignores, and
    // returning true alone would accept it.
    //
    // ⚠ It is meaningless on the focus-OUT pair, and deliberately not wired
    // there: focusLosing/focusLost return void because, as their note says,
    // declining is not a thing a focus loss can do.
    //
    // ⚠ ignore() is const and the flag is mutable because every hook takes a
    // `const ICoreFocusEvent&` -- the shape ICoreKeyEvent records, for the
    // reason ICoreMouseEvent's note records rejecting the alternative on cost.
    // ------------------------------------------------------------------
    void ignore() const;

    [[nodiscard]] bool isIgnored() const;

    // ⚠ PUBLIC, and set through ignore() rather than written directly. It is a
    // member rather than an Impl because this is an aggregate built fresh on
    // the stack for EVERY event -- a heap Impl here would be a malloc per
    // keystroke and per mouse move, and there is no implementation to hide
    // behind it: every other field of this struct is public already. Mutable
    // so ignore() can be const, because every hook takes a const reference.
    mutable bool m_ignored = false;
};
};

ICoreGestureEvent.h#

ICoreEssentials/UI/Events/ICoreGestureEvent.h

A recognised gesture: pan, pinch, long-press or rotate. TB1.1.

Recognition is the backend's: UIKit has UIPanGestureRecognizer and friends, Android its GestureDetector, a trackpad on macOS reports magnify natively. This type is only what a recognised gesture looks like once it crosses into ICore, and it reaches code through ICoreTouchSeat, never through a new virtual (PS0.1; the reason is in ICoreTouchEvent.h).

ONE type with a kind, rather than one type per gesture, so that a rotate or a two-finger tap is a new enumerator and not a new class and a new handler slot. The fields a kind does not move stay at their identity (scale 1, translation 0).

ICoreGestureEvent#

ICoreGestureEvent.h:38 · class · pImpl · 34 declaration(s)

class ICoreGestureEvent {
public:
    ICoreGestureEvent();
    ~ICoreGestureEvent();
    ICoreGestureEvent(const ICoreGestureEvent& other);
    ICoreGestureEvent& operator=(const ICoreGestureEvent& other);
    ICoreGestureEvent(ICoreGestureEvent&& other) noexcept;
    ICoreGestureEvent& operator=(ICoreGestureEvent&& other) noexcept;

    // Pan by default.
    [[nodiscard]] ICoreGestureKind kind() const;
    void setKind(ICoreGestureKind kind);

    // Began by default.
    [[nodiscard]] ICoreGestureState state() const;
    void setState(ICoreGestureState state);

    // What performed it. Touch by default; a trackpad pinch on a desktop is
    // Mouse, which lets a canvas treat it as a zoom without treating it as a
    // finger.
    [[nodiscard]] ICorePointerKind pointerKind() const;
    void setPointerKind(ICorePointerKind kind);

    // The centroid of the contacts: in the receiver's coordinates, on the
    // screen, and in the scene (zero for a widget with no scene). A pinch-zoom
    // scales about this point.
    [[nodiscard]] ICorePoint pos() const;
    void setPos(const ICorePoint& pos);
    [[nodiscard]] ICorePoint globalPos() const;
    void setGlobalPos(const ICorePoint& pos);
    [[nodiscard]] ICorePoint scenePos() const;
    void setScenePos(const ICorePoint& pos);

    // Pan and Pinch: how far the centroid has moved since Began, in the
    // receiver's coordinates -- for a pinch, that is the two-finger pan a
    // canvas applies alongside the zoom. (0, 0) for a long press.
    [[nodiscard]] ICorePoint translation() const;
    void setTranslation(const ICorePoint& translation);

    // Pan: the centroid's speed now, in the receiver's units per second, for a
    // momentum scroll at Ended. (0, 0) for the other kinds.
    [[nodiscard]] ICorePoint velocity() const;
    void setVelocity(const ICorePoint& velocity);

    // Pinch: the distance between the contacts now over the distance at Began.
    // 1.0 at Began and for the other kinds.
    [[nodiscard]] double scale() const;
    void setScale(double scale);

    // Pinch: the factor since the PREVIOUS event of this gesture, which is what
    // a view applies incrementally. The product of every scaleStep() since
    // Began is scale(). 1.0 at Began and for the other kinds.
    [[nodiscard]] double scaleStep() const;
    void setScaleStep(double step);

    // How many contacts perform it: 1 for a one-finger pan, 2 for a pinch.
    // 1 by default.
    // Rotate: the angle turned since Began, in radians, positive
    // COUNTER-CLOCKWISE as seen on the screen (so a view with y pointing down
    // negates it to turn its content the same way). 0 at Began and for the
    // other kinds.
    [[nodiscard]] double rotation() const;
    void setRotation(double radians);

    // Rotate: the angle since the PREVIOUS event of this gesture, which is
    // what a view applies incrementally. The sum of every rotationStep() since
    // Began is rotation(). 0 at Began and for the other kinds.
    [[nodiscard]] double rotationStep() const;
    void setRotationStep(double radians);

    [[nodiscard]] int pointCount() const;
    void setPointCount(int count);

    [[nodiscard]] ICoreKeyModifiers modifiers() const;
    void setModifiers(ICoreKeyModifiers modifiers);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

File-scope declarations#

// Append-only (PS0.1).
enum class ICoreGestureKind : int {
    Pan = 0,         // one or more contacts dragged; translation and velocity move
    Pinch = 1,       // two contacts moving apart or together; scale moves
    LongPress = 2,   // a contact held still past the platform's delay
    Rotate = 3,      // two contacts turning about their centroid; rotation moves
};

// Append-only (PS0.1).
enum class ICoreGestureState : int {
    Began = 0,       // recognised; the first event of this gesture
    Changed = 1,
    Ended = 2,       // finished normally: commit what it did
    Cancelled = 3,   // taken away: undo what Changed did
};

ICoreInputEnums.h#

ICoreEssentials/UI/Events/ICoreInputEnums.h

ICore names for the Qt:: constants that cross the wrapper boundary.

Clients spell ICoreAlignment::Center where they used to spell Qt::AlignCenter; the wrapper .cpps translate with a static_cast, which is only sound because every enumerator's underlying value below EQUALS its Qt counterpart. That equality is not trusted to this comment -- it is pinned by static_asserts in ICoreInputEnumsVerify.cpp, which includes the real Qt headers (it lives in the wrapper zone, so it may) and refuses to compile the moment Qt and this file disagree.

This header itself names no Qt token, so any layer may include it.

ICoreEasingSpec#

ICoreInputEnums.h:274 · struct · 2 declaration(s)

A curve plus the two knobs the toolkit exposes for the springy ones.

struct ICoreEasingSpec {
public:
    ICoreEasing curve = ICoreEasing::Linear;

    // Overshoot size for the Back and Elastic families. < 0 keeps the default.
    double amplitude = -1.0;

    // Oscillation frequency for the Elastic family. < 0 keeps the default.
    double period = -1.0;

    // Implicit on purpose: setEasing(ICoreEasing::OutCubic) must keep working
    // unchanged at the ~10 sites that write it, spec overload or not.
    ICoreEasingSpec(ICoreEasing c = ICoreEasing::Linear);

    ICoreEasingSpec(ICoreEasing c, double amplitudeValue, double periodValue);
};
};

File-scope declarations#

// ICore names for the Qt:: constants that cross the wrapper boundary.
// 
// Clients spell ICoreAlignment::Center where they used to spell
// Qt::AlignCenter; the wrapper .cpps translate with a static_cast, which is
// only sound because every enumerator's underlying value below EQUALS its Qt
// counterpart. That equality is not trusted to this comment -- it is pinned by
using ICoreReal = double;

enum class ICoreMouseButton : unsigned int {
    None = 0x00000000,
    Left = 0x00000001,
    Right = 0x00000002,
    Middle = 0x00000004,
};

// Bitmask of ICoreMouseButton values ("which buttons are held right now").
using ICoreMouseButtons = unsigned int;

enum class ICoreKeyModifier : unsigned int {
    None = 0x00000000,
    Shift = 0x02000000,
    Control = 0x04000000,
    Alt = 0x08000000,
    Meta = 0x10000000,
    Keypad = 0x20000000,
};

// Bitmask of ICoreKeyModifier values.
using ICoreKeyModifiers = unsigned int;

// The keys client code actually branches on. A key event also carries the raw
// key code, so an exotic key can still be matched by value; printable keys
// use their ASCII uppercase code (ICoreKey::A == 'A'), exactly as Qt does.
enum class ICoreKey : int {
    Space = 0x20,
    Plus = 0x2b, Minus = 0x2d, Equal = 0x3d, Underscore = 0x5f,
    Digit0 = 0x30, Digit1, Digit2, Digit3, Digit4, Digit5, Digit6, Digit7, Digit8, Digit9,
    A = 0x41, B, C, D, E, F, G, H, I, J, K, L, M,
    N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
    Escape = 0x01000000,
    Tab = 0x01000001,
    Backtab = 0x01000002,
    Backspace = 0x01000003,
    Return = 0x01000004,
    Enter = 0x01000005,
    Insert = 0x01000006,
    Delete = 0x01000007,
    Home = 0x01000010,
    End = 0x01000011,
    ArrowLeft = 0x01000012,
    ArrowUp = 0x01000013,
    ArrowRight = 0x01000014,
    ArrowDown = 0x01000015,
    PageUp = 0x01000016,
    PageDown = 0x01000017,
    Shift = 0x01000020,
    Control = 0x01000021,
    Meta = 0x01000022,
    Alt = 0x01000023,
    F1 = 0x01000030, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
};

enum class ICoreAlignment : unsigned int {
    Left = 0x0001,
    Right = 0x0002,
    HCenter = 0x0004,
    Justify = 0x0008,
    Top = 0x0020,
    Bottom = 0x0040,
    VCenter = 0x0080,
    Baseline = 0x0100,
    Center = HCenter | VCenter,
};

enum class ICoreOrientation : unsigned int {
    Horizontal = 0x1,
    Vertical = 0x2,
};

// How a widget wants a layout to treat its size hint, one axis at a time.
enum class ICoreSizeBehavior : int {
    // The values are the toolkit's grow/shrink/expand bit set, not a
    // sequence -- Maximum is 4 and Preferred is 5, which is why the
    // static_asserts next door exist rather than a comment claiming so.
    Fixed = 0,        // the hint is the size, full stop
    Minimum = 1,      // the hint is a floor; may grow
    Maximum = 4,      // the hint is a ceiling; may shrink
    Preferred = 5,    // the hint is ideal; may grow or shrink
    MinimumExpanding = 3,
    Expanding = 7,    // wants as much room as it can get
    Ignored = 13,     // the hint carries no information
};

// What kind of top-level a widget is, if any. Child (the default) means it
// is laid out inside its parent and is not a window at all.
enum class ICoreWindowNature {
    Child,
    FramelessWindow,   // a real window with no OS title bar
    Popup,             // dismissed by a click elsewhere; takes focus
    FloatingCard,      // a hover card: no frame, no shadow, never takes focus
    // Q5.1: a real window WITH the OS title bar -- the plain top-level. The
    // vocabulary had frameless but not decorated, so the one site that wanted
    // it (ICoreBlockCodeEditorWindow) had to reach past the wrapper for a bare
    // setWindowFlag. Appended rather than inserted: nothing pins these values,
    // but renumbering an enum other code stores is a gratuitous risk.
    DecoratedWindow,
};

// How many rows a view lets the user pick at once.
enum class ICoreSelectionMode : int {
    None = 0,
    Single = 1,
    Multi = 2,
    Extended = 3,     // click, shift-click, ctrl-click -- the usual list behaviour
    Contiguous = 4,
};

enum class ICoreScrollBarPolicy : int {
    AsNeeded = 0,
    AlwaysOff = 1,
    AlwaysOn = 2,
};

enum class ICoreTextElide : int {
    Left = 0,
    Right = 1,
    Middle = 2,
    None = 3,
};

// Whether, and how, a widget accepts keyboard focus. The values are a bit set
// (Strong == Tab|Click|0x8), not a sequence -- see the static_asserts.
enum class ICoreFocusPolicy : int {
    None = 0,
    Tab = 0x1,
    Click = 0x2,
    Strong = 0xb,
    Wheel = 0xf,
};

// A per-widget behaviour switch -- the toolkit's "widget attribute" set.
// 
// A shortlist of the nine this project actually sets, not a mirror of the
// toolkit's ~130, for the same reason ICoreEasing is a shortlist: a name is
// only worth having if it means something here. The values are the toolkit's
// own and are NOT a sequence -- they are positions in a bitfield the toolkit
enum class ICoreWidgetAttribute : int {
    OpaquePaintEvent = 4,            // the widget paints every pixel itself
    NoSystemBackground = 9,
    TransparentForMouseEvents = 51,  // clicks fall through to what is behind
    DeleteOnClose = 55,
    Hover = 74,                      // ask for enter/leave events (see ICoreWidget)
    // Marked "internal" in the toolkit's own header. Kept because the styling
    // module needs it for a stylesheet background to paint on a plain widget,
    // and there is no public spelling that does the same job.
    StyledBackground = 93,
    ShowWithoutActivating = 98,
    DontShowOnScreen = 103,          // lay out and render, but never map a window
    TranslucentBackground = 120,
};

// What kind of top-level a widget is, plus the frame hints that modify it.
// 
// Distinct from ICoreWindowNature, which is a NARROWED vocabulary -- four
// named shapes the editor actually builds. This is the wide form, for the
// constructor parameters that pass a caller's flags through verbatim. Prefer
// ICoreWindowNature in new code; this exists so those ctors stop naming Qt.
enum class ICoreWindowFlag : unsigned int {
    Widget = 0x00000000,
    Window = 0x00000001,
    Dialog = 0x00000002 | Window,
    Popup = 0x00000008 | Window,
    Tool = Popup | Dialog,
    FramelessWindowHint = 0x00000800,
    WindowStaysOnTopHint = 0x00040000,
    WindowDoesNotAcceptFocus = 0x00200000,
    CustomizeWindowHint = 0x02000000,
    NoDropShadowWindowHint = 0x40000000,
};

// Bitmask of ICoreWindowFlag values -- the same shape as ICoreMouseButtons.
using ICoreWindowFlags = unsigned int;

// How a view's columns take their width.
enum class ICoreColumnResize : int {
    Interactive = 0,
    Stretch = 1,
    Fixed = 2,
    ToContents = 3,
};

// How wide a keyboard shortcut listens. The values are the toolkit's context
// constants, which are not in this order -- WidgetWithChildren is 3 and
// Application is 2 -- so the static_asserts next door are what keeps them
// honest rather than the order they are written in here.
// 
// Window is the default at every call site: a key that means something in one
enum class ICoreShortcutScope : int {
    Window = 1,
    WidgetWithChildren = 3,   // the host widget and anything inside it, only
    Application = 2,
};

// The motion curves the editor actually uses. Deliberately a shortlist, not a
// mirror of the toolkit's ~40: a named vocabulary is only worth having if the
// names mean something here.
enum class ICoreEasing {
    Linear, InQuad, OutQuad, InOutQuad,
    InCubic, OutCubic, InOutCubic,
    InBack, OutBack, OutElastic, InOutSine,
};

enum class ICoreFontWeight : int {
    Normal = 400,
    Medium = 500,
    DemiBold = 600,
    Bold = 700,
};

enum class ICorePenStyle : int {
    None = 0,
    Solid = 1,
    Dash = 2,
    Dot = 3,
    DashDot = 4,
    DashDotDot = 5,
};

enum class ICorePenCap : int {
    Flat = 0x00,
    Square = 0x10,
    Round = 0x20,
};

// How two segments of a stroked line meet. Deliberately the three the toolkit
// offers as line joins; the SVG-compatible miter variant has no call site.
enum class ICorePenJoin : int {
    Miter = 0x00,
    Bevel = 0x40,
    Round = 0x80,
};

// Why a widget is being given focus. It matters: a field focused by the mouse
// does not select its contents, one focused by Tab does.
enum class ICoreFocusReason : int {
    Mouse = 0,
    Tab = 1,
    Backtab = 2,
    ActiveWindow = 3,
    Popup = 4,
    Shortcut = 5,
    MenuBar = 6,
    Other = 7,
};

enum class ICoreCursorShape : int {
    Arrow = 0,
    UpArrow = 1,
    Cross = 2,
    Wait = 3,
    IBeam = 4,
    SizeVertical = 5,
    SizeHorizontal = 6,
    SizeBackwardDiagonal = 7,
    SizeForwardDiagonal = 8,
    SizeAll = 9,
    Blank = 10,
    SplitVertical = 11,
    SplitHorizontal = 12,
    PointingHand = 13,
    Forbidden = 14,
    WhatsThis = 15,
    Busy = 16,
    OpenHand = 17,
    ClosedHand = 18,
    DragCopy = 19,
    DragMove = 20,
    DragLink = 21,
};

ICoreKeyEvent.h#

ICoreEssentials/UI/Events/ICoreKeyEvent.h

ICoreKeyEvent#

ICoreKeyEvent.h:9 · struct · 4 declaration(s)

What a widget hook learns about a key event.

struct ICoreKeyEvent {
public:
    int key = 0;

    ICoreKeyModifiers modifiers = 0;

    // The text this key would insert ("" for pure modifiers and navigation).
    ICoreString text;

    bool autoRepeat = false;

    [[nodiscard]] bool is(ICoreKey which) const;

    [[nodiscard]] bool hasModifier(ICoreKeyModifier which) const;

    // ------------------------------------------------------------------
    // ⚠ THE SAME TWO-AXIS PAIR ICoreMouseEvent CARRIES, AND ADDED FOR THE SAME
    // REASON (P2.10b-4). A `bool keyPressed` hook can say "do not run the
    // toolkit base"; it cannot say what to tell the parent item. Those are two
    // facts, and ICoreGraphicsBoxedText needs both: it swallows Return/Enter to
    // prevent a newline, and it does so with `event->ignore()` -- so the key
    // keeps propagating to the item above, which is how a dialog still sees
    // Enter. Returning true alone would ACCEPT it and silently swallow that.
    //
    // ⚠ ignore() is const and the flag is mutable because every hook takes a
    // `const ICoreKeyEvent&`. Widening the hooks instead is the edit
    // ICoreMouseEvent's note records being rejected on cost.
    // ------------------------------------------------------------------
    void ignore() const;

    [[nodiscard]] bool isIgnored() const;

    // ⚠ PUBLIC -- see ICoreFocusEvent.h for why an event aggregate carries this
    // as a member instead of behind an Impl. Set through ignore(); mutable so
    // ignore() can be const, because every hook takes a const reference.
    mutable bool m_ignored = false;
};
};

ICoreMouseEvent.h#

ICoreEssentials/UI/Events/ICoreMouseEvent.h

ICoreMouseEvent#

ICoreMouseEvent.h:33 · struct · 2 declaration(s)

What a widget hook learns about a pointer event.

struct ICoreMouseEvent {
public:
    // Position in the receiving widget's own coordinates.
    ICorePoint pos;

    // Position on the screen -- what QMouseEvent::globalPosition() carried.
    ICorePoint globalPos;

    // Position in the SCENE, for the graphics tier. Zero for widget events,
    // which have no scene.
    //
    // Carried rather than left to the receiver to map: an item handling a drag
    // needs the scene position on every move, mapping it back costs a call into
    // the item's transform chain, and the toolkit already computed it. (This was
    // omitted at first on the theory that item-local was always enough -- it is
    // used 55 times across the scene tier, so it was not.)
    ICorePoint scenePos;

    // The button that caused the event (None for pure moves).
    ICoreMouseButton button = ICoreMouseButton::None;

    // Every button held at the time of the event, or-ed together.
    ICoreMouseButtons buttons = 0;

    ICoreKeyModifiers modifiers = 0;

    // "Not mine -- let the scene carry it to whatever is under me." Pair it
    // with `return true` from the hook: true stops the toolkit base from
    // running, and this decides what the forwarder tells the toolkit event.
    //
    // A hook that returns true WITHOUT calling this accepts, exactly as
    // before. A hook that returns false runs the base and this flag is not
    // consulted at all -- the base decides accept/ignore itself, which is the
    // behaviour every unmigrated subclass still has.
    void ignore() const;

    [[nodiscard]] bool isIgnored() const;

    // Mutable so ignore() can be const -- see the note above the struct. The
    // forwarder reads this after the hook returns; it is never serialized,
    // compared or copied across events.
    //
    // ⚠ PUBLIC, not behind an Impl, and set through ignore() rather than
    // written directly. This aggregate is built fresh on the stack for every
    // pointer event, so a heap Impl would be a malloc per mouse MOVE -- and it
    // would hide nothing, since every other field here is public already.
    mutable bool m_ignored = false;
};
};

ICorePointerDetail.h#

ICoreEssentials/UI/Events/ICorePointerDetail.h

Which device produced a mouse event, and how hard a pen was pressing. TB1.2.

⚠ NOT A FIELD ON ICoreMouseEvent, AND THAT IS THE WHOLE DESIGN. The mouse event is a public aggregate built on the stack by every backend and read by ~60 hook overrides. A new field changes its sizeof with no mangled-name change, so a translation unit compiled against the old header -- a peer's half-built tree today, an SDK consumer's binary tomorrow (PS0.1) -- builds a shorter object than the new code reads, and it links. The padding after m_ignored looks free and is not: an old TU never writes it, so the new code would read garbage there.

So the detail travels BESIDE the event. A backend that knows it opens an ICorePointerDetailScope around the dispatch; a hook asks through the two

ICorePointerDetailScope#

ICorePointerDetail.h:63 · class · pImpl · 6 declaration(s)

A backend's half.

class ICorePointerDetailScope {
public:
    ICorePointerDetailScope(const ICoreMouseEvent& event, ICorePointerKind kind, double pressure);
    ~ICorePointerDetailScope();

    ICorePointerDetailScope(const ICorePointerDetailScope&) = delete;
    ICorePointerDetailScope& operator=(const ICorePointerDetailScope&) = delete;
    ICorePointerDetailScope(ICorePointerDetailScope&&) = delete;
    ICorePointerDetailScope& operator=(ICorePointerDetailScope&&) = delete;

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICorePointerKind.h#

ICoreEssentials/UI/Events/ICorePointerKind.h

File-scope declarations#

// What produced a pointer event: a mouse (or trackpad), a finger, or a pen.
// 
// TB1.1 / TB1.2. An enum-only header, so any layer may
// include it and it has nothing to move behind an Impl (header-surface
// exemption 3).
// 
enum class ICorePointerKind : int {
    Mouse = 0,   // a mouse, or a trackpad driving a cursor
    Touch = 1,   // a finger on a touch screen
    Pen = 2,     // a stylus: Apple Pencil, an S Pen, a Wacom pen
};

ICorePointerLock.h#

ICoreEssentials/UI/Events/ICorePointerLock.h

ICorePointerLock#

ICorePointerLock.h:24 · class · 5 declaration(s)

Pointer lock: the cursor is hidden and stops moving, and the mouse's RELATIVE motion is reported instead -- what a fly camera steers by.

class ICorePointerLock {
public:
    ICorePointerLock() = delete;

    [[nodiscard]] static bool isSupported();

    // Lock the pointer for `widget` (the view that asked: kept for the
    // platforms that lock to an element). False if unsupported, if `widget`
    // or `onMotion` is missing, or if the platform refuses.
    static bool lock(ICoreNativeWidget* widget, std::function<void(double dx, double dy)> onMotion);

    static void unlock();

    [[nodiscard]] static bool isLocked();
};
};

ICoreTouchEvent.h#

ICoreEssentials/UI/Events/ICoreTouchEvent.h

Raw touch input: every finger (or pen tip) currently on the screen, and what each one just did. TB1.1.

⚠ A NEW TYPE, AND NOT A NEW HOOK. The ABI rule PS0.1 forbids a new virtual on a shipped class: it changes the vtable of ICoreWidget and all 84 of its overriders with no mangled-name change, so a stale object links and then crashes. A touch event therefore reaches code through ICoreTouchSeat (ICoreTouchSeat.h), an installable handler, and a widget that installs none gets exactly what it got before this file existed: the backend's synthesized mouse events.

⚠ AND BEHIND AN Impl, UNLIKE ICoreMouseEvent. The mouse aggregate keeps its fields public because a heap Impl would cost a malloc per mouse MOVE and hide nothing. A touch event already holds a vector of points, so it allocates

ICoreTouchPoint#

ICoreTouchEvent.h:41 · class · pImpl · 20 declaration(s)

One contact: a finger or a pen tip.

class ICoreTouchPoint {
public:
    ICoreTouchPoint();
    ~ICoreTouchPoint();
    ICoreTouchPoint(const ICoreTouchPoint& other);
    ICoreTouchPoint& operator=(const ICoreTouchPoint& other);
    ICoreTouchPoint(ICoreTouchPoint&& other) noexcept;
    ICoreTouchPoint& operator=(ICoreTouchPoint&& other) noexcept;

    // Stable for the life of the contact, from Began to Ended or Cancelled, and
    // unique among the contacts down at the same time. A backend may reuse an
    // id once its contact has ended; code tracking fingers keys on it and
    // forgets it at Ended/Cancelled. 0 by default.
    [[nodiscard]] std::int64_t id() const;
    void setId(std::int64_t id);

    // Began by default, so a point built and filled in one place reads as a
    // new contact rather than as a stale one.
    [[nodiscard]] ICoreTouchPhase phase() const;
    void setPhase(ICoreTouchPhase phase);

    // Touch or Pen. Touch by default; Mouse is never set here by a backend,
    // because a mouse is not a touch.
    [[nodiscard]] ICorePointerKind kind() const;
    void setKind(ICorePointerKind kind);

    // In the receiving widget's own coordinates, on the screen, and in the
    // scene -- the same three positions ICoreMouseEvent carries, with the same
    // rule: scenePos is zero for a widget that has no scene.
    [[nodiscard]] ICorePoint pos() const;
    void setPos(const ICorePoint& pos);
    [[nodiscard]] ICorePoint globalPos() const;
    void setGlobalPos(const ICorePoint& pos);
    [[nodiscard]] ICorePoint scenePos() const;
    void setScenePos(const ICorePoint& pos);

    // 0.0 to 1.0. A device that cannot measure pressure reports 1.0 while the
    // contact is down, which is the convention every toolkit this tree has
    // shipped on uses, so code can multiply by it unconditionally.
    [[nodiscard]] double pressure() const;
    void setPressure(double pressure);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

ICoreTouchEvent#

ICoreTouchEvent.h:89 · class · pImpl · 14 declaration(s)

Every contact that is down, plus the ones that just lifted.

class ICoreTouchEvent {
public:
    ICoreTouchEvent();
    ~ICoreTouchEvent();
    ICoreTouchEvent(const ICoreTouchEvent& other);
    ICoreTouchEvent& operator=(const ICoreTouchEvent& other);
    ICoreTouchEvent(ICoreTouchEvent&& other) noexcept;
    ICoreTouchEvent& operator=(ICoreTouchEvent&& other) noexcept;

    // In the order the backend added them. A contact that lifted in this event
    // is still listed, with phase Ended, so a handler sees the lift; it is gone
    // from the next event.
    [[nodiscard]] const std::vector<ICoreTouchPoint>& points() const;
    void addPoint(const ICoreTouchPoint& point);

    // How many contacts are still down after this event: every point whose
    // phase is not Ended or Cancelled.
    [[nodiscard]] int activeCount() const;

    // The contact with this id, or nullptr. The pointer is into this event and
    // is invalidated by addPoint() or by the event's destruction.
    [[nodiscard]] const ICoreTouchPoint* findPoint(std::int64_t id) const;

    [[nodiscard]] ICoreKeyModifiers modifiers() const;
    void setModifiers(ICoreKeyModifiers modifiers);

    // When the toolkit says the event happened, in milliseconds on a clock that
    // only means something relative to other events from the same backend. For
    // velocities; 0 when the backend does not know.
    [[nodiscard]] double timestampMs() const;
    void setTimestampMs(double ms);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

File-scope declarations#

// Where one contact is in its life. Append-only (PS0.1).
enum class ICoreTouchPhase : int {
    Began = 0,        // the finger went down in this event
    Moved = 1,        // it moved since the last event
    Stationary = 2,   // it is down and did not move; another finger did
    Ended = 3,        // it lifted in this event
    Cancelled = 4,    // the system took it away (a system gesture, an alert)
};

ICoreTouchSeat.h#

ICoreEssentials/UI/Events/ICoreTouchSeat.h

Returns true when it handled the event. False hands it back to the backend, which then does what it did before any seat existed.

ICoreTouchSeat#

ICoreTouchSeat.h:47 · class · pImpl · 21 declaration(s)

Where touch and gesture events are delivered: an installable handler on a widget or a scene item.

class ICoreTouchSeat {
public:
    // A null target registers nothing, and deliver() never finds it.
    explicit ICoreTouchSeat(const ICoreNativeWidget* widget);
    explicit ICoreTouchSeat(const ICoreNativeItem* item);
    ~ICoreTouchSeat();

    ICoreTouchSeat(const ICoreTouchSeat&) = delete;
    ICoreTouchSeat& operator=(const ICoreTouchSeat&) = delete;
    ICoreTouchSeat(ICoreTouchSeat&&) = delete;
    ICoreTouchSeat& operator=(ICoreTouchSeat&&) = delete;

    // An empty function clears the handler; the seat stays registered.
    void setTouchHandler(ICoreTouchHandlerFn handler);
    void setGestureHandler(ICoreGestureHandlerFn handler);

    // ---- the backend's half ------------------------------------------------

    // Whether anything would take a touch / gesture on this target. A backend
    // asks before doing work it would otherwise skip, such as keeping raw
    // touches instead of converting them to mouse events.
    static bool wantsTouch(const ICoreNativeWidget* widget);
    static bool wantsTouch(const ICoreNativeItem* item);
    static bool wantsGestures(const ICoreNativeWidget* widget);
    static bool wantsGestures(const ICoreNativeItem* item);

    // Hands the event to the newest seat on `target` that has a handler of
    // that kind, and answers what it returned. False when there is none.
    static bool deliverTouch(const ICoreNativeWidget* widget, const ICoreTouchEvent& event);
    static bool deliverTouch(const ICoreNativeItem* item, const ICoreTouchEvent& event);
    static bool deliverGesture(const ICoreNativeWidget* widget, const ICoreGestureEvent& event);
    static bool deliverGesture(const ICoreNativeItem* item, const ICoreGestureEvent& event);

    // The same four, keyed by the TOOLKIT object instead of the wrapper: the
    // handle nativeWidgetHandle() / nativeItemHandle() returns. A backend's
    // event arrives on its own view or node, and walking from there to the
    // wrapper is exactly what these save it (the web window picks a node and
    // walks up its parents asking wantsTouchAt()).
    //
    // ⚠ THESE DO CALL INTO THE TARGETS: each registered wrapper is asked for its
    // handle. So a seat must not outlive what it seats -- the rule its handler
    // already has, and what holding the seat as a member guarantees. The
    // wrapper-keyed functions above still never touch the target.
    static bool wantsTouchAt(const void* nativeHandle);
    static bool wantsGesturesAt(const void* nativeHandle);
    static bool deliverTouchAt(const void* nativeHandle, const ICoreTouchEvent& event);
    static bool deliverGestureAt(const void* nativeHandle, const ICoreGestureEvent& event);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

File-scope declarations#

// Returns true when it handled the event. False hands it back to the backend,
// which then does what it did before any seat existed.
using ICoreTouchHandlerFn = std::function<bool(const ICoreTouchEvent&)>;

using ICoreGestureHandlerFn = std::function<bool(const ICoreGestureEvent&)>;

ICoreWheelDetail.h#

ICoreEssentials/UI/Events/ICoreWheelDetail.h

What kind of device produced a scroll event, its gesture phase, and its deltas in pixels -- the facts a 3D view needs to tell "zoom with the wheel" from "pan with two fingers", and that ICoreWheelEvent does not carry.

⚠ NOT FIELDS ON ICoreWheelEvent, FOR THE REASON ICorePointerDetail.h GIVES. The wheel event is a public aggregate built on the stack by every backend. A new field changes its sizeof with no mangled-name change, so a translation unit compiled against the old header builds a shorter object than new code reads, and it links. So the detail travels BESIDE the event: a backend that knows it opens an ICoreWheelDetailScope around the dispatch, and a hook asks through the functions below.

UNSET MEANS "NOT REPORTED". With no scope open -- every seat that has not opted in -- the source is Unknown, both phases are None, there is no pixel

ICoreWheelDetailScope#

ICoreWheelDetail.h:73 · class · pImpl · 11 declaration(s)

A backend's half.

class ICoreWheelDetailScope {
public:
    ICoreWheelDetailScope();
    ~ICoreWheelDetailScope();

    ICoreWheelDetailScope(const ICoreWheelDetailScope&) = delete;
    ICoreWheelDetailScope& operator=(const ICoreWheelDetailScope&) = delete;
    ICoreWheelDetailScope(ICoreWheelDetailScope&&) = delete;
    ICoreWheelDetailScope& operator=(ICoreWheelDetailScope&&) = delete;

    void setSource(ICoreWheelSource source);
    void setPhase(ICoreScrollPhase phase);
    void setMomentumPhase(ICoreScrollPhase phase);
    void setPixelDelta(double dx, double dy);
    void setInverted(bool inverted);

private:
    class Impl;                    // the two-line residue; state lives here
    std::unique_ptr<Impl> impl;
};

File-scope declarations#

// The device behind the scroll.
enum class ICoreWheelSource : int {
    Unknown = 0,    // the seat does not say
    Wheel = 1,      // a notched wheel: discrete steps, no gesture phases
    Trackpad = 2,   // a continuous surface: a trackpad, or a touch mouse's surface
};

// Where the event sits in a scroll GESTURE. A notched wheel has no gesture
// and reports None. A trackpad reports MayBegin (fingers down, not moving yet),
// Began, Changed..., then Ended or Cancelled. After the fingers lift, the
// momentum phase runs its own Began, Changed..., Ended while the phase itself
// is None.
enum class ICoreScrollPhase : int {
    None = 0,
    MayBegin = 1,
    Began = 2,
    Changed = 3,
    Ended = 4,
    Cancelled = 5,
};

ICoreWheelEvent.h#

ICoreEssentials/UI/Events/ICoreWheelEvent.h

ICoreWheelEvent#

ICoreWheelEvent.h:9 · struct · 0 declaration(s)

What a widget hook learns about a scroll event.

struct ICoreWheelEvent {
public:
    // Position in the receiving widget's own coordinates.
    ICorePoint pos;

    double deltaX = 0.0;
    double deltaY = 0.0;

    ICoreKeyModifiers modifiers = 0;
};
};