Chrome · Chromoting › Remoting
CVE-2026-113237
Memory Corruption in Chromoting (Remoting)
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifremoting/host/input_monitor/local_hotkey_input_monitor_x11.cc |
modified | |
forremoting/host/input_monitor/local_hotkey_input_monitor_x11.cc |
modified | |
ifremoting/host/input_monitor/local_input_monitor_x11_common.cc |
modified | |
forremoting/host/input_monitor/local_input_monitor_x11_common.cc |
modified | |
ifremoting/host/input_monitor/local_mouse_input_monitor_x11.cc |
modified | |
LocalMouseInputMonitorX11Testremoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc |
modified | |
forremoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc |
modified | |
ifremoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc |
modified | |
TEST_Fremoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc |
modified |
Files Changed
remoting/host/peer_session_impl.ccremoting/host/input_monitor/local_mouse_input_monitor_x11.hremoting/host/input_monitor/local_mouse_input_monitor_x11.ccremoting/host/input_monitor/local_hotkey_input_monitor_x11.ccremoting/host/BUILD.gnremoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.ccremoting/host/desktop_session_agent.ccremoting/host/input_monitor/local_input_monitor_x11_common.hremoting/host/input_monitor/local_input_monitor_x11_common.ccremoting/host/peer_session_impl_unittest.cc
Patch
From 3c9473be5e24baff49a71090fadb3f141e8e593c Mon Sep 17 00:00:00 2001
From: Jamie Walch <jamiewalch@chromium.org>
Date: Mon, 21 Sep 2026 17:05:36 -0700
Subject: [PATCH] [remoting] Filter out XTest motion in LocalMouseInputMonitorX11 and disable X11 echo filtering
Update LocalMouseInputMonitorX11 to ignore RawMotion events originating
from XTEST virtual devices (sharing GetXTestDeviceIds with
LocalHotkeyInputMonitorX11) so remote XTest-injected pointer motion is
never reported as local mouse activity.
With self-filtering in place on X11, disable position-based echo
filtering in RemoteInputFilter (SetExpectLocalEcho(false)) on Linux X11
in both PeerSessionImpl and DesktopSessionAgent while retaining it for
Wayland sessions (PipewireLocalInputMonitor).
TAG=agy
CONV=4b851193-d649-43a8-8a69-eabdd12dba8b
Bug: b:562978160
Fixed: b:562978160
Change-Id: Ibee8190d191618ce024640ad106cc0d89769d8ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8435388
Reviewed-by: Lambros Lambrou <lambroslambrou@chromium.org>
Auto-Submit: Jamie Walch <jamiewalch@chromium.org>
Commit-Queue: Lambros Lambrou <lambroslambrou@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1702230}
---
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index 8efcf75..13becedb 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -50,6 +50,7 @@
#include "remoting/proto/url_forwarder_control.pb.h"
#include "remoting/protocol/clipboard_stub.h"
#include "remoting/protocol/input_event_tracker.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "ui/events/types/event_type.h"
@@ -678,7 +679,13 @@
// LocalInputMonitorWin filters out an echo of the injected input before it
// reaches |remote_input_filter_|.
remote_input_filter_->SetExpectLocalEcho(false);
-#endif // BUILDFLAG(IS_WIN)
+#elif BUILDFLAG(IS_LINUX)
+ // LocalMouseInputMonitorX11 filters out XTest-injected input before it
+ // reaches `remote_input_filter_`.
+ if (!webrtc::DesktopCapturer::IsRunningUnderWayland()) {
+ remote_input_filter_->SetExpectLocalEcho(false);
+ }
+#endif
// Start the input injector.
std::unique_ptr<protocol::ClipboardStub> clipboard_stub(
diff --git a/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc b/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc
index b72fc0f..9c9cdaa8 100644
--- a/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc
+++ b/remoting/host/input_monitor/local_hotkey_input_monitor_x11.cc
@@ -86,20 +86,7 @@
void LocalHotkeyInputMonitorX11::Core::UpdateXTestDeviceIds() {
DCHECK(input_task_runner_->BelongsToCurrentThread());
- xtest_device_ids_.clear();
-
- auto reply =
- connection_->xinput().XIQueryDevice({x11::Input::DeviceId::All}).Sync();
- if (!reply) {
- LOG(ERROR) << "XIQueryDevice failed.";
- return;
- }
- for (const auto& info : reply->infos) {
- if (info.name.ends_with("XTEST keyboard") ||
- info.name.ends_with("XTEST pointer")) {
- xtest_device_ids_.insert(info.deviceid);
- }
- }
+ xtest_device_ids_ = GetXTestDeviceIds(connection_);
}
bool LocalHotkeyInputMonitorX11::Core::IsXTestDevice(
diff --git a/remoting/host/input_monitor/local_input_monitor_x11_common.cc b/remoting/host/input_monitor/local_input_monitor_x11_common.cc
index cc40c32..d5e331a 100644
--- a/remoting/host/input_monitor/local_input_monitor_x11_common.cc
+++ b/remoting/host/input_monitor/local_input_monitor_x11_common.cc
@@ -5,6 +5,8 @@
#include "remoting/host/input_monitor/local_input_monitor_x11_common.h"
#include "base/containers/span.h"
+#include "base/logging.h"
+#include "ui/gfx/x/future.h"
namespace remoting {
@@ -19,4 +21,22 @@
return mask;
}
+base::flat_set<x11::Input::DeviceId> GetXTestDeviceIds(
+ x11::Connection* connection) {
+ base::flat_set<x11::Input::DeviceId> xtest_device_ids;
+ auto reply =
+ connection->xinput().XIQueryDevice({x11::Input::DeviceId::All}).Sync();
+ if (!reply) {
+ LOG(ERROR) << "XIQueryDevice failed.";
+ return xtest_device_ids;
+ }
+ for (const auto& info : reply->infos) {
+ if (info.name.ends_with("XTEST keyboard") ||
+ info.name.ends_with("XTEST pointer")) {
+ xtest_device_ids.insert(info.deviceid);
+ }
+ }
+ return xtest_device_ids;
+}
+
} // namespace remoting
diff --git a/remoting/host/input_monitor/local_input_monitor_x11_common.h b/remoting/host/input_monitor/local_input_monitor_x11_common.h
index b3f197d..c616ed6 100644
--- a/remoting/host/input_monitor/local_input_monitor_x11_common.h
+++ b/remoting/host/input_monitor/local_input_monitor_x11_common.h
@@ -5,7 +5,9 @@
#ifndef REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_
#define REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_
+#include "base/containers/flat_set.h"
#include "ui/events/devices/x11/xinput_util.h"
+#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/xinput.h"
namespace remoting {
@@ -15,6 +17,11 @@
// the same mask.
x11::Input::XIEventMask CommonXIEventMaskForRootWindow();
+// Queries XInput2 and returns the set of DeviceIds corresponding to synthetic
+// XTEST devices ("XTEST keyboard" and "XTEST pointer").
+base::flat_set<x11::Input::DeviceId> GetXTestDeviceIds(
+ x11::Connection* connection);
+
} // namespace remoting
#endif // REMOTING_HOST_INPUT_MONITOR_LOCAL_INPUT_MONITOR_X11_COMMON_H_
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc b/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc
index 6e51893a..1a73f1dd 100644
--- a/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc
+++ b/remoting/host/input_monitor/local_mouse_input_monitor_x11.cc
@@ -81,6 +81,8 @@
return;
}
+ xtest_device_ids_ = GetXTestDeviceIds(connection_);
+
auto mask = CommonXIEventMaskForRootWindow();
connection_->xinput().XISelectEvents(
{connection_->default_root(),
@@ -93,6 +95,12 @@
connection_->RemoveEventObserver(this);
}
+bool LocalMouseInputMonitorX11::Core::IsXTestDevice(
+ x11::Input::DeviceId device_id) const {
+ DCHECK(input_task_runner_->BelongsToCurrentThread());
+ return xtest_device_ids_.contains(device_id);
+}
+
void LocalMouseInputMonitorX11::Core::OnEvent(const x11::Event& event) {
DCHECK(input_task_runner_->BelongsToCurrentThread());
@@ -105,6 +113,11 @@
if (raw->opcode != x11::Input::RawDeviceEvent::RawMotion) {
return;
}
+ // Ignore events injected via XTEST so remote input is not mistaken for local
+ // mouse activity.
+ if (IsXTestDevice(raw->sourceid)) {
+ return;
+ }
connection_->QueryPointer({connection_->default_root()})
.OnResponse(base::BindOnce(
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_x11.h b/remoting/host/input_monitor/local_mouse_input_monitor_x11.h
index fdcc1303..6593e7ea 100644
--- a/remoting/host/input_monitor/local_mouse_input_monitor_x11.h
+++ b/remoting/host/input_monitor/local_mouse_input_monitor_x11.h
@@ -5,6 +5,7 @@
#ifndef REMOTING_HOST_INPUT_MONITOR_LOCAL_MOUSE_INPUT_MONITOR_X11_H_
#define REMOTING_HOST_INPUT_MONITOR_LOCAL_MOUSE_INPUT_MONITOR_X11_H_
+#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
@@ -50,8 +51,7 @@
void StartOnInputThread();
void StopOnInputThread();
- // Called when there are pending X events.
- void OnConnectionData();
+ bool IsXTestDevice(x11::Input::DeviceId device_id) const;
// x11::EventObserver:
void OnEvent(const x11::Event& event) override;
@@ -65,6 +65,9 @@
// Used to send mouse event notifications.
LocalInputMonitor::PointerMoveCallback on_mouse_move_;
+ // Cached XTEST device IDs to ignore synthetic events.
+ base::flat_set<x11::Input::DeviceId> xtest_device_ids_;
+
raw_ptr<x11::Connection> connection_ = nullptr;
};
diff --git a/remoting/host/peer_session_impl.cc b/remoting/host/peer_session_impl.cc
index 2a4c3f7..17a4a0d 100644
--- a/remoting/host/peer_session_impl.cc
+++ b/remoting/host/peer_session_impl.cc
@@ -95,6 +95,7 @@
#include "remoting/protocol/webrtc_connection_to_client.h"
#include "remoting/protocol/webrtc_video_stream.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor.h"
#include "ui/events/types/event_type.h"
@@ -154,7 +155,15 @@
// LocalMouseInputMonitorMac filter out an echo of the injected input before
// it reaches `remote_input_filter_`.
input_pipeline_.remote_input_filter()->SetExpectLocalEcho(false);
-#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC)
+#elif BUILDFLAG(IS_LINUX)
+ // LocalMouseInputMonitorX11 filters out XTest-injected input before it
+ // reaches `remote_input_filter_`. On Wayland, PipewireLocalInputMonitor
+ // observes global cursor positions from PipeWire and still relies on echo
+ // filtering.
+ if (!webrtc::DesktopCapturer::IsRunningUnderWayland()) {
+ input_pipeline_.remote_input_filter()->SetExpectLocalEcho(false);
+ }
+#endif
}
void PeerSessionImpl::Start(
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc b/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc
new file mode 100644
index 0000000..87f3ca9
--- /dev/null
+++ b/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/functional/callback_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "remoting/host/input_monitor/local_input_monitor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "ui/events/event.h"
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/event.h"
+#include "ui/gfx/x/future.h"
+#include "ui/gfx/x/xinput.h"
+#include "ui/gfx/x/xproto.h"
+#include "ui/gfx/x/xtest.h"
+
+namespace remoting {
+
+class LocalMouseInputMonitorX11Test : public testing::Test {
+ public:
+ LocalMouseInputMonitorX11Test()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
+
+ void SetUp() override {
+ connection_ = x11::Connection::Get();
+ ASSERT_NE(connection_, nullptr);
+ ASSERT_TRUE(connection_->Ready());
+ ASSERT_TRUE(connection_->xinput().present());
+
+ auto reply =
+ connection_->xinput().XIQueryDevice({x11::Input::DeviceId::All}).Sync();
+ ASSERT_TRUE(reply);
+ for (const auto& info : reply->infos) {
+ if (info.type == x11::Input::DeviceType::MasterPointer) {
+ master_pointer_id_ = info.deviceid;
+ } else if (info.name.ends_with("XTEST pointer")) {
+ xtest_pointer_id_ = info.deviceid;
+ }
+ }
+ ASSERT_NE(master_pointer_id_, x11::Input::DeviceId{});
+ ASSERT_NE(xtest_pointer_id_, x11::Input::DeviceId{});
+ ASSERT_NE(xtest_pointer_id_, kLocalPointerId);
+
+ auto task_runner = task_environment_.GetMainThreadTaskRunner();
+ monitor_ =
+ LocalInputMonitor::Create(task_runner, task_runner, task_runner);
+ monitor_->StartMonitoring(pointer_move_future_.GetRepeatingCallback(),
+ LocalInputMonitor::KeyPressedCallback(),
+ base::DoNothing());
+ FlushTaskRunner();
+ connection_->Sync();
+ connection_->DispatchAll();
+ }
+
+ void TearDown() override {
+ monitor_.reset();
+ FlushTaskRunner();
+ }
+
+ void DispatchRawMotionEvent(x11::Input::DeviceId source_id) {
+ x11::Input::RawDeviceEvent raw_event;
+ raw_event.opcode = x11::Input::RawDeviceEvent::RawMotion;
+ raw_event.deviceid = master_pointer_id_;
+ raw_event.sourceid = source_id;
+
+ x11::Event event(false, std::move(raw_event));
+ connection_->DispatchEvent(event);
+ connection_->Sync();
+ connection_->DispatchAll();
+ FlushTaskRunner();
+ }
+
+ void InjectXTestMotionEvent(int16_t x, int16_t y) {
+ ASSERT_TRUE(connection_->xtest().present());
+ connection_->xtest().FakeInput({
+ .type = x11::MotionNotifyEvent::opcode,
+ .detail = false,
+ .root = connection_->default_root(),
+ .rootX = x,
+ .rootY = y,
+ });
+ connection_->Sync();
+ connection_->DispatchAll();
+ FlushTaskRunner();
+ }
+
+ void FlushTaskRunner() {
+ base::RunLoop run_loop;
+ task_environment_.GetMainThreadTaskRunner()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ protected:
+ // Headless Xorg (used by testing/xvfb.py on CQ bots) only creates the master
+ // devices and the virtual XTEST devices, with no physical pointer attached.
+ // Use a distinct synthetic DeviceId to represent a physical pointer when
+ // dispatching RawDeviceEvents.
+ static constexpr x11::Input::DeviceId kLocalPointerId{100};
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ raw_ptr<x11::Connection> connection_ = nullptr;
+ x11::Input::DeviceId master_pointer_id_{};
+ x11::Input::DeviceId xtest_pointer_id_{};
+ x11::Input::DeviceId local_pointer_id_{kLocalPointerId};
+ base::test::TestFuture<const webrtc::DesktopVector&, ui::EventType>
+ pointer_move_future_;
+ std::unique_ptr<LocalInputMonitor> monitor_;
+};
+
+TEST_F(LocalMouseInputMonitorX11Test, LocalMotionTriggersCallback) {
+ DispatchRawMotionEvent(local_pointer_id_);
+
+ ASSERT_TRUE(pointer_move_future_.Wait());
+ EXPECT_EQ(pointer_move_future_.Get<1>(), ui::EventType::kMouseMoved);
+}
+
+TEST_F(LocalMouseInputMonitorX11Test,
+ RemoteInjectedXTestMotionDoesNotTriggerCallback) {
+ DispatchRawMotionEvent(xtest_pointer_id_);
+ InjectXTestMotionEvent(100, 100);
+ InjectXTestMotionEvent(101, 100);
+
+ EXPECT_FALSE(pointer_move_future_.IsReady());
+
+ // Subsequent local motion should still be detected.
+ DispatchRawMotionEvent(local_pointer_id_);
+ ASSERT_TRUE(pointer_move_future_.Wait());
+ EXPECT_EQ(pointer_move_future_.Get<1>(), ui::EventType::kMouseMoved);
+}
+
+} // namespace remoting
diff --git a/remoting/host/peer_session_impl_unittest.cc b/remoting/host/peer_session_impl_unittest.cc
index 901e447..01d0536 100644
--- a/remoting/host/peer_session_impl_unittest.cc
+++ b/remoting/host/peer_session_impl_unittest.cc
@@ -59,6 +59,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/events/event.h"
@@ -520,11 +521,13 @@
connection_->input_stub()->InjectMouseEvent(MakeFractionalMouseMoveEvent(
100, 101, kDisplay1Id, kDisplay1Width, kDisplay1Height));
... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc b/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc
new file mode 100644
index 0000000..87f3ca9
--- /dev/null
+++ b/remoting/host/input_monitor/local_mouse_input_monitor_x11_unittest.cc
@@ -0,0 +1,138 @@
+// Copyright 2026 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/functional/callback_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
+#include "remoting/host/input_monitor/local_input_monitor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "ui/events/event.h"
+#include "ui/gfx/x/connection.h"
+#include "ui/gfx/x/event.h"
+#include "ui/gfx/x/future.h"
+#include "ui/gfx/x/xinput.h"
+#include "ui/gfx/x/xproto.h"
+#include "ui/gfx/x/xtest.h"
+
+namespace remoting {
+
+class LocalMouseInputMonitorX11Test : public testing::Test {
+ public:
+ LocalMouseInputMonitorX11Test()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {}
+
+ void SetUp() override {
+ connection_ = x11::Connection::Get();
+ ASSERT_NE(connection_, nullptr);
+ ASSERT_TRUE(connection_->Ready());
+ ASSERT_TRUE(connection_->xinput().present());
+
+ auto reply =
+ connection_->xinput().XIQueryDevice({x11::Input::DeviceId::All}).Sync();
+ ASSERT_TRUE(reply);
+ for (const auto& info : reply->infos) {
+ if (info.type == x11::Input::DeviceType::MasterPointer) {
+ master_pointer_id_ = info.deviceid;
+ } else if (info.name.ends_with("XTEST pointer")) {
+ xtest_pointer_id_ = info.deviceid;
+ }
+ }
+ ASSERT_NE(master_pointer_id_, x11::Input::DeviceId{});
+ ASSERT_NE(xtest_pointer_id_, x11::Input::DeviceId{});
+ ASSERT_NE(xtest_pointer_id_, kLocalPointerId);
+
+ auto task_runner = task_environment_.GetMainThreadTaskRunner();
+ monitor_ =
+ LocalInputMonitor::Create(task_runner, task_runner, task_runner);
+ monitor_->StartMonitoring(pointer_move_future_.GetRepeatingCallback(),
+ LocalInputMonitor::KeyPressedCallback(),
+ base::DoNothing());
+ FlushTaskRunner();
+ connection_->Sync();
+ connection_->DispatchAll();
+ }
+
+ void TearDown() override {
+ monitor_.reset();
+ FlushTaskRunner();
+ }
+
+ void DispatchRawMotionEvent(x11::Input::DeviceId source_id) {
+ x11::Input::RawDeviceEvent raw_event;
+ raw_event.opcode = x11::Input::RawDeviceEvent::RawMotion;
+ raw_event.deviceid = master_pointer_id_;
+ raw_event.sourceid = source_id;
+
+ x11::Event event(false, std::move(raw_event));
+ connection_->DispatchEvent(event);
+ connection_->Sync();
+ connection_->DispatchAll();
+ FlushTaskRunner();
+ }
+
+ void InjectXTestMotionEvent(int16_t x, int16_t y) {
+ ASSERT_TRUE(connection_->xtest().present());
+ connection_->xtest().FakeInput({
+ .type = x11::MotionNotifyEvent::opcode,
+ .detail = false,
+ .root = connection_->default_root(),
+ .rootX = x,
+ .rootY = y,
+ });
+ connection_->Sync();
+ connection_->DispatchAll();
+ FlushTaskRunner();
+ }
+
+ void FlushTaskRunner() {
+ base::RunLoop run_loop;
+ task_environment_.GetMainThreadTaskRunner()->PostTask(
+ FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ protected:
+ // Headless Xorg (used by testing/xvfb.py on CQ bots) only creates the master
+ // devices and the virtual XTEST devices, with no physical pointer attached.
+ // Use a distinct synthetic DeviceId to represent a physical pointer when
+ // dispatching RawDeviceEvents.
+ static constexpr x11::Input::DeviceId kLocalPointerId{100};
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ raw_ptr<x11::Connection> connection_ = nullptr;
+ x11::Input::DeviceId master_pointer_id_{};
+ x11::Input::DeviceId xtest_pointer_id_{};
+ x11::Input::DeviceId local_pointer_id_{kLocalPointerId};
+ base::test::TestFuture<const webrtc::DesktopVector&, ui::EventType>
+ pointer_move_future_;
+ std::unique_ptr<LocalInputMonitor> monitor_;
+};
+
+TEST_F(LocalMouseInputMonitorX11Test, LocalMotionTriggersCallback) {
+ DispatchRawMotionEvent(local_pointer_id_);
+
+ ASSERT_TRUE(pointer_move_future_.Wait());
+ EXPECT_EQ(pointer_move_future_.Get<1>(), ui::EventType::kMouseMoved);
+}
+
+TEST_F(LocalMouseInputMonitorX11Test,
+ RemoteInjectedXTestMotionDoesNotTriggerCallback) {
+ DispatchRawMotionEvent(xtest_pointer_id_);
+ InjectXTestMotionEvent(100, 100);
+ InjectXTestMotionEvent(101, 100);
+
+ EXPECT_FALSE(pointer_move_future_.IsReady());
+
+ // Subsequent local motion should still be detected.
+ DispatchRawMotionEvent(local_pointer_id_);
+ ASSERT_TRUE(pointer_move_future_.Wait());
+ EXPECT_EQ(pointer_move_future_.Get<1>(), ui::EventType::kMouseMoved);
+}
+
+} // namespace remoting
diff --git a/remoting/host/peer_session_impl_unittest.cc b/remoting/host/peer_session_impl_unittest.cc
index 901e447..01d0536 100644
--- a/remoting/host/peer_session_impl_unittest.cc
+++ b/remoting/host/peer_session_impl_unittest.cc
@@ -59,6 +59,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "ui/events/event.h"
@@ -520,11 +521,13 @@
connection_->input_stub()->InjectMouseEvent(MakeFractionalMouseMoveEvent(
100, 101, kDisplay1Id, kDisplay1Width, kDisplay1Height));
-#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MAC)
- // The OS echoes the injected event back.
- peer_session_->OnLocalPointerMoved(webrtc::DesktopVector(100, 101),
- ui::EventType::kMouseMoved);
-#endif // !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_MAC)
+#if BUILDFLAG(IS_LINUX)
+ if (webrtc::DesktopCapturer::IsRunningUnderWayland()) {
+ // Under Wayland, PipewireLocalInputMonitor echoes the injected event back.
+ peer_session_->OnLocalPointerMoved(webrtc::DesktopVector(100, 101),
+ ui::EventType::kMouseMoved);
+ }
+#endif // BUILDFLAG(IS_LINUX)
// This one should get through as well.
connection_->input_stub()->InjectMouseEvent(MakeFractionalMouseMoveEvent(
@@ -622,8 +625,6 @@
EqualsMouseMoveEvent(kDisplay1Width - 1, kDisplay1Height - 1));
}
-
-
TEST_F(PeerSessionImplTest, DataChannelCallbackIsCalled) {
ConnectPeerSession();
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page