25#include <unordered_map>
58 bool transform(
float& sx,
float& sy,
float& tx,
float& ty)
const {
68 float sx = 1, sy = 1, tx = 0, ty = 0;
69 if (!mapping.
transform(sx, sy, tx, ty) || sx <= 0.0f || sy <= 0.0f)
71 return {(css.
x - tx) / sx, (css.
y - ty) / sy};
76 float sx = 1, sy = 1, tx = 0, ty = 0;
77 if (!mapping.
transform(sx, sy, tx, ty) || sx <= 0.0f || sy <= 0.0f)
79 return {root.
x * sx + tx, root.
y * sy + ty};
99 store.
width =
static_cast<uint32_t
>(
100 std::lround(
static_cast<double>(std::max(0.0f, css_width)) * dpr));
101 store.
height =
static_cast<uint32_t
>(
102 std::lround(
static_cast<double>(std::max(0.0f, css_height)) * dpr));
176 switch (w3c_button) {
201 const bool button_held =
event.buttons != 0;
208 out.
pointer_id =
event.is_primary ? 0 :
event.pointer_id;
213 switch (event.
phase) {
255 out.window_position = root;
258 out.scroll_delta_x =
event.delta_x * unit;
259 out.scroll_delta_y =
event.delta_y * unit;
267 if (key.size() == 1) {
268 const unsigned char ch =
static_cast<unsigned char>(key[0]);
269 if (ch >=
'A' && ch <=
'Z')
270 return static_cast<KeyCode>(ch -
'A' +
'a');
271 if ((ch >=
'a' && ch <=
'z') || (ch >=
'0' && ch <=
'9') || ch ==
' ' ||
272 ch ==
';' || ch ==
'\'')
273 return static_cast<KeyCode>(ch);
289 if (key.size() >= 2 && key[0] ==
'F') {
290 const std::string digits = key.substr(1);
291 if (digits.find_first_not_of(
"0123456789") == std::string::npos) {
292 const int n = std::stoi(digits);
293 if (
n >= 1 &&
n <= 12)
320 if (event.
key.empty())
return {};
321 if (event.
key.size() == 1) {
322 const unsigned char ch =
static_cast<unsigned char>(
event.key[0]);
323 return (ch >= 0x20 && ch != 0x7f) ?
event.key : std::string{};
325 if (
static_cast<unsigned char>(event.
key[0]) & 0x80)
return event.key;
346 on_dirty_ = std::move(cb);
352 drag_targets_.clear();
353 hover_target_ =
nullptr;
354 focus_target_ =
nullptr;
359 if (drag_targets_.empty())
return nullptr;
360 const auto& capture = drag_targets_.begin()->second;
361 return capture.lifetime.expired() ? nullptr : capture.target;
366 switch (event.
phase) {
372 return pointer_up(me, event.
pointer_id,
false);
374 return pointer_up(me, event.
pointer_id,
true);
387 if (!target)
return false;
411 View* target = focus_target_ ? focus_target_ : &root_;
415 if (!
text.empty() && focus_target_) {
418 focus_target_->on_text_input(te);
421 if (handled) mark_dirty();
436 if (
text.empty() || !focus_target_)
return false;
439 focus_target_->on_text_input(te);
445 static bool in_tree(
View* needle,
View* root) {
446 if (!needle || !root)
return false;
447 if (needle == root)
return true;
449 if (in_tree(needle, root->
child_at(
i)))
return true;
453 void clear_cached_target(
455 const std::weak_ptr<const std::uint64_t>& lifetime) {
456 if (focus_target_ == target) {
457 focus_target_ =
nullptr;
458 if (!lifetime.expired()) {
463 if (hover_target_ == target) hover_target_ =
nullptr;
467 if (on_dirty_) on_dirty_();
470 void set_focus(View* target) {
471 if (focus_target_ == target)
return;
473 focus_target_->on_focus_changed(
false);
474 focus_target_->release_input_focus();
476 focus_target_ = target;
478 focus_target_->on_focus_changed(
true);
479 focus_target_->claim_input_focus();
483 bool pointer_down(
const MouseEvent& me,
int raw_pointer_id) {
494 const auto overlay_press =
496 if (overlay_press.consume_press) {
503 ? overlay_press.target
504 : root_.hit_test(me.window_position);
520 set_focus(target->focusable() ? target :
nullptr);
522 const auto lifetime = target->import_binding_lifetime_token();
523 const auto target_is_live = [&] {
524 return !lifetime.expired() && in_tree(target, &root_);
526 MouseEvent local_event = me;
527 local_event.position =
point_to_local(me.window_position, target, &root_);
529 if (target_is_live()) target->on_mouse_down(local_event.position);
530 if (target_is_live())
531 drag_targets_[raw_pointer_id] = {target, lifetime};
533 clear_cached_target(target, lifetime);
538 bool pointer_move(
const MouseEvent& me,
int raw_pointer_id) {
539 auto capture = drag_targets_.find(raw_pointer_id);
540 if (capture != drag_targets_.end()) {
541 const auto lifetime = capture->second.lifetime;
542 View* captured = capture->second.target;
543 if (lifetime.expired() || !in_tree(captured, &root_)) {
544 drag_targets_.erase(capture);
545 clear_cached_target(captured, lifetime);
548 const auto captured_is_live = [&] {
549 return !lifetime.expired() && in_tree(captured, &root_);
551 MouseEvent local_event = me;
552 local_event.position =
554 local_event.is_down =
true;
558 if (captured_is_live())
559 captured->on_mouse_drag(local_event.position);
560 if (captured_is_live()) {
562 if (captured->on_drag)
563 captured->on_drag(local_event.position);
564 }
else if (captured->on_pointer_move) {
565 captured->on_pointer_move(local_event);
568 if (!captured_is_live()) {
569 drag_targets_.erase(raw_pointer_id);
574 clear_cached_target(captured, lifetime);
580 View* target = root_.hit_test(me.window_position);
581 if (target != hover_target_) {
582 if (hover_target_) hover_target_->set_hovered(
false);
583 hover_target_ = target;
584 if (hover_target_) hover_target_->set_hovered(
true);
587 if (!target)
return false;
589 MouseEvent local_event = me;
590 local_event.position =
point_to_local(me.window_position, target, &root_);
592 target->on_hover_move(local_event.position);
597 bool pointer_up(
const MouseEvent& me,
int raw_pointer_id,
bool cancelled) {
598 auto capture = drag_targets_.find(raw_pointer_id);
599 if (capture == drag_targets_.end())
return false;
600 const auto lifetime = capture->second.lifetime;
601 View* target = capture->second.target;
602 if (lifetime.expired() || !in_tree(target, &root_)) {
603 drag_targets_.erase(capture);
604 clear_cached_target(target, lifetime);
607 drag_targets_.erase(raw_pointer_id);
609 MouseEvent local_event = me;
610 local_event.position =
point_to_local(me.window_position, target, &root_);
612 if (!lifetime.expired() && in_tree(target, &root_)) {
614 target->on_mouse_cancel(local_event.position);
616 target->on_mouse_up(local_event.position);
618 clear_cached_target(target, lifetime);
625 ViewportMapping mapping_;
626 std::function<void()> on_dirty_;
627 struct PointerCapture {
628 View* target =
nullptr;
629 std::weak_ptr<const std::uint64_t> lifetime;
631 std::unordered_map<int, PointerCapture> drag_targets_;
632 View* hover_target_ =
nullptr;
633 View* focus_target_ =
nullptr;
static void notify_global_click(View *target)
Called by the root view on any mouse click — closes popup if click is outside.
View * child_at(size_t index)
Definition view.hpp:161
void release_input_focus()
Guarded release — clears the root slot AND the shim mirror only when this currently holds them.
virtual void on_wheel(float delta_y)
Adjust the widget's value by a scroll-wheel delta (delta_y positive = scrolled down).
Definition view.hpp:457
size_t child_count() const
Definition view.hpp:160
virtual void on_focus_changed(bool gained)
Called when this view gains or loses focus.
Definition view.hpp:480
virtual void layout_children()
virtual void on_mouse_event(const MouseEvent &event)
Mouse down with full event context.
Definition view.hpp:438
virtual View * hit_test(Point local_point)
virtual bool on_key_event(const KeyEvent &event)
Key event with modifiers and up/down state.
Definition view.hpp:475
static bool compute_design_viewport_transform(float window_w, float window_h, float design_w, float design_h, float &sx, float &sy, float &tx, float &ty, bool top_align=false)
Pure math behind set_design_viewport — used both by the platform host's paint_scene and by tests.
Definition window_host.hpp:501
Definition web_event_translate.hpp:27
BrowserDeltaMode
W3C WheelEvent.deltaMode.
Definition web_event_translate.hpp:116
@ line
Definition web_event_translate.hpp:116
@ page
Definition web_event_translate.hpp:116
@ pixel
Definition web_event_translate.hpp:116
constexpr float kWheelLinePixels
A wheel line is one text line; a wheel page falls back to this when the mapping carries no CSS height...
Definition web_event_translate.hpp:159
constexpr float kWheelPageFallbackPixels
Definition web_event_translate.hpp:160
uint16_t translate_modifiers(const BrowserModifiers &mods)
metaKey is Command on a Mac browser and the Super/Windows key elsewhere, so it sets both kModMeta and...
Definition web_event_translate.hpp:166
MouseEvent translate_wheel(const BrowserWheelEvent &event, const ViewportMapping &mapping)
Browser wheel event → Pulp wheel MouseEvent in ROOT coordinates.
Definition web_event_translate.hpp:241
Point root_to_css(const ViewportMapping &mapping, Point root)
Root-view point → CSS-pixel point. The exact inverse of css_to_root().
Definition web_event_translate.hpp:75
void install_browser_window_host(std::string canvas_selector="#canvas")
Register the Emscripten BrowserWindowHost factory so WindowHost::create() returns a canvas-backed hos...
KeyCode translate_key_code(const std::string &key)
KeyboardEvent.key → KeyCode.
Definition web_event_translate.hpp:266
PointerType translate_pointer_type(BrowserPointerType type)
Definition web_event_translate.hpp:184
MouseButton translate_button(int w3c_button)
Definition web_event_translate.hpp:175
BrowserPointerPhase
W3C PointerEvent phase.
Definition web_event_translate.hpp:110
@ cancel
Definition web_event_translate.hpp:110
@ move
Definition web_event_translate.hpp:110
@ up
Definition web_event_translate.hpp:110
@ down
Definition web_event_translate.hpp:110
BrowserPointerType
W3C PointerEvent.pointerType.
Definition web_event_translate.hpp:113
@ pen
Definition web_event_translate.hpp:113
@ mouse
Definition web_event_translate.hpp:113
@ touch
Definition web_event_translate.hpp:113
BackingStore compute_backing_store(float css_width, float css_height, float device_pixel_ratio)
The one place the HiDPI factor is applied.
Definition web_event_translate.hpp:95
MouseEvent translate_pointer(const BrowserPointerEvent &event, const ViewportMapping &mapping)
Browser pointer event → Pulp MouseEvent in ROOT coordinates.
Definition web_event_translate.hpp:198
KeyEvent translate_key(const BrowserKeyEvent &event)
Definition web_event_translate.hpp:300
void remove_web_input_listeners(const std::string &canvas_selector)
void set_canvas_visible(const std::string &canvas_selector, bool visible)
Show/hide the canvas element (style.display). Emscripten only.
void notify_browser_host_resized(float css_width, float css_height)
The canvas element's CSS size changed.
void install_web_input_listeners(const std::string &canvas_selector, WebInputRouter &router)
Attach/detach the DOM listeners (pointer, wheel, key, resize) that feed router.
float device_pixel_ratio()
Current devicePixelRatio, and the canvas element's CSS size. Emscripten only.
bool browser_host_gpu_available()
Is the live browser host's GPU surface renderable RIGHT NOW?
void set_canvas_size(const std::string &canvas_selector, const BackingStore &backing, float css_width, float css_height)
Size the canvas element: backing store in device pixels, CSS box in CSS pixels.
bool canvas_css_size(const std::string &canvas_selector, float &css_width, float &css_height)
std::string text_for_key(const BrowserKeyEvent &event)
The text a key-down should also deliver as a TextInputEvent, or "" when the key produces no character...
Definition web_event_translate.hpp:317
Point css_to_root(const ViewportMapping &mapping, Point css)
CSS-pixel point → root-view point. Identity without a design viewport.
Definition web_event_translate.hpp:67
@ kModCmd
Command (macOS) — alias for platform primary modifier.
Definition input_events.hpp:21
@ kModMeta
Windows key / Command key.
Definition input_events.hpp:20
@ kModNone
Definition input_events.hpp:16
@ kModShift
Definition input_events.hpp:17
@ kModAlt
Alt / Option.
Definition input_events.hpp:19
@ kModCtrl
Control key (Ctrl on Windows/Linux).
Definition input_events.hpp:18
@ text
Plain text (default color).
Definition code_editor_tokenizer.hpp:37
@ type
Built-in / common type name (e.g. int, Number).
Definition code_editor_tokenizer.hpp:39
void dispatch_dom_pointer_event(View &root, View *target, const MouseEvent &event, bool moving, bool bubble=true)
Enter rich + JS pointer delivery from a platform host.
@ routed
The press landed inside the overlay and resolved to a view in its subtree.
Definition overlay_dismissal.hpp:67
@ none
Nothing was open under root.
Definition overlay_dismissal.hpp:257
bool dispatch_context_menu(View &root, Point root_pos)
Route a right-click at root_pos to the view under it.
MouseButton
Mouse button identifiers.
Definition input_events.hpp:67
@ middle
Definition input_events.hpp:71
@ right
Definition input_events.hpp:70
@ left
Definition input_events.hpp:69
PointerType
Pointer device type (W3C PointerEvent.pointerType).
Definition input_events.hpp:75
@ pen
Stylus / Apple Pencil.
Definition input_events.hpp:78
@ mouse
Mouse cursor (default).
Definition input_events.hpp:76
@ touch
Direct touch (finger).
Definition input_events.hpp:77
OverlayEscapeResult route_escape_to_active_overlay(View &root, std::uint16_t modifiers=0, bool is_repeat=false)
Dismiss the topmost thing Escape should close under root.
@ visible
Content renders beyond bounds (default for views).
Definition geometry.hpp:384
KeyCode
Definition input_events.hpp:35
@ delete_
Definition input_events.hpp:57
@ home
Definition input_events.hpp:54
@ up
Definition input_events.hpp:53
@ backspace
Definition input_events.hpp:57
@ down
Definition input_events.hpp:53
@ n
Definition input_events.hpp:40
@ right
Definition input_events.hpp:53
@ left
Definition input_events.hpp:53
@ i
Definition input_events.hpp:40
@ end_
Definition input_events.hpp:54
@ unknown
Definition input_events.hpp:36
@ f1
Definition input_events.hpp:61
@ page_down
Definition input_events.hpp:54
@ escape
Definition input_events.hpp:57
@ enter
Definition input_events.hpp:57
@ tab
Definition input_events.hpp:57
@ page_up
Definition input_events.hpp:54
View * find_wheel_scroll_view_at(View &root, Point root_point)
Find the deepest view that participates in native wheel scrolling.
@ cancelled
Definition gesture.hpp:19
Point point_to_local(Point root_pos, View *target, View *root)
Convert root_pos (root-local, i.e.
@ release
Button-up that ends a gesture.
Definition input_events.hpp:98
@ press
Initial button-down that begins a gesture.
Definition input_events.hpp:96
@ drag
Pointer moved with the button held (a drag tick).
Definition input_events.hpp:97
@ hover
Pointer moved with no button held.
Definition input_events.hpp:99
OverlayPressTarget route_press_to_active_overlay(View &root, Point root_pt)
Consult root's generalized overlay slot for a press at root_pt.
The one implementation of Pulp's overlay-dismissal policy.
Rich key event with key code, modifiers, and repeat state.
Definition input_events.hpp:193
uint16_t modifiers
Definition input_events.hpp:195
bool is_repeat
True if this is a key repeat.
Definition input_events.hpp:197
KeyCode key
Definition input_events.hpp:194
bool is_down
True for key-down, false for key-up.
Definition input_events.hpp:196
Rich mouse/pointer event with position, modifiers, button state, pointer ID, and stylus properties.
Definition input_events.hpp:104
bool is_down
True for mouse-down / touch-began events.
Definition input_events.hpp:111
Point window_position
Position in window coordinates.
Definition input_events.hpp:106
float scroll_delta_y
Vertical scroll delta (positive = down).
Definition input_events.hpp:116
int click_count
1=single, 2=double, 3=triple click
Definition input_events.hpp:110
bool is_cancelled
True for touchesCancelled (→ pointercancel).
Definition input_events.hpp:113
Point position
Position in local view coordinates.
Definition input_events.hpp:105
uint16_t modifiers
Bitfield of Modifier flags.
Definition input_events.hpp:108
MouseButton button
Definition input_events.hpp:107
MousePhase phase
Explicit gesture phase (see MousePhase).
Definition input_events.hpp:112
float pressure
0.0–1.0 (0.5 = default for mouse)
Definition input_events.hpp:120
PointerType pointer_type
Definition input_events.hpp:119
int pointer_id
0 = primary, >0 = additional touches (multi-touch)
Definition input_events.hpp:109
Definition geometry.hpp:20
float x
Definition geometry.hpp:21
float y
Definition geometry.hpp:21
Text input from IME or keyboard composition (separate from KeyEvent).
Definition input_events.hpp:210
std::string text
UTF-8 encoded text.
Definition input_events.hpp:211
Canvas backing-store size and the scale factor handed to the Skia surface.
Definition web_event_translate.hpp:85
uint32_t height
canvas.height (device pixels)
Definition web_event_translate.hpp:87
uint32_t width
canvas.width (device pixels)
Definition web_event_translate.hpp:86
float scale_factor
SkiaSurface scale — the devicePixelRatio.
Definition web_event_translate.hpp:88
Definition web_event_translate.hpp:148
BrowserModifiers modifiers
Definition web_event_translate.hpp:152
std::string key
KeyboardEvent.key ("a", "Shift", "ArrowLeft", " ", …).
Definition web_event_translate.hpp:149
bool is_repeat
Definition web_event_translate.hpp:151
bool is_down
Definition web_event_translate.hpp:150
Definition web_event_translate.hpp:118
bool ctrl
Definition web_event_translate.hpp:119
bool shift
Definition web_event_translate.hpp:120
bool alt
Definition web_event_translate.hpp:121
bool meta
Definition web_event_translate.hpp:122
Definition web_event_translate.hpp:125
int click_count
MouseEvent.detail.
Definition web_event_translate.hpp:132
BrowserPointerPhase phase
Definition web_event_translate.hpp:133
bool is_primary
Definition web_event_translate.hpp:131
int pointer_id
Definition web_event_translate.hpp:130
int buttons
MouseEvent.buttons bitmask (0 = no button held).
Definition web_event_translate.hpp:129
float css_x
Definition web_event_translate.hpp:126
int button
MouseEvent.button — 0 left, 1 middle, 2 right.
Definition web_event_translate.hpp:128
BrowserModifiers modifiers
Definition web_event_translate.hpp:136
BrowserPointerType pointer_type
Definition web_event_translate.hpp:134
float pressure
Definition web_event_translate.hpp:135
float css_y
Definition web_event_translate.hpp:127
Definition web_event_translate.hpp:139
float delta_y
Definition web_event_translate.hpp:143
float delta_x
Definition web_event_translate.hpp:142
float css_y
Definition web_event_translate.hpp:141
BrowserModifiers modifiers
Definition web_event_translate.hpp:145
float css_x
Definition web_event_translate.hpp:140
BrowserDeltaMode delta_mode
Definition web_event_translate.hpp:144
Maps CSS pixels — the unit every browser pointer event reports — to root-view coordinates.
Definition web_event_translate.hpp:44
bool transform(float &sx, float &sy, float &tx, float &ty) const
Root → CSS transform, or false when no design viewport is active (identity; outputs untouched).
Definition web_event_translate.hpp:58
float design_width
Definition web_event_translate.hpp:47
bool has_design_viewport() const
Definition web_event_translate.hpp:51
float design_height
Definition web_event_translate.hpp:48
float css_height
Definition web_event_translate.hpp:46
float css_width
Definition web_event_translate.hpp:45
bool top_align
Definition web_event_translate.hpp:49
Additional UI components: ComboBox, Tooltip, ProgressBar, CallOutBox, TabPanel, ListBox,...