90 const bool valid_pair = high >= 0xD800 && high <= 0xDBFF &&
91 low >= 0xDC00 && low <= 0xDFFF;
92 if (!valid_pair)
return {};
93 cp = 0x10000u + ((
static_cast<std::uint32_t
>(high) - 0xD800u) << 10) +
94 (
static_cast<std::uint32_t
>(low) - 0xDC00u);
98 if (high >= 0xD800 && high <= 0xDFFF)
return {};
104 out +=
static_cast<char>(cp);
105 }
else if (cp < 0x800) {
106 out +=
static_cast<char>(0xC0u | (cp >> 6));
107 out +=
static_cast<char>(0x80u | (cp & 0x3Fu));
108 }
else if (cp < 0x10000) {
109 out +=
static_cast<char>(0xE0u | (cp >> 12));
110 out +=
static_cast<char>(0x80u | ((cp >> 6) & 0x3Fu));
111 out +=
static_cast<char>(0x80u | (cp & 0x3Fu));
113 out +=
static_cast<char>(0xF0u | (cp >> 18));
114 out +=
static_cast<char>(0x80u | ((cp >> 12) & 0x3Fu));
115 out +=
static_cast<char>(0x80u | ((cp >> 6) & 0x3Fu));
116 out +=
static_cast<char>(0x80u | (cp & 0x3Fu));
141 std::uint64_t generation = 0;
147 View& root = host_.input_root();
153 route_press_to_open_combo(root, pt, modifiers)) {
154 host_.input_request_repaint();
157 if (!session_.begin(button))
return;
158 generation = session_.generation();
159 const auto accepts_original = [
this, generation, button] {
160 return session_.accepts(generation, button);
168 if (!accepts_original())
return;
169 if (overlay_press.consume_press) {
174 drag_target_.set(overlay_press.target);
178 gesture_event.
button = button;
188 yield_to_gesture(gesture_event)) {
191 if (accepts_original()) host_.input_capture_pointer();
194 if (!accepts_original())
return;
202 drag_target_.set(root.
hit_test(pt));
203 View* drag_target = drag_target_.live_in(root);
206 if (!accepts_original())
return;
207 drag_target = drag_target_.live_in(root);
212 host_.input_take_keyboard_focus();
213 if (!accepts_original())
return;
214 drag_target = drag_target_.live_in(root);
220 if (accepts_original()) {
221 drag_target_.reset();
226 if (!accepts_original())
return;
227 host_.input_capture_pointer();
228 if (!accepts_original())
return;
231 const bool target_alive =
236 if (!accepts_original())
return;
237 if (!target_alive) drag_target_.reset();
240 if (!accepts_original())
return;
241 host_.input_request_repaint();
242 }
catch (
const std::exception& e) {
256 std::uint16_t modifiers) {
259 if (!tracking_leave_)
260 tracking_leave_ = host_.input_begin_mouse_leave_tracking();
261 View& root = host_.input_root();
264 if (!session_.active()) {
266 host_.input_request_repaint();
272 gesture_event.
button = session_.button();
276 if (!drag_target_.live_in(root)) drag_target_.reset();
277 const bool gesture_yielded = yield_to_gesture(gesture_event);
278 if (!gesture_yielded) {
279 View* target = drag_target_.live_in(root);
285 host_.input_request_repaint();
286 }
catch (
const std::exception& e) {
297 if (!session_.accepts(button))
return;
301 const auto terminal = session_.terminalize();
303 View& root = host_.input_root();
304 if (!drag_target_.live_in(root)) drag_target_.reset();
308 gesture_event.
button = button;
316 session_.generation() != terminal.generation)
318 View* target = drag_target_.live_in(root);
319 drag_target_.reset();
320 if (gesture_yielded) {
327 [](
const std::function<void()>& click_handler,
328 const std::string&, std::uint16_t) {
329 if (click_handler) click_handler();
335 session_.generation() == terminal.generation) {
336 host_.input_release_pointer_capture();
337 session_.finish_terminal(terminal);
339 host_.input_request_repaint();
340 }
catch (
const std::exception& e) {
359 tracking_leave_ =
false;
360 if (session_.active())
362 host_.input_root().simulate_hover({-1000000.0f, -1000000.0f});
363 host_.input_request_repaint();
367 std::uint16_t modifiers = 0) {
369 wheel_host.
request_repaint = [
this] { host_.input_request_repaint(); };
389 host_.input_request_repaint();
393 if (!focused)
return false;
397 event.modifiers = modifiers;
398 event.is_down = is_down;
399 event.is_repeat = is_repeat;
400 bool consumed =
false;
401 if (focused->accepts_text_input()) {
402 consumed = focused->on_key_event(event);
403 }
else if (focused->accepts_navigation_input()) {
404 constexpr std::uint16_t kHostChordModifiers =
406 const bool allowed = (modifiers & kHostChordModifiers) == 0 &&
411 if (!allowed)
return false;
412 consumed = focused->on_key_event(event);
415 host_.input_root(),
static_cast<int>(key), modifiers, is_down);
420 if (consumed) host_.input_request_repaint();
429 if (!focused || !focused->accepts_text_input())
return false;
433 if (unit < 0x20)
return true;
436 if (unit >= 0xD800 && unit <= 0xDBFF) {
438 pending_high_surrogate_ = unit;
441 if (unit >= 0xDC00 && unit <= 0xDFFF && pending_high_surrogate_ != 0) {
446 pending_high_surrogate_ = 0;
447 if (text.empty())
return true;
449 host_.input_request_repaint();
458 pending_high_surrogate_ = 0;
459 View& root = host_.input_root();
462 host_.input_request_repaint();
472 const auto terminal = session_.terminalize();
474 View& root = host_.input_root();
480 drag_target_.
reset();
482 if (!target && !terminal.cancel_gesture && !terminal.owns_terminal)
484 if (terminal.cancel_gesture) {
487 event.window_position = last_point_;
488 event.button = terminal.button;
489 event.is_down =
false;
491 event.is_cancelled =
true;
494 target = cancelled_target.
live_in(root);
499 }
catch (
const std::exception& e) {
505 if (terminal.owns_terminal &&
507 session_.generation() == terminal.generation) {
508 host_.input_release_pointer_capture();
509 session_.finish_terminal(terminal);
511 host_.input_request_repaint();
519 return drag_target_.has_value();
522 return drag_target_.live_in(host_.input_root());
527 return pending_high_surrogate_ != 0;
531 static bool route_press_to_open_combo(
View& root,
Point pt,
532 std::uint16_t modifiers) {
534 if (!combo)
return false;
535 float x = 0,
y = 0, width = 0,
height = 0;
536 if (!combo->dropdown_window_rect(x, y, width, height) ||
537 pt.
x < x || pt.
x > x + width ||
538 pt.
y < y || pt.
y > y + height)
542 event.window_position = pt;
544 event.modifiers = modifiers;
545 event.is_down =
true;
547 combo->on_mouse_event(event);
553 bool yield_to_gesture(
const MouseEvent& event) {
555 View& root = host_.input_root();
556 const std::uint64_t generation = session_.generation();
561 if (session_.generation() != generation || !session_.active())
563 if (!yielded)
return false;
566 session_.mark_claimed();
567 View* handoff_target = drag_target_.live_in(root);
568 drag_target_.reset();
575 InputRouterHost& host_;
576 PointerSession session_;
577 ViewCapture drag_target_;
579 bool tracking_leave_ =
false;
580 char16_t pending_high_surrogate_ = 0;
static void notify_global_click(View *target)
Called by the root view on any mouse click — closes popup if click is outside.
static ComboBox * active_popup_in(View &scope)
The open dropdown that belongs to scope's own tree, or nullptr.
Identity-safe reference to a View captured across native event boundaries.
Definition view.hpp:56
View * live_in(View &root) const noexcept
bool dispatch_gesture_pointer_event(const MouseEvent &root_event, double timestamp_seconds=-1.0)
void simulate_hover(Point root_pos)
virtual View * hit_test(Point local_point)
Bounded event contracts shared by host ingress and graph-authored nodes.
Definition anticipation_eligibility.hpp:9
void log_warn(std::format_string< Args... > fmt, Args &&... args)
Definition log.hpp:190
bool dispatch_key_for_root(View &root, int key_code, uint16_t modifiers, bool is_down)
bool transfer_input_focus(View &root, View *target)
Move input focus within one hosted root while tolerating callbacks that synchronously unmount either ...
void deliver_mouse_drag(View &root, View *target, Point root_pt, uint16_t modifiers, int click_count=1, PointerType pointer_type=PointerType::mouse, float pressure=0.5f)
Deliver one drag tick of an in-flight gesture to the captured target.
View * focused_input_under_root(View &root)
Return this root's live focused input.
@ kModCmd
Command (macOS) — alias for platform primary modifier.
Definition input_events.hpp:21
@ kModMeta
Windows key / Command key.
Definition input_events.hpp:20
@ kModAlt
Alt / Option.
Definition input_events.hpp:19
@ kModCtrl
Control key (Ctrl on Windows/Linux).
Definition input_events.hpp:18
bool should_yield_to_gesture(View &root, const MouseEvent &event)
Feed one pointer event to root's gesture arbiter and report whether the host must now YIELD — i....
@ 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
@ right
Definition input_events.hpp:70
@ left
Definition input_events.hpp:69
void deliver_mouse_up(View &root, View *target, Point root_pt, uint16_t modifiers, int click_count, const MouseUpHost &host)
Deliver a release for an in-flight gesture captured on target.
@ mouse
Mouse cursor (default).
Definition input_events.hpp:76
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.
bool deliver_mouse_down(View &root, View *target, Point root_pt, uint16_t modifiers, int click_count=1, bool bubble=true)
Deliver a press to an already-resolved target (the host has done the hit_test, any combo/overlay pre-...
void deliver_gesture_handoff(View &root, View *target, Point root_pt, uint16_t modifiers, int click_count)
Close the press bracket when a recognizer CLAIMS the pointer mid-gesture, after a press was already d...
KeyCode
Definition input_events.hpp:35
@ home
Definition input_events.hpp:54
@ y
Definition input_events.hpp:42
@ up
Definition input_events.hpp:53
@ down
Definition input_events.hpp:53
@ right
Definition input_events.hpp:53
@ left
Definition input_events.hpp:53
@ x
Definition input_events.hpp:41
@ end_
Definition input_events.hpp:54
@ unknown
Definition input_events.hpp:36
@ escape
Definition input_events.hpp:57
@ enter
Definition input_events.hpp:57
void deliver_mouse_wheel(View &root, Point root_pt, float scroll_delta_x, float scroll_delta_y, const WheelHost &host)
Route one wheel/scroll tick to the view tree rooted at root.
@ height
Definition css_animation.hpp:128
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
OverlayPressTarget route_press_to_active_overlay(View &root, Point root_pt)
Consult root's generalized overlay slot for a press at root_pt.
void deliver_mouse_cancel(View &root, View *target, Point root_pt, uint16_t modifiers, int click_count, MouseButton button, const PointerAttributes &pointer={})
Cancel an in-flight gesture through the same identity-safe terminal router as deliver_mouse_up.
The one implementation of Pulp's overlay-dismissal policy.
Rich key event with key code, modifiers, and repeat state.
Definition input_events.hpp:193
KeyCode key
Definition input_events.hpp:194
Optional host-owned continuation check for re-entrant press delivery.
Definition pointer_dispatch.hpp:279
std::function< bool()> should_continue
Definition pointer_dispatch.hpp:280
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
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
Host hooks the portable mouse-up router calls back into.
Definition pointer_dispatch.hpp:301
std::function< void(const std::function< void()> &click_handler, const std::string &clicked_id, uint16_t modifiers)> fire_click
Invoked exactly when the release lands on the SAME view the press captured (released == target,...
Definition pointer_dispatch.hpp:319
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
Host hooks the portable wheel router calls back into.
Definition pointer_dispatch.hpp:199
std::function< void()> request_repaint
Invoked after a wheel event mutates the tree (a scroll pane scrolled, a value widget stepped,...
Definition pointer_dispatch.hpp:205
Additional UI components: ComboBox, Tooltip, ProgressBar, CallOutBox, TabPanel, ListBox,...