Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
web_event_translate.hpp
Go to the documentation of this file.
1#pragma once
2
11
16#include <pulp/view/view.hpp>
18
19#include <algorithm>
20#include <cmath>
21#include <cstdint>
22#include <functional>
23#include <memory>
24#include <string>
25#include <unordered_map>
26
27namespace pulp::view::web {
28
29// ── Coordinate mapping ──────────────────────────────────────────────────────
30
45 float css_width = 0;
46 float css_height = 0;
47 float design_width = 0;
48 float design_height = 0;
49 bool top_align = false;
50
51 bool has_design_viewport() const {
52 return design_width > 0.0f && design_height > 0.0f &&
53 css_width > 0.0f && css_height > 0.0f;
54 }
55
58 bool transform(float& sx, float& sy, float& tx, float& ty) const {
59 if (!has_design_viewport()) return false;
62 top_align);
63 }
64};
65
67inline Point css_to_root(const ViewportMapping& mapping, Point css) {
68 float sx = 1, sy = 1, tx = 0, ty = 0;
69 if (!mapping.transform(sx, sy, tx, ty) || sx <= 0.0f || sy <= 0.0f)
70 return css;
71 return {(css.x - tx) / sx, (css.y - ty) / sy};
72}
73
75inline Point root_to_css(const ViewportMapping& mapping, Point root) {
76 float sx = 1, sy = 1, tx = 0, ty = 0;
77 if (!mapping.transform(sx, sy, tx, ty) || sx <= 0.0f || sy <= 0.0f)
78 return root;
79 return {root.x * sx + tx, root.y * sy + ty};
80}
81
82// ── Backing store ───────────────────────────────────────────────────────────
83
86 uint32_t width = 0;
87 uint32_t height = 0;
88 float scale_factor = 1.0f;
89};
90
95inline BackingStore compute_backing_store(float css_width, float css_height,
96 float device_pixel_ratio) {
97 const float dpr = device_pixel_ratio > 0.0f ? device_pixel_ratio : 1.0f;
98 BackingStore store;
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));
103 store.scale_factor = dpr;
104 return store;
105}
106
107// ── Raw browser event shapes ────────────────────────────────────────────────
108
110enum class BrowserPointerPhase : uint8_t { down, move, up, cancel };
111
113enum class BrowserPointerType : uint8_t { mouse, touch, pen };
114
116enum class BrowserDeltaMode : uint8_t { pixel = 0, line = 1, page = 2 };
117
119 bool ctrl = false;
120 bool shift = false;
121 bool alt = false;
122 bool meta = false;
123};
124
138
147
149 std::string key;
150 bool is_down = true;
151 bool is_repeat = false;
153};
154
155// ── Translation ─────────────────────────────────────────────────────────────
156
159inline constexpr float kWheelLinePixels = 16.0f;
160inline constexpr float kWheelPageFallbackPixels = 400.0f;
161
166inline uint16_t translate_modifiers(const BrowserModifiers& mods) {
167 uint16_t out = kModNone;
168 if (mods.shift) out |= kModShift;
169 if (mods.ctrl) out |= kModCtrl;
170 if (mods.alt) out |= kModAlt;
171 if (mods.meta) out |= static_cast<uint16_t>(kModMeta | kModCmd);
172 return out;
173}
174
175inline MouseButton translate_button(int w3c_button) {
176 switch (w3c_button) {
177 case 1: return MouseButton::middle;
178 case 2: return MouseButton::right;
179 case 0: return MouseButton::left;
180 default: return MouseButton::left;
181 }
182}
183
191
199 const ViewportMapping& mapping) {
200 const Point root = css_to_root(mapping, {event.css_x, event.css_y});
201 const bool button_held = event.buttons != 0;
202
203 MouseEvent out;
204 out.position = root;
205 out.window_position = root;
206 out.button = translate_button(event.button);
208 out.pointer_id = event.is_primary ? 0 : event.pointer_id;
209 out.click_count = std::max(1, event.click_count);
211 out.pressure = event.pressure;
212
213 switch (event.phase) {
215 out.is_down = true;
217 break;
219 out.is_down = button_held;
220 out.phase = button_held ? MousePhase::drag : MousePhase::hover;
221 break;
223 out.is_down = false;
225 break;
227 out.is_down = false;
229 out.is_cancelled = true;
230 break;
231 }
232 return out;
233}
234
242 const ViewportMapping& mapping) {
243 float unit = 1.0f;
244 if (event.delta_mode == BrowserDeltaMode::line) {
245 unit = kWheelLinePixels;
246 } else if (event.delta_mode == BrowserDeltaMode::page) {
247 unit = mapping.css_height > 0.0f ? mapping.css_height
249 }
250
251 const Point root = css_to_root(mapping, {event.css_x, event.css_y});
252
253 MouseEvent out;
254 out.position = root;
255 out.window_position = root;
256 out.modifiers = translate_modifiers(event.modifiers);
257 out.is_wheel = true;
258 out.scroll_delta_x = event.delta_x * unit;
259 out.scroll_delta_y = event.delta_y * unit;
260 return out;
261}
262
266inline KeyCode translate_key_code(const std::string& key) {
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);
274 return KeyCode::unknown;
275 }
276 if (key == "ArrowLeft") return KeyCode::left;
277 if (key == "ArrowRight") return KeyCode::right;
278 if (key == "ArrowUp") return KeyCode::up;
279 if (key == "ArrowDown") return KeyCode::down;
280 if (key == "Home") return KeyCode::home;
281 if (key == "End") return KeyCode::end_;
282 if (key == "PageUp") return KeyCode::page_up;
283 if (key == "PageDown") return KeyCode::page_down;
284 if (key == "Backspace") return KeyCode::backspace;
285 if (key == "Delete") return KeyCode::delete_;
286 if (key == "Tab") return KeyCode::tab;
287 if (key == "Enter") return KeyCode::enter;
288 if (key == "Escape") return KeyCode::escape;
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)
294 return static_cast<KeyCode>(static_cast<int>(KeyCode::f1) + n - 1);
295 }
296 }
297 return KeyCode::unknown;
298}
299
301 KeyEvent out;
302 out.key = translate_key_code(event.key);
304 out.is_down = event.is_down;
305 out.is_repeat = event.is_repeat;
306 return out;
307}
308
317inline std::string text_for_key(const BrowserKeyEvent& event) {
318 if (!event.is_down) return {};
319 if (event.modifiers.ctrl || event.modifiers.meta) return {};
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{};
324 }
325 if (static_cast<unsigned char>(event.key[0]) & 0x80) return event.key;
326 return {};
327}
328
329// ── View-tree routing ───────────────────────────────────────────────────────
330
337public:
338 explicit WebInputRouter(View& root) : root_(root) {}
339
340 void set_mapping(const ViewportMapping& mapping) { mapping_ = mapping; }
341 const ViewportMapping& mapping() const { return mapping_; }
342
345 void set_dirty_callback(std::function<void()> cb) {
346 on_dirty_ = std::move(cb);
347 }
348
351 void invalidate() {
352 drag_targets_.clear();
353 hover_target_ = nullptr;
354 focus_target_ = nullptr;
355 }
356
357 View* focused_view() const { return focus_target_; }
358 View* drag_target() const {
359 if (drag_targets_.empty()) return nullptr;
360 const auto& capture = drag_targets_.begin()->second;
361 return capture.lifetime.expired() ? nullptr : capture.target;
362 }
363
365 const MouseEvent me = translate_pointer(event, mapping_);
366 switch (event.phase) {
368 return pointer_down(me, event.pointer_id);
370 return pointer_move(me, event.pointer_id);
372 return pointer_up(me, event.pointer_id, false);
374 return pointer_up(me, event.pointer_id, true);
375 }
376 return false;
377 }
378
379 bool handle_wheel(const BrowserWheelEvent& event) {
380 MouseEvent me = translate_wheel(event, mapping_);
381 View* target = root_.hit_test(me.position);
382 if (!target) {
383 // An empty patch of a scroll pane has no hit-testable child under
384 // it; route to the scroll container the pointer is over so the
385 // wheel works anywhere in the pane without clicking first.
386 target = find_wheel_scroll_view_at(root_, me.position);
387 if (!target) return false;
388 target->on_mouse_event(me);
389 target->layout_children();
390 mark_dirty();
391 return true;
392 }
393 target->on_mouse_event(me);
394 target->on_wheel(me.scroll_delta_y);
395 mark_dirty();
396 return true;
397 }
398
399 bool handle_key(const BrowserKeyEvent& event) {
400 const KeyEvent ke = translate_key(event);
401 // Escape runs the shared dismissal policy before focused-view
402 // delivery, matching every other host: a modal, an open ComboBox
403 // dropdown, then the generalized overlay slot. Without it a popover
404 // whose trigger never took focus could only be closed with the mouse.
405 if (ke.is_down && ke.key == KeyCode::escape &&
408 mark_dirty();
409 return true;
410 }
411 View* target = focus_target_ ? focus_target_ : &root_;
412 bool handled = target->on_key_event(ke);
413
414 const std::string text = text_for_key(event);
415 if (!text.empty() && focus_target_) {
417 te.text = text;
418 focus_target_->on_text_input(te);
419 handled = true;
420 }
421 if (handled) mark_dirty();
422 return handled;
423 }
424
435 bool handle_text(const std::string& text) {
436 if (text.empty() || !focus_target_) return false;
438 te.text = text;
439 focus_target_->on_text_input(te);
440 mark_dirty();
441 return true;
442 }
443
444private:
445 static bool in_tree(View* needle, View* root) {
446 if (!needle || !root) return false;
447 if (needle == root) return true;
448 for (size_t i = 0; i < root->child_count(); ++i)
449 if (in_tree(needle, root->child_at(i))) return true;
450 return false;
451 }
452
453 void clear_cached_target(
454 View* target,
455 const std::weak_ptr<const std::uint64_t>& lifetime) {
456 if (focus_target_ == target) {
457 focus_target_ = nullptr;
458 if (!lifetime.expired()) {
459 target->on_focus_changed(false);
460 if (!lifetime.expired()) target->release_input_focus();
461 }
462 }
463 if (hover_target_ == target) hover_target_ = nullptr;
464 }
465
466 void mark_dirty() {
467 if (on_dirty_) on_dirty_();
468 }
469
470 void set_focus(View* target) {
471 if (focus_target_ == target) return;
472 if (focus_target_) {
473 focus_target_->on_focus_changed(false);
474 focus_target_->release_input_focus();
475 }
476 focus_target_ = target;
477 if (focus_target_) {
478 focus_target_->on_focus_changed(true);
479 focus_target_->claim_input_focus();
480 }
481 }
482
483 bool pointer_down(const MouseEvent& me, int raw_pointer_id) {
484 // The generalized overlay slot is consulted through the one shared
485 // policy, exactly as the macOS and Windows hosts do. This host used to
486 // hand-roll a reduced version of it against the process-global
487 // `View::active_overlay_` shim mirror, which cost it three behaviours
488 // the other hosts have: a press INSIDE the overlay was not routed into
489 // the overlay's subtree (so an absolutely-positioned popover child lost
490 // the click to whatever sibling occupied that pixel), an overlay that
491 // opted to consume the dismissing press did not get to (so one click
492 // both closed the popover and mutated the underlay), and the slot was
493 // read process-wide rather than from this root.
494 const auto overlay_press =
495 route_press_to_active_overlay(root_, me.window_position);
496 if (overlay_press.consume_press) {
497 mark_dirty();
498 return true;
499 }
500
501 View* target =
502 overlay_press.routing == OverlayPressRouting::routed
503 ? overlay_press.target
504 : root_.hit_test(me.window_position);
505
506 // The overlay-aware context-menu overload, so a right-click inside a
507 // popover reaches the popover rather than the sibling beneath it.
508 if (me.button == MouseButton::right &&
509 dispatch_context_menu(root_, target, me.window_position)) {
510 mark_dirty();
511 return true;
512 }
514 if (!target) {
515 set_focus(nullptr);
516 mark_dirty();
517 return false;
518 }
519
520 set_focus(target->focusable() ? target : nullptr);
521
522 const auto lifetime = target->import_binding_lifetime_token();
523 const auto target_is_live = [&] {
524 return !lifetime.expired() && in_tree(target, &root_);
525 };
526 MouseEvent local_event = me;
527 local_event.position = point_to_local(me.window_position, target, &root_);
528 dispatch_dom_pointer_event(root_, target, local_event, false);
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};
532 else
533 clear_cached_target(target, lifetime);
534 mark_dirty();
535 return true;
536 }
537
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);
546 return false;
547 }
548 const auto captured_is_live = [&] {
549 return !lifetime.expired() && in_tree(captured, &root_);
550 };
551 MouseEvent local_event = me;
552 local_event.position =
553 point_to_local(me.window_position, captured, &root_);
554 local_event.is_down = true;
555 local_event.phase = MousePhase::drag;
556
557 dispatch_dom_pointer_event(root_, captured, local_event, true);
558 if (captured_is_live())
559 captured->on_mouse_drag(local_event.position);
560 if (captured_is_live()) {
561 if (local_event.pointer_type == PointerType::mouse) {
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);
566 }
567 }
568 if (!captured_is_live()) {
569 drag_targets_.erase(raw_pointer_id);
570 // Comparing an invalidated pointer is safe; invoking focus or
571 // hover callbacks on it is not. The lifetime token lets a
572 // detached-but-retained view release its focus ownership while
573 // avoiding a dereference if the callback destroyed it.
574 clear_cached_target(captured, lifetime);
575 }
576 mark_dirty();
577 return true;
578 }
579
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);
585 mark_dirty();
586 }
587 if (!target) return false;
588
589 MouseEvent local_event = me;
590 local_event.position = point_to_local(me.window_position, target, &root_);
591 dispatch_dom_pointer_event(root_, target, local_event, true);
592 target->on_hover_move(local_event.position);
593 mark_dirty();
594 return true;
595 }
596
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);
605 return false;
606 }
607 drag_targets_.erase(raw_pointer_id);
608
609 MouseEvent local_event = me;
610 local_event.position = point_to_local(me.window_position, target, &root_);
611 dispatch_dom_pointer_event(root_, target, local_event, false);
612 if (!lifetime.expired() && in_tree(target, &root_)) {
613 if (cancelled)
614 target->on_mouse_cancel(local_event.position);
615 else
616 target->on_mouse_up(local_event.position);
617 } else {
618 clear_cached_target(target, lifetime);
619 }
620 mark_dirty();
621 return true;
622 }
623
624 View& root_;
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;
630 };
631 std::unordered_map<int, PointerCapture> drag_targets_;
632 View* hover_target_ = nullptr;
633 View* focus_target_ = nullptr;
634};
635
636// ── Host installation (Emscripten only) ─────────────────────────────────────
637
642void install_browser_window_host(std::string canvas_selector = "#canvas");
643
646void install_web_input_listeners(const std::string& canvas_selector,
647 WebInputRouter& router);
648void remove_web_input_listeners(const std::string& canvas_selector);
649
652void notify_browser_host_resized(float css_width, float css_height);
653
663
666bool canvas_css_size(const std::string& canvas_selector, float& css_width,
667 float& css_height);
668
671void set_canvas_size(const std::string& canvas_selector,
672 const BackingStore& backing, float css_width,
673 float css_height);
674
676void set_canvas_visible(const std::string& canvas_selector, bool visible);
677
678} // namespace pulp::view::web
static void notify_global_click(View *target)
Called by the root view on any mouse click — closes popup if click is outside.
Definition view.hpp:73
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
Routes translated browser events into a live View tree.
Definition web_event_translate.hpp:336
void set_mapping(const ViewportMapping &mapping)
Definition web_event_translate.hpp:340
const ViewportMapping & mapping() const
Definition web_event_translate.hpp:341
void set_dirty_callback(std::function< void()> cb)
Called after any handler that changed view state, so the host can mark the surface dirty.
Definition web_event_translate.hpp:345
bool handle_wheel(const BrowserWheelEvent &event)
Definition web_event_translate.hpp:379
bool handle_key(const BrowserKeyEvent &event)
Definition web_event_translate.hpp:399
bool handle_pointer(const BrowserPointerEvent &event)
Definition web_event_translate.hpp:364
bool handle_text(const std::string &text)
Composed text from a DOM input / IME commit.
Definition web_event_translate.hpp:435
View * drag_target() const
Definition web_event_translate.hpp:358
WebInputRouter(View &root)
Definition web_event_translate.hpp:338
View * focused_view() const
Definition web_event_translate.hpp:357
void invalidate()
Forget cached drag / hover / focus targets.
Definition web_event_translate.hpp:351
Input event types with modifier keys and pointer IDs.
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,...