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

Commit b70e24b

Browse files
authored
Windows UWP: Add support for emulated mouse cursor for targets such as XBOX (#24698)
Adds an emulated mouse cursor for devices that don't typically have a traditional mouse. Enables mouse-like user interactions by using gamepad devices. flutter/flutter#76092 flutter/flutter#14967 Unit tests blocked by: flutter/flutter#70197 label added
1 parent 1c72318 commit b70e24b

File tree

10 files changed

+1002
-174
lines changed

10 files changed

+1002
-174
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,8 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plu
15041504
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
15051505
FILE: ../../../flutter/shell/platform/windows/cursor_handler.cc
15061506
FILE: ../../../flutter/shell/platform/windows/cursor_handler.h
1507+
FILE: ../../../flutter/shell/platform/windows/display_helper_winuwp.cc
1508+
FILE: ../../../flutter/shell/platform/windows/display_helper_winuwp.h
15071509
FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32.cc
15081510
FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32.h
15091511
FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32_unittests.cc
@@ -1529,6 +1531,10 @@ FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
15291531
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
15301532
FILE: ../../../flutter/shell/platform/windows/flutter_windows_win32.cc
15311533
FILE: ../../../flutter/shell/platform/windows/flutter_windows_winuwp.cc
1534+
FILE: ../../../flutter/shell/platform/windows/game_pad_cursor_winuwp.cc
1535+
FILE: ../../../flutter/shell/platform/windows/game_pad_cursor_winuwp.h
1536+
FILE: ../../../flutter/shell/platform/windows/game_pad_winuwp.cc
1537+
FILE: ../../../flutter/shell/platform/windows/game_pad_winuwp.h
15321538
FILE: ../../../flutter/shell/platform/windows/keyboard_handler_base.h
15331539
FILE: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.cc
15341540
FILE: ../../../flutter/shell/platform/windows/keyboard_key_channel_handler.h

shell/platform/windows/BUILD.gn

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,15 @@ source_set("flutter_windows_source") {
9393
# Target-specific sources.
9494
if (target_os == "winuwp") {
9595
sources += [
96+
"display_helper_winuwp.cc",
97+
"display_helper_winuwp.h",
9698
"flutter_window_winuwp.cc",
9799
"flutter_window_winuwp.h",
98100
"flutter_windows_winuwp.cc",
101+
"game_pad_cursor_winuwp.cc",
102+
"game_pad_cursor_winuwp.h",
103+
"game_pad_winuwp.cc",
104+
"game_pad_winuwp.h",
99105
"platform_handler_winuwp.cc",
100106
"platform_handler_winuwp.h",
101107
"system_utils_winuwp.cc",
@@ -146,7 +152,6 @@ source_set("flutter_windows_source") {
146152
defines = [
147153
"_SILENCE_CLANG_COROUTINE_MESSAGE",
148154
"FLUTTER_ENGINE_NO_PROTOTYPES",
149-
"USECOREWINDOW",
150155
]
151156
} else {
152157
defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ]
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/windows/display_helper_winuwp.h"
6+
7+
namespace flutter {
8+
9+
DisplayHelperWinUWP::DisplayHelperWinUWP() {
10+
current_display_info_ = winrt::Windows::Graphics::Display::
11+
DisplayInformation::GetForCurrentView();
12+
13+
ConfigureXboxSpecific();
14+
}
15+
16+
bool DisplayHelperWinUWP::IsRunningOnLargeScreenDevice() {
17+
return large_screen_device_;
18+
}
19+
20+
float DisplayHelperWinUWP::GetRenderTargetXOffset() {
21+
return render_target_x_offset_;
22+
}
23+
24+
float DisplayHelperWinUWP::GetRenderTargetYOffset() {
25+
return render_target_y_offset_;
26+
}
27+
28+
WindowBoundsWinUWP DisplayHelperWinUWP::GetPhysicalBounds() {
29+
return GetBounds(current_display_info_, true);
30+
}
31+
32+
WindowBoundsWinUWP DisplayHelperWinUWP::GetLogicalBounds() {
33+
return GetBounds(current_display_info_, false);
34+
}
35+
36+
WindowBoundsWinUWP DisplayHelperWinUWP::GetBounds(
37+
winrt::Windows::Graphics::Display::DisplayInformation const& disp,
38+
bool physical) {
39+
winrt::Windows::UI::ViewManagement::ApplicationView app_view =
40+
winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
41+
winrt::Windows::Foundation::Rect bounds = app_view.VisibleBounds();
42+
43+
if (large_screen_device_) {
44+
return {bounds.Width + (bounds.X), bounds.Height + (bounds.Y)};
45+
}
46+
47+
if (physical) {
48+
// Return the height in physical pixels
49+
return {bounds.Width * static_cast<float>(disp.RawPixelsPerViewPixel()),
50+
bounds.Height * static_cast<float>(disp.RawPixelsPerViewPixel())};
51+
}
52+
53+
return {bounds.Width, bounds.Height};
54+
}
55+
56+
void DisplayHelperWinUWP::ConfigureXboxSpecific() {
57+
bool running_on_xbox =
58+
winrt::Windows::System::Profile::AnalyticsInfo::VersionInfo()
59+
.DeviceFamily() == L"Windows.Xbox";
60+
61+
if (running_on_xbox) {
62+
large_screen_device_ = running_on_xbox;
63+
bool result =
64+
winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()
65+
.SetDesiredBoundsMode(winrt::Windows::UI::ViewManagement::
66+
ApplicationViewBoundsMode::UseCoreWindow);
67+
if (!result) {
68+
OutputDebugString(L"Couldn't set bounds mode.");
69+
}
70+
71+
winrt::Windows::UI::ViewManagement::ApplicationView app_view = winrt::
72+
Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
73+
winrt::Windows::Foundation::Rect bounds = app_view.VisibleBounds();
74+
75+
// The offset /2 represents how much off-screan the CoreWindow is
76+
// positioned.
77+
render_target_x_offset_ = bounds.X / 2;
78+
render_target_y_offset_ = bounds.Y / 2;
79+
}
80+
}
81+
82+
float DisplayHelperWinUWP::GetDpiScale() {
83+
double raw_per_view = current_display_info_.RawPixelsPerViewPixel();
84+
85+
// TODO(clarkezone): ensure DPI handling is correct:
86+
// because XBOX has display scaling off, logicalDpi retuns 96 which is
87+
// incorrect check if raw_per_view is more acurate.
88+
// Also confirm if it is necessary to use this workaround on 10X
89+
// https://github.com/flutter/flutter/issues/70198
90+
91+
if (large_screen_device_) {
92+
return 1.5;
93+
}
94+
return static_cast<float>(raw_per_view);
95+
}
96+
97+
} // namespace flutter
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_DISPLAY_HELPER_WINUWP_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_DISPLAY_HELPER_WINUWP_H_
7+
8+
#include <DispatcherQueue.h>
9+
#include <third_party/cppwinrt/generated/winrt/Windows.Graphics.Display.h>
10+
#include <third_party/cppwinrt/generated/winrt/Windows.System.Profile.h>
11+
#include <third_party/cppwinrt/generated/winrt/Windows.UI.Composition.h>
12+
#include <third_party/cppwinrt/generated/winrt/Windows.UI.Core.h>
13+
#include <third_party/cppwinrt/generated/winrt/Windows.UI.ViewManagement.Core.h>
14+
#include "third_party/cppwinrt/generated/winrt/Windows.System.Threading.h"
15+
16+
#include "flutter/shell/platform/windows/flutter_windows_view.h"
17+
#include "flutter/shell/platform/windows/game_pad_winuwp.h"
18+
19+
namespace flutter {
20+
21+
struct WindowBoundsWinUWP {
22+
float width;
23+
float height;
24+
};
25+
26+
// Helper that enables consumers to determine window bounds, DPI and some XBOX
27+
// specific characteristics in the case when the current application is running
28+
// on those devices.
29+
class DisplayHelperWinUWP {
30+
public:
31+
DisplayHelperWinUWP();
32+
33+
// physical = true
34+
// Returns with the physical bounds of the active window.
35+
WindowBoundsWinUWP GetPhysicalBounds();
36+
37+
// Returns with the logical bounds of the active window.
38+
WindowBoundsWinUWP GetLogicalBounds();
39+
40+
// Returns a bounds structure containing width and height information
41+
// for the backing CoreWindow in either view or physical pixels depending on
42+
// |physical|.
43+
WindowBoundsWinUWP GetBounds(
44+
winrt::Windows::Graphics::Display::DisplayInformation const& disp,
45+
bool physical);
46+
47+
// Returns a scaling factor representing the current DPI scale applied to the
48+
// backing CoreWindow.
49+
float GetDpiScale();
50+
51+
bool IsRunningOnLargeScreenDevice();
52+
53+
// Returns a value representing the overscan to correct for X.
54+
float GetRenderTargetXOffset();
55+
56+
// Returns a value representing the overscan to correct for Y.
57+
float GetRenderTargetYOffset();
58+
59+
private:
60+
// Test is current context is running on an xbox device and perform device
61+
// specific initialization.
62+
void ConfigureXboxSpecific();
63+
64+
// Most recent display information.
65+
winrt::Windows::Graphics::Display::DisplayInformation current_display_info_{
66+
nullptr};
67+
68+
// Is current context is executing on a large screen device.
69+
bool large_screen_device_ = false;
70+
71+
// Current X overscan compensation factor.
72+
float render_target_x_offset_ = 1.0f;
73+
74+
// Current Y overscan compensation factor.
75+
float render_target_y_offset_ = 1.0f;
76+
};
77+
} // namespace flutter
78+
79+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_DISPLAY_HELPER_WINUWP_H_

0 commit comments

Comments
 (0)