[feat] acknowledge remote input and wait for visual changes

This commit is contained in:
dijunkun
2026-11-06 20:12:41 +08:00
parent a49eb7ad5b
commit 0eab020c38
15 changed files with 285 additions and 11 deletions
@@ -39,14 +39,14 @@ void RemoteInputDispatcher::Connect(const std::string& id) {
}
RemoteInputDispatcher::Result RemoteInputDispatcher::Push(
const std::string& id, const RemoteAction& action) {
const std::string& id, const RemoteAction& action, Completion completion) {
// HostInfo owns raw arrays; it must never enter this value-copy queue.
if (!Accepts(action)) return Result::rejected;
std::lock_guard lock(mutex_);
if (stopping_ || !connected_.count(id)) return Result::rejected;
if (IsMove(action) && !pending_.empty()) {
if (!completion && IsMove(action) && !pending_.empty()) {
auto& last = pending_.back();
if (last.id == id && last.IsInput() && IsMove(*last.action)) {
if (!last.completion && last.id == id && last.IsInput() && IsMove(*last.action)) {
last.action = action;
last.queued_at = Clock::now();
return Result::coalesced;
@@ -56,7 +56,7 @@ RemoteInputDispatcher::Result RemoteInputDispatcher::Push(
QueueReleaseLocked(id);
return Result::overflow;
}
pending_.push_back({id, action, Clock::now(), ItemKind::input});
pending_.push_back({id, action, Clock::now(), ItemKind::input, 0, std::move(completion)});
++pending_counts_[id];
ready_.notify_one();
return Result::queued;
@@ -328,6 +328,9 @@ void RemoteInputDispatcher::Run() {
!pending_counts_.count(item.id))
logs_.erase(item.id);
lock.unlock();
if (item.completion) {
try { item.completion(outcome); } catch (...) {}
}
if (report) {
try {
report_(item.id, queued_ms, execution_ms, outcome);
@@ -38,6 +38,7 @@ class RemoteInputDispatcher {
// Optional targeted adapter; legacy callers fall back to full Release.
using ReleaseMouse =
std::function<InputOutcome(const std::string&, unsigned)>;
using Completion = std::function<void(InputOutcome)>;
enum class Result { queued, coalesced, rejected, overflow };
static constexpr size_t kMaxPendingPerController = 128;
@@ -47,7 +48,8 @@ class RemoteInputDispatcher {
~RemoteInputDispatcher();
static bool Accepts(const RemoteAction& action);
void Connect(const std::string& id);
Result Push(const std::string& id, const RemoteAction& action);
Result Push(const std::string& id, const RemoteAction& action,
Completion completion = {});
void Disconnect(const std::string& id);
// Scheduled recovery is not idle work. Check HasPendingReleases() as well,
@@ -68,6 +70,7 @@ class RemoteInputDispatcher {
// Zero requests full controller cleanup; otherwise only these mouse
// buttons.
unsigned mouse_mask = 0;
Completion completion;
bool IsReset() const { return kind == ItemKind::reset_display; }
bool IsInput() const { return kind == ItemKind::input; }
bool IsCleanup() const { return kind == ItemKind::cleanup; }
@@ -120,4 +123,4 @@ class RemoteInputDispatcher {
} // namespace crossdesk
#endif
#endif