Bug 1744687 - Part 1. Lock orientation backend for Windows Tablet. r=gsvelto

Since Windows tablet mode has a orientation lock API, this patch
implements orientation lock backend for Windows tablet mode.

`GetAutoRotationState` API recognizes whether orientation API is supported on
the device. So this fix uses this API to check orientation API capability.

Differential Revision: https://phabricator.services.mozilla.com/D162451
This commit is contained in:
Makoto Kato 2022-11-24 15:10:15 +00:00
Родитель c14185f7cc
Коммит 3dbf8deeb8
6 изменённых файлов: 124 добавлений и 3 удалений

Просмотреть файл

@ -63,8 +63,8 @@ elif CONFIG["OS_TARGET"] == "Linux":
elif CONFIG["OS_TARGET"] == "WINNT":
REQUIRES_UNIFIED_BUILD = True
UNIFIED_SOURCES += [
"fallback/FallbackScreenConfiguration.cpp",
"fallback/FallbackVibration.cpp",
"windows/WindowsScreenConfiguration.cpp",
"windows/WindowsSensor.cpp",
]
# WindowsBattery.cpp cannot be built in unified mode because it relies on HalImpl.h.

Просмотреть файл

@ -0,0 +1,98 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/widget/ScreenManager.h"
#include "nsIWindowsUIUtils.h"
#include "WinUtils.h"
#include <windows.h>
namespace mozilla {
namespace hal_impl {
static decltype(SetDisplayAutoRotationPreferences)*
sSetDisplayAutoRotationPreferences = nullptr;
RefPtr<GenericNonExclusivePromise> LockScreenOrientation(
const hal::ScreenOrientation& aOrientation) {
// SetDisplayAutoRotationPreferences requires Win8, tablet mode and device
// support.
if (!IsWin8OrLater()) {
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
AR_STATE state;
if (!widget::WinUtils::GetAutoRotationState(&state)) {
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
if (state & (AR_DISABLED | AR_REMOTESESSION | AR_MULTIMON | AR_NOSENSOR |
AR_NOT_SUPPORTED | AR_LAPTOP | AR_DOCKED)) {
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
if (!sSetDisplayAutoRotationPreferences) {
HMODULE user32dll = GetModuleHandleW(L"user32.dll");
if (user32dll) {
sSetDisplayAutoRotationPreferences =
(decltype(SetDisplayAutoRotationPreferences)*)GetProcAddress(
user32dll, "SetDisplayAutoRotationPreferences");
}
if (!sSetDisplayAutoRotationPreferences) {
return GenericNonExclusivePromise::CreateAndReject(
NS_ERROR_DOM_NOT_SUPPORTED_ERR, __func__);
}
}
ORIENTATION_PREFERENCE orientation = ORIENTATION_PREFERENCE_NONE;
if (aOrientation == hal::ScreenOrientation::Default) {
// Actually, current screen is single and tablet mode according to
// GetAutoRotationState. So get primary screen data for natural orientation.
RefPtr<widget::Screen> screen =
widget::ScreenManager::GetSingleton().GetPrimaryScreen();
hal::ScreenOrientation defaultOrientation =
screen->GetDefaultOrientationType();
if (defaultOrientation == hal::ScreenOrientation::LandscapePrimary) {
orientation = ORIENTATION_PREFERENCE_LANDSCAPE;
} else {
orientation = ORIENTATION_PREFERENCE_PORTRAIT;
}
} else {
if (aOrientation & hal::ScreenOrientation::LandscapePrimary) {
orientation |= ORIENTATION_PREFERENCE_LANDSCAPE;
}
if (aOrientation & hal::ScreenOrientation::LandscapeSecondary) {
orientation |= ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
}
if (aOrientation & hal::ScreenOrientation::PortraitPrimary) {
orientation |= ORIENTATION_PREFERENCE_PORTRAIT;
}
if (aOrientation & hal::ScreenOrientation::PortraitSecondary) {
orientation |= ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
}
}
if (!sSetDisplayAutoRotationPreferences(orientation)) {
return GenericNonExclusivePromise::CreateAndReject(NS_ERROR_DOM_ABORT_ERR,
__func__);
}
return GenericNonExclusivePromise::CreateAndResolve(true, __func__);
}
void UnlockScreenOrientation() {
if (!sSetDisplayAutoRotationPreferences) {
return;
}
// This does nothing if the device doesn't support orientation lock
sSetDisplayAutoRotationPreferences(ORIENTATION_PREFERENCE_NONE);
}
} // namespace hal_impl
} // namespace mozilla

Просмотреть файл

@ -165,4 +165,18 @@ Screen::GetIsPseudoDisplay(bool* aIsPseudoDisplay) {
return NS_OK;
}
hal::ScreenOrientation Screen::GetDefaultOrientationType() const {
if (mRect.Width() >= mRect.Height()) {
if (mOrientationAngle == 0 || mOrientationAngle == 180) {
return hal::ScreenOrientation::LandscapePrimary;
}
return hal::ScreenOrientation::PortraitPrimary;
}
if (mOrientationAngle == 0 || mOrientationAngle == 180) {
return hal::ScreenOrientation::PortraitPrimary;
}
return hal::ScreenOrientation::LandscapePrimary;
}
} // namespace mozilla::widget

Просмотреть файл

@ -43,6 +43,12 @@ class Screen final : public nsIScreen {
return mScreenOrientation;
}
/**
* Return default orientation type that angle is 0.
* This returns LandscapePrimary or PortraitPrimary.
*/
hal::ScreenOrientation GetDefaultOrientationType() const;
float GetDPI() const { return mDPI; }
const LayoutDeviceIntRect& GetRect() const { return mRect; }

Просмотреть файл

@ -1525,7 +1525,8 @@ WinUtils::GetPowerPlatformRole() {
return power_determine_platform_role(POWER_PLATFORM_ROLE_V2);
}
static bool CallGetAutoRotationState(AR_STATE* aRotationState) {
// static
bool WinUtils::GetAutoRotationState(AR_STATE* aRotationState) {
typedef BOOL(WINAPI * GetAutoRotationStateFunc)(PAR_STATE pState);
static GetAutoRotationStateFunc get_auto_rotation_state_func =
reinterpret_cast<GetAutoRotationStateFunc>(::GetProcAddress(
@ -1564,7 +1565,7 @@ static bool IsTabletDevice() {
// 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) &&
if (WinUtils::GetAutoRotationState(&rotation_state) &&
(rotation_state & (AR_NOT_SUPPORTED | AR_LAPTOP | AR_NOSENSOR))) {
return false;
}

Просмотреть файл

@ -608,6 +608,8 @@ class WinUtils {
static nsresult RestoreHiDPIMode();
#endif
static bool GetAutoRotationState(AR_STATE* aRotationState);
private:
static WhitelistVec BuildWhitelist();