Bug 1035774 - Introduce functions to get the capabilities for the primary pointer and for all available pointers on Windows. r=masayuki

Note that the logic of IsTabletDevice() and relevant stuff are mostly a mimic of
IsTabletDevice [1] and IsDeviceUsedAsATablet [2] in chromium.

As for the primary pointer's capabilities, there seems no API to tell which
device is the primary, so here we determine it as following priorities;

1) if the machine is in tablet mode, the tablet (touch screen) is the primary
2) if the machine has a mouse, the mouse is the primary
3) if the machine has a digitizer, it's the primary

This priority is also the same as what chromium does in
GetPrimaryPointerType [2] and GetAvailablePointerTypes [3].

[1] d4c8983688/base/win/win_util.cc (450)
[2] d4c8983688/base/win/win_util.cc (468)
[3] d4c8983688/ui/base/touch/touch_device_win.cc (37)
[4] d4c8983688/ui/base/touch/touch_device_win.cc (82)

Differential Revision: https://phabricator.services.mozilla.com/D3300
This commit is contained in:
Thomas Wisniewski 2018-08-14 16:38:03 +09:00
parent d82fa0f0c9
commit fa9d7563e5
3 changed files with 138 additions and 5 deletions

View File

@ -24,6 +24,7 @@
#include "mozilla/WindowsVersion.h"
#include "mozilla/Unused.h"
#include "nsIContentPolicy.h"
#include "nsIWindowsUIUtils.h"
#include "nsContentUtils.h"
#include "mozilla/Logging.h"
@ -1802,6 +1803,120 @@ WinUtils::GetPowerPlatformRole()
return power_determine_platform_role(POWER_PLATFORM_ROLE_V2);
}
static bool
IsWindows10TabletMode()
{
nsCOMPtr<nsIWindowsUIUtils>
uiUtils(do_GetService("@mozilla.org/windows-ui-utils;1"));
if (NS_WARN_IF(!uiUtils)) {
return false;
}
bool isInTabletMode = false;
uiUtils->GetInTabletMode(&isInTabletMode);
return isInTabletMode;
}
static bool
CallGetAutoRotationState(AR_STATE* aRotationState)
{
typedef BOOL (WINAPI* GetAutoRotationStateFunc)(PAR_STATE pState);
static GetAutoRotationStateFunc get_auto_rotation_state_func =
reinterpret_cast<GetAutoRotationStateFunc>(::GetProcAddress(
GetModuleHandleW(L"user32.dll"), "GetAutoRotationState"));
if (get_auto_rotation_state_func) {
ZeroMemory(aRotationState, sizeof(AR_STATE));
return get_auto_rotation_state_func(aRotationState);
}
return false;
}
static bool
IsTabletDevice()
{
// Guarantees that:
// - The device has a touch screen.
// - It is used as a tablet which means that it has no keyboard connected.
// On Windows 10 it means that it is verifying with ConvertibleSlateMode.
if (!IsWin8OrLater()) {
return false;
}
if (IsWindows10TabletMode()) {
return true;
}
if (!GetSystemMetrics(SM_MAXIMUMTOUCHES)) {
return false;
}
// If the device is docked, the user is treating the device as a PC.
if (GetSystemMetrics(SM_SYSTEMDOCKED)) {
return false;
}
// If the device is not supporting rotation, it's unlikely to be a tablet,
// a convertible or a detachable. See:
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn629263(v=vs.85).aspx
AR_STATE rotation_state;
if (CallGetAutoRotationState(&rotation_state) &&
(rotation_state & (AR_NOT_SUPPORTED | AR_LAPTOP | AR_NOSENSOR))) {
return false;
}
// PlatformRoleSlate was added in Windows 8+.
POWER_PLATFORM_ROLE role = WinUtils::GetPowerPlatformRole();
if (role == PlatformRoleMobile || role == PlatformRoleSlate) {
return !GetSystemMetrics(SM_CONVERTIBLESLATEMODE);
}
return false;
}
static bool
IsMousePresent()
{
return ::GetSystemMetrics(SM_MOUSEPRESENT);
}
/* static */
PointerCapabilities
WinUtils::GetPrimaryPointerCapabilities()
{
if (IsTabletDevice()) {
return PointerCapabilities::Coarse;
}
if (IsMousePresent()) {
return PointerCapabilities::Fine|
PointerCapabilities::Hover;
}
if (IsTouchDeviceSupportPresent()) {
return PointerCapabilities::Coarse;
}
return PointerCapabilities::None;
}
/* static */
PointerCapabilities
WinUtils::GetAllPointerCapabilities()
{
PointerCapabilities result = PointerCapabilities::None;
if (IsTabletDevice() ||
IsTouchDeviceSupportPresent()) {
result |= PointerCapabilities::Coarse;
}
if (IsMousePresent()) {
result |= PointerCapabilities::Fine |
PointerCapabilities::Hover;
}
return result;
}
/* static */
bool
WinUtils::ResolveJunctionPointsAndSymLinks(std::wstring& aPath)

View File

@ -105,6 +105,7 @@ typedef DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContextProc)(DPI_AWA
typedef BOOL(WINAPI * EnableNonClientDpiScalingProc)(HWND);
namespace mozilla {
enum class PointerCapabilities : uint8_t;
#if defined(ACCESSIBILITY)
namespace a11y {
class Accessible;
@ -474,6 +475,11 @@ public:
*/
static POWER_PLATFORM_ROLE GetPowerPlatformRole();
// For pointer and hover media queries features.
static PointerCapabilities GetPrimaryPointerCapabilities();
// For any-pointer and any-hover media queries features.
static PointerCapabilities GetAllPointerCapabilities();
/**
* Fully resolves a path to its final path name. So if path contains
* junction points or symlinks to other folders, we'll resolve the path

View File

@ -609,11 +609,23 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult)
res = SystemWantsDarkTheme(aResult);
break;
case eIntID_PrefersReducedMotion: {
BOOL enableAnimation = TRUE;
::SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION,
0, &enableAnimation, 0);
aResult = enableAnimation ? 0 : 1;
break;
BOOL enableAnimation = TRUE;
::SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION,
0, &enableAnimation, 0);
aResult = enableAnimation ? 0 : 1;
break;
}
case eIntID_PrimaryPointerCapabilities: {
PointerCapabilities caps =
widget::WinUtils::GetPrimaryPointerCapabilities();
aResult = static_cast<int32_t>(caps);
break;
}
case eIntID_AllPointerCapabilities: {
PointerCapabilities caps =
widget::WinUtils::GetAllPointerCapabilities();
aResult = static_cast<int32_t>(caps);
break;
}
default:
aResult = 0;