Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pointer_coalescer.hpp
Go to the documentation of this file.
1// pointer_coalescer.hpp — collapse a burst of pointer motion into one
2// dispatch per presented frame.
3//
4// A host receives pointer motion at the input device's rate; it presents
5// frames at the display's rate, or slower when a frame is expensive. Those two
6// rates are independent, and when motion outruns presentation every extra
7// sample costs a full delivery — hit test, handler invocation (which for a
8// scripted UI means entering the JS engine), and an invalidation whose only
9// effect is to re-dirty a surface that is already dirty. None of that work
10// reaches the screen: only the last sample before the next presented frame is
11// visible.
12//
13// Measured on Spectr Native Preview before this existed: at 60 input events
14// per second — an ordinary hand-drag rate, not a synthetic one — the app
15// presented 2.7 frames per second while issuing ~997 repaint requests per
16// second, i.e. ~363 repaint requests per presented frame. Holding the button
17// still (no motion) stayed at 7.5 fps, so it is the motion, not the gesture
18// state, that costs.
19//
20// ── What this deliberately does NOT decide ──────────────────────────────────
21//
22// This type coalesces a STREAM. It knows nothing about views, hit testing, or
23// dispatch, so it can be unit-tested without a window and reused by any host.
24// The caller decides what a flushed sample means.
25//
26// It also does not assume the consumer can reconstruct skipped motion. Some
27// consumers can: Spectr's band paint sends (start_band, current_band) and
28// repaints that whole span every message, so dropping intermediate samples
29// provably cannot leave gaps. Others cannot — anything that stamps one value
30// per sample would draw a dotted line instead of a stroke. So a coalesced move
31// carries the full merged `path` alongside the surviving position, and a
32// consumer that needs the intermediate points can walk it. Nothing here forces
33// the span interpretation into shared code.
34
35#pragma once
36
39
40#include <cstddef>
41#include <vector>
42
43namespace pulp::view {
44
64
72public:
87 std::vector<PointerSample> submit(const PointerSample& sample);
88
91 std::vector<PointerSample> flush_frame();
92
94 bool has_pending() const { return has_pending_; }
95
98 const std::vector<Point>& pending_path() const { return path_; }
99
103 std::size_t last_merged_count() const { return last_merged_; }
104
106 std::size_t total_merged() const { return total_merged_; }
107
110 void reset();
111
112private:
113 std::vector<PointerSample> take_pending_();
114
115 PointerSample pending_{};
116 std::vector<Point> path_;
117 bool has_pending_ = false;
118 std::size_t merged_in_pending_ = 0;
119 std::size_t last_merged_ = 0;
120 std::size_t total_merged_ = 0;
121};
122
123} // namespace pulp::view
Collapses runs of motion into one sample per presented frame while leaving button transitions untouch...
Definition pointer_coalescer.hpp:71
std::vector< PointerSample > submit(const PointerSample &sample)
Feed one raw sample.
std::vector< PointerSample > flush_frame()
Call once per PRESENTED frame.
std::size_t total_merged() const
Total motion samples dropped since construction. Diagnostics only.
Definition pointer_coalescer.hpp:106
const std::vector< Point > & pending_path() const
Positions merged into the currently-held motion, oldest first, with the surviving position last.
Definition pointer_coalescer.hpp:98
std::size_t last_merged_count() const
Raw motion samples discarded by the most recent flush or transition — the samples that would have bee...
Definition pointer_coalescer.hpp:103
void reset()
Drop any held motion without dispatching it.
bool has_pending() const
True when motion is held and waiting for a flush.
Definition pointer_coalescer.hpp:94
Input event types with modifier keys and pointer IDs.
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
MouseButton
Mouse button identifiers.
Definition input_events.hpp:67
@ left
Definition input_events.hpp:69
MousePhase
Explicit press/drag/release phase for a pointer gesture.
Definition input_events.hpp:94
@ automatic
Infer from is_down (legacy / headless default).
Definition input_events.hpp:95
@ 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
Definition geometry.hpp:20
Device identity of the pointer a delivery verb is dispatching, stamped onto every MouseEvent the verb...
Definition pointer_dispatch.hpp:110
One pointer sample as the host received it, before any coalescing.
Definition pointer_coalescer.hpp:46
PointerAttributes pointer
Definition pointer_coalescer.hpp:55
int click_count
Definition pointer_coalescer.hpp:52
MouseButton button
Definition pointer_coalescer.hpp:54
bool is_motion() const
Motion is mergeable; a button transition is not.
Definition pointer_coalescer.hpp:60
std::vector< Point > path
Raw positions represented by this sample after coalescing, oldest first.
Definition pointer_coalescer.hpp:50
Point position
Definition pointer_coalescer.hpp:47
std::uint16_t modifiers
Definition pointer_coalescer.hpp:51
MousePhase phase
Definition pointer_coalescer.hpp:53