Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0627351

Browse files
chaopengdkwingsmtmoffatman
authored
[Fuchsia] Support scroll_*_physical_pixel fields (#34325)
* [WIP][Fuchsia] Support scroll_physical_pixel fields * add test * update * update * update * update * update * update * update * update * use scroll_delta instead of pan * use kMouse * use kMouse * Update shell/platform/fuchsia/flutter/pointer_delegate.cc Co-authored-by: Tong Mu <[email protected]> * Update shell/platform/fuchsia/flutter/pointer_delegate.cc Co-authored-by: Callum Moffat <[email protected]> * format Co-authored-by: Tong Mu <[email protected]> Co-authored-by: Callum Moffat <[email protected]>
1 parent 92606c2 commit 0627351

File tree

4 files changed

+328
-21
lines changed

4 files changed

+328
-21
lines changed

shell/platform/fuchsia/flutter/pointer_delegate.cc

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -287,22 +287,40 @@ flutter::PointerData CreateMouseDraft(const fup_MouseEvent& event,
287287
ptr.buttons = flutter_buttons;
288288
}
289289

290-
// Fuchsia currently provides scroll data in "ticks", not physical pixels.
291-
// However, Flutter expects scroll data in physical pixels. To compensate for
292-
// lack of guidance, we make up a "reasonable amount".
293-
// TODO(fxbug.dev/85388): Replace with physical pixel scroll.
290+
// Fuchsia previously only provided scroll data in "ticks", not physical
291+
// pixels. On legacy platforms, since Flutter expects scroll data in physical
292+
// pixels, to compensate for lack of guidance, we make up a "reasonable
293+
// amount".
294+
// TODO(fxbug.dev/103443): Remove the tick based scrolling after the
295+
// transition.
294296
const int kScrollOffsetMultiplier = 20;
295297

296-
if (sample.has_scroll_v()) {
297-
ptr.signal_kind = flutter::PointerData::SignalKind::kScroll;
298-
double dy = -sample.scroll_v() * kScrollOffsetMultiplier; // logical amount
299-
ptr.scroll_delta_y = dy; // Not yet physical; adjusted in Platform View.
298+
double dy = 0;
299+
double dx = 0;
300+
bool is_scroll = false;
301+
302+
if (sample.has_scroll_v_physical_pixel()) {
303+
dy = -sample.scroll_v_physical_pixel();
304+
is_scroll = true;
305+
} else if (sample.has_scroll_v()) {
306+
dy = -sample.scroll_v() *
307+
kScrollOffsetMultiplier; // logical amount, not yet physical; adjusted
308+
// in Platform View.
309+
is_scroll = true;
310+
}
311+
312+
if (sample.has_scroll_h_physical_pixel()) {
313+
dx = sample.scroll_h_physical_pixel();
314+
is_scroll = true;
315+
} else if (sample.has_scroll_h()) {
316+
dx = sample.scroll_h() * kScrollOffsetMultiplier; // logical amount
317+
is_scroll = true;
300318
}
301319

302-
if (sample.has_scroll_h()) {
320+
if (is_scroll) {
303321
ptr.signal_kind = flutter::PointerData::SignalKind::kScroll;
304-
double dx = sample.scroll_h() * kScrollOffsetMultiplier; // logical amount
305-
ptr.scroll_delta_x = dx; // Not yet physical; adjusted in Platform View.
322+
ptr.scroll_delta_y = dy;
323+
ptr.scroll_delta_x = dx;
306324
}
307325

308326
return ptr;

shell/platform/fuchsia/flutter/pointer_delegate_unittests.cc

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ using fup_TouchPointerSample = fuchsia::ui::pointer::TouchPointerSample;
3030
using fup_TouchResponse = fuchsia::ui::pointer::TouchResponse;
3131
using fup_TouchResponseType = fuchsia::ui::pointer::TouchResponseType;
3232
using fup_ViewParameters = fuchsia::ui::pointer::ViewParameters;
33+
using fup_MouseEvent = fuchsia::ui::pointer::MouseEvent;
3334

3435
constexpr std::array<std::array<float, 2>, 2> kRect = {{{0, 0}, {20, 20}}};
3536
constexpr std::array<float, 9> kIdentity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
3637
constexpr fup_TouchIxnId kIxnOne = {.device_id = 1u,
3738
.pointer_id = 1u,
3839
.interaction_id = 2u};
3940

41+
constexpr uint32_t kMouseDeviceId = 123;
42+
constexpr std::array<int64_t, 2> kNoScrollInPhysicalPixelDelta = {0, 0};
43+
const bool kNotPrecisionScroll = false;
44+
const bool kPrecisionScroll = true;
45+
4046
// Fixture to exercise Flutter runner's implementation for
4147
// fuchsia.ui.pointer.TouchSource.
4248
class PointerDelegateTest : public ::testing::Test {
@@ -676,4 +682,163 @@ TEST_F(PointerDelegateTest, Protocol_PointersAreIndependent) {
676682
pointers = {};
677683
}
678684

685+
TEST_F(PointerDelegateTest, MouseWheel_TickBased) {
686+
std::optional<std::vector<flutter::PointerData>> pointers;
687+
pointer_delegate_->WatchLoop(
688+
[&pointers](std::vector<flutter::PointerData> events) {
689+
pointers = std::move(events);
690+
});
691+
RunLoopUntilIdle(); // Server gets watch call.
692+
693+
std::vector<fup_MouseEvent> events =
694+
MouseEventBuilder()
695+
.AddTime(1111789u)
696+
.AddViewParameters(kRect, kRect, kIdentity)
697+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1},
698+
kNoScrollInPhysicalPixelDelta, kNotPrecisionScroll)
699+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
700+
.BuildAsVector();
701+
mouse_source_->ScheduleCallback(std::move(events));
702+
RunLoopUntilIdle();
703+
704+
ASSERT_TRUE(pointers.has_value());
705+
ASSERT_EQ(pointers.value().size(), 1u);
706+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
707+
EXPECT_EQ(pointers.value()[0].signal_kind,
708+
flutter::PointerData::SignalKind::kScroll);
709+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
710+
EXPECT_EQ(pointers.value()[0].buttons, 0);
711+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
712+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, -20);
713+
pointers = {};
714+
715+
// receive a horizontal scroll
716+
events = MouseEventBuilder()
717+
.AddTime(1111789u)
718+
.AddViewParameters(kRect, kRect, kIdentity)
719+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0},
720+
kNoScrollInPhysicalPixelDelta, kNotPrecisionScroll)
721+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
722+
.BuildAsVector();
723+
mouse_source_->ScheduleCallback(std::move(events));
724+
RunLoopUntilIdle();
725+
726+
ASSERT_TRUE(pointers.has_value());
727+
ASSERT_EQ(pointers.value().size(), 1u);
728+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
729+
EXPECT_EQ(pointers.value()[0].signal_kind,
730+
flutter::PointerData::SignalKind::kScroll);
731+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
732+
EXPECT_EQ(pointers.value()[0].buttons, 0);
733+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 20);
734+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
735+
pointers = {};
736+
}
737+
738+
TEST_F(PointerDelegateTest, MouseWheel_PixelBased) {
739+
std::optional<std::vector<flutter::PointerData>> pointers;
740+
pointer_delegate_->WatchLoop(
741+
[&pointers](std::vector<flutter::PointerData> events) {
742+
pointers = std::move(events);
743+
});
744+
RunLoopUntilIdle(); // Server gets watch call.
745+
746+
std::vector<fup_MouseEvent> events =
747+
MouseEventBuilder()
748+
.AddTime(1111789u)
749+
.AddViewParameters(kRect, kRect, kIdentity)
750+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120},
751+
kNotPrecisionScroll)
752+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
753+
.BuildAsVector();
754+
mouse_source_->ScheduleCallback(std::move(events));
755+
RunLoopUntilIdle();
756+
757+
ASSERT_TRUE(pointers.has_value());
758+
ASSERT_EQ(pointers.value().size(), 1u);
759+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
760+
EXPECT_EQ(pointers.value()[0].signal_kind,
761+
flutter::PointerData::SignalKind::kScroll);
762+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
763+
EXPECT_EQ(pointers.value()[0].buttons, 0);
764+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
765+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120);
766+
pointers = {};
767+
768+
// receive a horizontal scroll
769+
events = MouseEventBuilder()
770+
.AddTime(1111789u)
771+
.AddViewParameters(kRect, kRect, kIdentity)
772+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0},
773+
kNotPrecisionScroll)
774+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
775+
.BuildAsVector();
776+
mouse_source_->ScheduleCallback(std::move(events));
777+
RunLoopUntilIdle();
778+
779+
ASSERT_TRUE(pointers.has_value());
780+
ASSERT_EQ(pointers.value().size(), 1u);
781+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
782+
EXPECT_EQ(pointers.value()[0].signal_kind,
783+
flutter::PointerData::SignalKind::kScroll);
784+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
785+
EXPECT_EQ(pointers.value()[0].buttons, 0);
786+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120);
787+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
788+
pointers = {};
789+
}
790+
791+
TEST_F(PointerDelegateTest, MouseWheel_TouchpadPixelBased) {
792+
std::optional<std::vector<flutter::PointerData>> pointers;
793+
pointer_delegate_->WatchLoop(
794+
[&pointers](std::vector<flutter::PointerData> events) {
795+
pointers = std::move(events);
796+
});
797+
RunLoopUntilIdle(); // Server gets watch call.
798+
799+
std::vector<fup_MouseEvent> events =
800+
MouseEventBuilder()
801+
.AddTime(1111789u)
802+
.AddViewParameters(kRect, kRect, kIdentity)
803+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {0, 1}, {0, 120},
804+
kPrecisionScroll)
805+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
806+
.BuildAsVector();
807+
mouse_source_->ScheduleCallback(std::move(events));
808+
RunLoopUntilIdle();
809+
810+
ASSERT_TRUE(pointers.has_value());
811+
ASSERT_EQ(pointers.value().size(), 1u);
812+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
813+
EXPECT_EQ(pointers.value()[0].signal_kind,
814+
flutter::PointerData::SignalKind::kScroll);
815+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
816+
EXPECT_EQ(pointers.value()[0].buttons, 0);
817+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 0);
818+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, -120);
819+
pointers = {};
820+
821+
// receive a horizontal scroll
822+
events = MouseEventBuilder()
823+
.AddTime(1111789u)
824+
.AddViewParameters(kRect, kRect, kIdentity)
825+
.AddSample(kMouseDeviceId, {10.f, 10.f}, {}, {1, 0}, {120, 0},
826+
kPrecisionScroll)
827+
.AddMouseDeviceInfo(kMouseDeviceId, {0, 1, 2})
828+
.BuildAsVector();
829+
mouse_source_->ScheduleCallback(std::move(events));
830+
RunLoopUntilIdle();
831+
832+
ASSERT_TRUE(pointers.has_value());
833+
ASSERT_EQ(pointers.value().size(), 1u);
834+
EXPECT_EQ(pointers.value()[0].change, flutter::PointerData::Change::kHover);
835+
EXPECT_EQ(pointers.value()[0].signal_kind,
836+
flutter::PointerData::SignalKind::kScroll);
837+
EXPECT_EQ(pointers.value()[0].kind, flutter::PointerData::DeviceKind::kMouse);
838+
EXPECT_EQ(pointers.value()[0].buttons, 0);
839+
EXPECT_EQ(pointers.value()[0].scroll_delta_x, 120);
840+
EXPECT_EQ(pointers.value()[0].scroll_delta_y, 0);
841+
pointers = {};
842+
}
843+
679844
} // namespace flutter_runner::testing

shell/platform/fuchsia/flutter/tests/pointer_event_utility.cc

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,30 @@ using fup_TouchIxnId = fuchsia::ui::pointer::TouchInteractionId;
1212
using fup_TouchIxnResult = fuchsia::ui::pointer::TouchInteractionResult;
1313
using fup_TouchPointerSample = fuchsia::ui::pointer::TouchPointerSample;
1414
using fup_ViewParameters = fuchsia::ui::pointer::ViewParameters;
15+
using fup_MouseEvent = fuchsia::ui::pointer::MouseEvent;
16+
using fup_MousePointerSample = fuchsia::ui::pointer::MousePointerSample;
17+
using fup_MouseDeviceInfo = fuchsia::ui::pointer::MouseDeviceInfo;
18+
19+
namespace {
20+
21+
fup_ViewParameters CreateViewParameters(
22+
std::array<std::array<float, 2>, 2> view,
23+
std::array<std::array<float, 2>, 2> viewport,
24+
std::array<float, 9> transform) {
25+
fup_ViewParameters params;
26+
fuchsia::ui::pointer::Rectangle view_rect;
27+
view_rect.min = view[0];
28+
view_rect.max = view[1];
29+
params.view = view_rect;
30+
fuchsia::ui::pointer::Rectangle viewport_rect;
31+
viewport_rect.min = viewport[0];
32+
viewport_rect.max = viewport[1];
33+
params.viewport = viewport_rect;
34+
params.viewport_to_view_transform = transform;
35+
return params;
36+
}
37+
38+
} // namespace
1539

1640
TouchEventBuilder TouchEventBuilder::New() {
1741
return TouchEventBuilder();
@@ -36,16 +60,8 @@ TouchEventBuilder& TouchEventBuilder::AddViewParameters(
3660
std::array<std::array<float, 2>, 2> view,
3761
std::array<std::array<float, 2>, 2> viewport,
3862
std::array<float, 9> transform) {
39-
params_ = std::make_optional<fup_ViewParameters>();
40-
fuchsia::ui::pointer::Rectangle view_rect;
41-
view_rect.min = view[0];
42-
view_rect.max = view[1];
43-
params_->view = view_rect;
44-
fuchsia::ui::pointer::Rectangle viewport_rect;
45-
viewport_rect.min = viewport[0];
46-
viewport_rect.max = viewport[1];
47-
params_->viewport = viewport_rect;
48-
params_->viewport_to_view_transform = transform;
63+
params_ = CreateViewParameters(std::move(view), std::move(viewport),
64+
std::move(transform));
4965
return *this;
5066
}
5167

@@ -77,4 +93,84 @@ std::vector<fup_TouchEvent> TouchEventBuilder::BuildAsVector() {
7793
return events;
7894
}
7995

96+
MouseEventBuilder MouseEventBuilder::New() {
97+
return MouseEventBuilder();
98+
}
99+
100+
MouseEventBuilder& MouseEventBuilder::AddTime(zx_time_t time) {
101+
time_ = time;
102+
return *this;
103+
}
104+
105+
MouseEventBuilder& MouseEventBuilder::AddSample(
106+
uint32_t id,
107+
std::array<float, 2> position,
108+
std::vector<uint8_t> pressed_buttons,
109+
std::array<int64_t, 2> scroll,
110+
std::array<int64_t, 2> scroll_in_physical_pixel,
111+
bool is_precision_scroll) {
112+
sample_ = std::make_optional<fup_MousePointerSample>();
113+
sample_->set_device_id(id);
114+
if (!pressed_buttons.empty()) {
115+
sample_->set_pressed_buttons(pressed_buttons);
116+
}
117+
sample_->set_position_in_viewport(position);
118+
if (scroll[0] != 0) {
119+
sample_->set_scroll_h(scroll[0]);
120+
}
121+
if (scroll[1] != 0) {
122+
sample_->set_scroll_v(scroll[1]);
123+
}
124+
if (scroll_in_physical_pixel[0] != 0) {
125+
sample_->set_scroll_h_physical_pixel(scroll_in_physical_pixel[0]);
126+
}
127+
if (scroll_in_physical_pixel[1] != 0) {
128+
sample_->set_scroll_v_physical_pixel(scroll_in_physical_pixel[1]);
129+
}
130+
sample_->set_is_precision_scroll(is_precision_scroll);
131+
return *this;
132+
}
133+
134+
MouseEventBuilder& MouseEventBuilder::AddViewParameters(
135+
std::array<std::array<float, 2>, 2> view,
136+
std::array<std::array<float, 2>, 2> viewport,
137+
std::array<float, 9> transform) {
138+
params_ = CreateViewParameters(std::move(view), std::move(viewport),
139+
std::move(transform));
140+
return *this;
141+
}
142+
143+
MouseEventBuilder& MouseEventBuilder::AddMouseDeviceInfo(
144+
uint32_t id,
145+
std::vector<uint8_t> buttons) {
146+
device_info_ = std::make_optional<fup_MouseDeviceInfo>();
147+
device_info_->set_id(id);
148+
device_info_->set_buttons(buttons);
149+
return *this;
150+
}
151+
152+
fup_MouseEvent MouseEventBuilder::Build() {
153+
fup_MouseEvent event;
154+
if (time_) {
155+
event.set_timestamp(time_.value());
156+
}
157+
if (params_) {
158+
event.set_view_parameters(std::move(params_.value()));
159+
}
160+
if (sample_) {
161+
event.set_pointer_sample(std::move(sample_.value()));
162+
}
163+
if (device_info_) {
164+
event.set_device_info(std::move(device_info_.value()));
165+
}
166+
event.set_trace_flow_id(123);
167+
return event;
168+
}
169+
170+
std::vector<fup_MouseEvent> MouseEventBuilder::BuildAsVector() {
171+
std::vector<fup_MouseEvent> events;
172+
events.emplace_back(Build());
173+
return events;
174+
}
175+
80176
} // namespace flutter_runner::testing

0 commit comments

Comments
 (0)