Bug 1907575 - Part 1: Add telemetry for pointing device existence r=win-reviewers,rkraesig,geckoview-reviewers,m_kato

For now this is Windows/Android only right now as we don't have the same set of detection used for IntID::AllPointerCapabilities on other platforms. That work can be done separately by e.g. bug 1874292.

Differential Revision: https://phabricator.services.mozilla.com/D216455
This commit is contained in:
Kagami Sascha Rosylight 2024-10-29 19:16:35 +00:00
parent ce9dae8aa7
commit f4de4250a4
10 changed files with 155 additions and 48 deletions

View File

@ -1394,6 +1394,58 @@ public class GeckoAppShell {
return result;
}
/*
* Keep in sync with PointingDevices in LookAndFeel.h
*/
private static final int POINTING_DEVICE_NONE = 0x00000000;
private static final int POINTING_DEVICE_MOUSE = 0x00000001;
private static final int POINTING_DEVICE_TOUCH = 0x00000002;
private static final int POINTING_DEVICE_PEN = 0x00000004;
private static int getPointingDeviceKinds(final InputDevice inputDevice) {
int result = POINTING_DEVICE_NONE;
final int sources = inputDevice.getSources();
// TODO(krosylight): For now this code is for telemetry purpose, but ultimately we want to
// replace the capabilities code above and move the capabilities computation into layout. We'll
// then have to add all the extra devices too that are not mouse/touch/pen. (Bug 1918207)
// We don't treat other devices properly for pointerType after all:
// https://searchfox.org/mozilla-central/rev/3b59c739df66574d94022a684596845cd05e7c65/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java#749-761
if (hasInputDeviceSource(sources, InputDevice.SOURCE_MOUSE)) {
result |= POINTING_DEVICE_MOUSE;
}
if (hasInputDeviceSource(sources, InputDevice.SOURCE_TOUCHSCREEN)) {
result |= POINTING_DEVICE_TOUCH;
}
if (hasInputDeviceSource(sources, InputDevice.SOURCE_STYLUS)) {
result |= POINTING_DEVICE_PEN;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& hasInputDeviceSource(sources, InputDevice.SOURCE_BLUETOOTH_STYLUS)) {
result |= POINTING_DEVICE_PEN;
}
return result;
}
@WrapForJNI(calledFrom = "gecko")
// For pointing devices telemetry.
private static int getPointingDeviceKinds() {
int result = POINTING_DEVICE_NONE;
for (final int deviceId : InputDevice.getDeviceIds()) {
final InputDevice inputDevice = InputDevice.getDevice(deviceId);
if (inputDevice == null || !InputDeviceUtils.isPointerTypeDevice(inputDevice)) {
continue;
}
result |= getPointingDeviceKinds(inputDevice);
}
return result;
}
private static boolean hasInputDeviceSource(final int sources, final int inputDeviceSource) {
return (sources & inputDeviceSource) == inputDeviceSource;
}

View File

@ -257,9 +257,19 @@ var dataProviders = {
try {
// Windows - Get info about attached pointing devices
data.pointingDevices = Services.sysinfo
.getProperty("pointingDevices")
.split(",");
data.pointingDevices = [];
if (Services.sysinfo.getProperty("hasMouse")) {
data.pointingDevices.push("pointing-device-mouse");
}
if (Services.sysinfo.getProperty("hasTouch")) {
data.pointingDevices.push("pointing-device-touchscreen");
}
if (Services.sysinfo.getProperty("hasPen")) {
data.pointingDevices.push("pointing-device-pen-digitizer");
}
if (!data.pointingDevices.length) {
data.pointingDevices.push("pointing-device-none");
}
} catch (e) {}
data.numTotalWindows = 0;

View File

@ -321,6 +321,13 @@ class LookAndFeel {
/* Whether macOS' full keyboard access is enabled */
FullKeyboardAccess,
// TODO(krosylight): This should ultimately be able to replace
// IntID::AllPointerCapabilities. (Bug 1918207)
//
// Note that PrimaryPointerCapabilities may not be replaceable as it has a
// bit more system specific heuristic, e.g. IsTabletMode on Windows.
PointingDeviceKinds,
/*
* Not an ID; used to define the range of valid IDs. Must be last.
*/
@ -389,6 +396,13 @@ class LookAndFeel {
using FontID = mozilla::StyleSystemFont;
enum class PointingDeviceKinds : uint8_t {
None = 0,
Mouse = 1 << 0,
Touch = 1 << 1,
Pen = 1 << 2,
};
static ColorScheme SystemColorScheme() {
return GetInt(IntID::SystemUsesDarkTheme) ? ColorScheme::Dark
: ColorScheme::Light;
@ -574,6 +588,8 @@ class LookAndFeel {
static bool sGlobalThemeChanged;
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LookAndFeel::PointingDeviceKinds);
} // namespace mozilla
// ---------------------------------------------------------------------

View File

@ -384,6 +384,10 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
aResult = 1;
break;
case IntID::PointingDeviceKinds:
aResult = java::GeckoAppShell::GetPointingDeviceKinds();
break;
default:
aResult = 0;
rv = NS_ERROR_FAILURE;

View File

@ -26,3 +26,20 @@ widget:
- cmccormack@mozilla.com
expires: never
telemetry_mirror: WIDGET_DARK_MODE
pointing_devices:
type: labeled_boolean
labels:
- mouse
- touch
- pen
description: >
Whether the system has any matching pointing device for each label.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1907575
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1907575
notification_emails:
- krosylight@mozilla.com
- dom-core@mozilla.com
expires: never

View File

@ -22,6 +22,7 @@
#include "SurfaceCacheUtils.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/glean/GleanMetrics.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/ServoStyleSet.h"
@ -192,6 +193,7 @@ static const char sIntPrefs[][45] = {
"ui.hideCursorWhileTyping",
"ui.gtkThemeFamily",
"ui.fullKeyboardAccess",
"ui.pointingDeviceKinds",
};
static_assert(std::size(sIntPrefs) == size_t(LookAndFeel::IntID::End),
@ -1166,6 +1168,19 @@ void nsXPLookAndFeel::RecordTelemetry() {
glean::widget::dark_mode.Set(
NS_SUCCEEDED(GetIntValue(IntID::SystemUsesDarkTheme, i)) && i != 0);
auto devices =
static_cast<PointingDeviceKinds>(GetInt(IntID::PointingDeviceKinds, 0));
glean::widget::pointing_devices
.EnumGet(glean::widget::PointingDevicesLabel::eMouse)
.Set(!!(devices & PointingDeviceKinds::Mouse));
glean::widget::pointing_devices
.EnumGet(glean::widget::PointingDevicesLabel::eTouch)
.Set(!!(devices & PointingDeviceKinds::Touch));
glean::widget::pointing_devices
.EnumGet(glean::widget::PointingDevicesLabel::ePen)
.Set(!!(devices & PointingDeviceKinds::Pen));
RecordLookAndFeelSpecificTelemetry();
}

View File

@ -1615,7 +1615,7 @@ static bool IsTabletDevice() {
return false;
}
static bool SystemHasMouse() {
bool WinUtils::SystemHasMouse() {
// As per MSDN, this value is rarely false because of virtual mice, and
// some machines report the existance of a mouse port as a mouse.
//
@ -1642,13 +1642,13 @@ PointerCapabilities WinUtils::GetPrimaryPointerCapabilities() {
return PointerCapabilities::None;
}
static bool SystemHasTouchscreen() {
bool WinUtils::SystemHasTouch() {
int digitizerMetrics = ::GetSystemMetrics(SM_DIGITIZER);
return (digitizerMetrics & NID_INTEGRATED_TOUCH) ||
(digitizerMetrics & NID_EXTERNAL_TOUCH);
}
static bool SystemHasPenDigitizer() {
bool WinUtils::SystemHasPen() {
int digitizerMetrics = ::GetSystemMetrics(SM_DIGITIZER);
return (digitizerMetrics & NID_INTEGRATED_PEN) ||
(digitizerMetrics & NID_EXTERNAL_PEN);
@ -1658,11 +1658,11 @@ static bool SystemHasPenDigitizer() {
PointerCapabilities WinUtils::GetAllPointerCapabilities() {
PointerCapabilities pointerCapabilities = PointerCapabilities::None;
if (SystemHasTouchscreen()) {
if (SystemHasTouch()) {
pointerCapabilities |= PointerCapabilities::Coarse;
}
if (SystemHasPenDigitizer() || SystemHasMouse()) {
if (SystemHasPen() || SystemHasMouse()) {
pointerCapabilities |=
PointerCapabilities::Fine | PointerCapabilities::Hover;
}
@ -1670,35 +1670,6 @@ PointerCapabilities WinUtils::GetAllPointerCapabilities() {
return pointerCapabilities;
}
void WinUtils::GetPointerExplanation(nsAString* aExplanation) {
// To support localization, we will return a comma-separated list of
// Fluent IDs
*aExplanation = u"pointing-device-none";
bool first = true;
auto append = [&](const char16_t* str) {
if (first) {
aExplanation->Truncate();
first = false;
} else {
aExplanation->Append(u",");
}
aExplanation->Append(str);
};
if (SystemHasTouchscreen()) {
append(u"pointing-device-touchscreen");
}
if (SystemHasPenDigitizer()) {
append(u"pointing-device-pen-digitizer");
}
if (SystemHasMouse()) {
append(u"pointing-device-mouse");
}
}
/* static */
bool WinUtils::ResolveJunctionPointsAndSymLinks(std::wstring& aPath) {
LOG_D("ResolveJunctionPointsAndSymLinks: Resolving path: %S", aPath.c_str());

View File

@ -463,9 +463,11 @@ class WinUtils {
static PointerCapabilities GetPrimaryPointerCapabilities();
// For any-pointer and any-hover media queries features.
static PointerCapabilities GetAllPointerCapabilities();
// Returns a string containing a comma-separated list of Fluent IDs
// representing the currently active pointing devices
static void GetPointerExplanation(nsAString* aExplanation);
// Returns whether the system has any active device for each pointer type.
static bool SystemHasMouse();
static bool SystemHasTouch();
static bool SystemHasPen();
/**
* Fully resolves a path to its final path name. So if path contains

View File

@ -600,6 +600,21 @@ nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
aResult = enable;
break;
}
case IntID::PointingDeviceKinds: {
LookAndFeel::PointingDeviceKinds result =
LookAndFeel::PointingDeviceKinds::None;
if (WinUtils::SystemHasMouse()) {
result |= LookAndFeel::PointingDeviceKinds::Mouse;
}
if (WinUtils::SystemHasTouch()) {
result |= LookAndFeel::PointingDeviceKinds::Touch;
}
if (WinUtils::SystemHasPen()) {
result |= LookAndFeel::PointingDeviceKinds::Pen;
}
aResult = static_cast<int32_t>(result);
break;
}
default:
aResult = 0;
res = NS_ERROR_FAILURE;

View File

@ -1460,15 +1460,20 @@ nsresult nsSystemInfo::Init() {
return rv;
}
if (XRE_IsParentProcess()) {
nsString pointerExplanation;
widget::WinUtils::GetPointerExplanation(&pointerExplanation);
rv = SetPropertyAsAString(u"pointingDevices"_ns, pointerExplanation);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
#endif
#if defined(XP_WIN) || defined(ANDROID)
// TODO(krosylight): Enable this on other platforms too when implemented
if (XRE_IsParentProcess()) {
auto kinds = static_cast<LookAndFeel::PointingDeviceKinds>(
LookAndFeel::GetInt(LookAndFeel::IntID::PointingDeviceKinds, 0));
MOZ_TRY(SetPropertyAsBool(
u"hasMouse"_ns, !!(kinds & LookAndFeel::PointingDeviceKinds::Mouse)));
MOZ_TRY(SetPropertyAsBool(
u"hasTouch"_ns, !!(kinds & LookAndFeel::PointingDeviceKinds::Touch)));
MOZ_TRY(SetPropertyAsBool(
u"hasPen"_ns, !!(kinds & LookAndFeel::PointingDeviceKinds::Pen)));
}
#endif
#if defined(XP_MACOSX)