Commit 73ebda83 authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

Update CSS prefers-reduced-motion dynamically on Mac and Windows

Previously the content-side support for reduced motion for a frame was
static and would not react to changes in the system settings until you
created a new frame. This CL listens for notifications and recomputes
the webkit preferences when that happens (which then causes the new
prefers-reduced-motion value to be calculated).

This CL also introduces a caching mechanism for the system setting, to
avoid potentially expensive recomputation.

Test: Tested manually on MacOS and Windows devices.
Bug: 722548
Change-Id: I6be0822cc40a697a4373fbf53888d2219e5890f2
Reviewed-on: https://chromium-review.googlesource.com/c/1418498
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarStephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#628406}
parent b76ea80f
......@@ -10,10 +10,16 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "build/build_config.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_mode_observer.h"
#if defined(OS_WIN)
#include <memory>
#include "ui/gfx/win/singleton_hwnd_observer.h"
#endif
namespace content {
// The BrowserAccessibilityState class is used to determine if Chrome should be
......@@ -93,6 +99,11 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
bool disable_hot_tracking_;
#if defined(OS_WIN)
// Only used on Windows
std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
#endif
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityStateImpl);
};
......
......@@ -7,6 +7,8 @@
#import <Cocoa/Cocoa.h>
#include "base/metrics/histogram_macros.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "ui/gfx/animation/animation.h"
@interface NSWorkspace (Partials)
......@@ -23,7 +25,39 @@
namespace content {
void BrowserAccessibilityStateImpl::PlatformInitialize() {}
namespace {
void SetupAccessibilityDisplayOptionsNotifier() {
// We need to call into gfx::Animation and WebContentsImpl on the UI thread,
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (@available(macOS 10.10, *)) {
// Listen to accessibility display options changing, so that we can update
// the renderer for the prefers reduced motion settings.
//
// BrowserAccessibilityStateImpl is a deliberately leaked singleton, so we
// don't need to record the notification token for later cleanup.
[[[NSWorkspace sharedWorkspace] notificationCenter]
addObserverForName:
NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
gfx::Animation::UpdatePrefersReducedMotion();
for (WebContentsImpl* wc :
WebContentsImpl::GetAllWebContents()) {
wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
}
}];
}
}
} // namespace
void BrowserAccessibilityStateImpl::PlatformInitialize() {
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&SetupAccessibilityDisplayOptionsNotifier));
}
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
// NOTE: This function is running on the file thread.
......
......@@ -15,7 +15,9 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/gfx/animation/animation.h"
namespace content {
......@@ -67,11 +69,24 @@ class WindowsAccessibilityEnabler : public ui::IAccessible2UsageObserver {
bool acc_name_called_ = false;
};
void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (message == WM_SETTINGCHANGE && wparam == SPI_SETCLIENTAREAANIMATION) {
gfx::Animation::UpdatePrefersReducedMotion();
for (WebContentsImpl* wc : WebContentsImpl::GetAllWebContents()) {
wc->GetRenderViewHost()->OnWebkitPreferencesChanged();
}
}
}
} // namespace
void BrowserAccessibilityStateImpl::PlatformInitialize() {
ui::GetIAccessible2UsageObserverList().AddObserver(
new WindowsAccessibilityEnabler());
singleton_hwnd_observer_.reset(
new gfx::SingletonHwndObserver(base::BindRepeating(&OnWndProc)));
}
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
......
......@@ -4,6 +4,7 @@
#include "ui/gfx/animation/animation.h"
#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "ui/gfx/animation/animation_container.h"
#include "ui/gfx/animation/animation_delegate.h"
......@@ -16,6 +17,9 @@ namespace gfx {
Animation::RichAnimationRenderMode Animation::rich_animation_rendering_mode_ =
RichAnimationRenderMode::PLATFORM;
// static
base::Optional<bool> Animation::prefers_reduced_motion_;
Animation::Animation(base::TimeDelta timer_interval)
: timer_interval_(timer_interval),
is_animating_(false),
......@@ -107,20 +111,31 @@ bool Animation::ShouldRenderRichAnimationImpl() {
}
#endif
#if !defined(OS_WIN) && !defined(OS_MACOSX)
#if !defined(OS_WIN) && (!defined(OS_MACOSX) || defined(OS_IOS))
// static
bool Animation::ScrollAnimationsEnabledBySystem() {
// Defined in platform specific files for Windows and OSX.
return true;
}
bool Animation::PrefersReducedMotion() {
// static
void Animation::UpdatePrefersReducedMotion() {
// prefers_reduced_motion_ should only be modified on the UI thread.
// TODO(crbug.com/927163): DCHECK this assertion once tests are well-behaved.
// By default, we assume that animations are enabled, to avoid impacting the
// experience for users on systems that don't have APIs for reduced motion.
return false;
prefers_reduced_motion_ = false;
}
#endif
// static
bool Animation::PrefersReducedMotion() {
if (!prefers_reduced_motion_)
UpdatePrefersReducedMotion();
return *prefers_reduced_motion_;
}
bool Animation::ShouldSendCanceledFromStop() {
return false;
}
......
......@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "ui/gfx/animation/animation_container_element.h"
#include "ui/gfx/animation/animation_export.h"
......@@ -80,8 +81,9 @@ class ANIMATION_EXPORT Animation : public AnimationContainerElement {
static bool ScrollAnimationsEnabledBySystem();
// Determines whether the user desires reduced motion based on platform APIs.
// Should only be called from the browser process.
// Should only be called from the browser process, on the UI thread.
static bool PrefersReducedMotion();
static void UpdatePrefersReducedMotion();
protected:
// Invoked from Start to allow subclasses to prepare for the animation.
......@@ -128,6 +130,10 @@ class ANIMATION_EXPORT Animation : public AnimationContainerElement {
// Time we started at.
base::TimeTicks start_time_;
// Obtaining the PrefersReducedMotion system setting can be expensive, so it
// is cached in this boolean.
static base::Optional<bool> prefers_reduced_motion_;
DISALLOW_COPY_AND_ASSIGN(Animation);
};
......
......@@ -33,21 +33,18 @@ bool Animation::ScrollAnimationsEnabledBySystem() {
}
// static
bool Animation::PrefersReducedMotion() {
// Because of sandboxing, OS settings should only be queried from the browser
// process.
DCHECK(base::MessageLoopCurrentForUI::IsSet() ||
base::MessageLoopCurrentForIO::IsSet());
void Animation::UpdatePrefersReducedMotion() {
// prefers_reduced_motion_ should only be modified on the UI thread.
// TODO(crbug.com/927163): DCHECK this assertion once tests are well-behaved.
// We default to assuming that animations are enabled, to avoid impacting the
// experience for users on pre-10.12 systems.
bool prefers_reduced_motion = false;
prefers_reduced_motion_ = false;
SEL sel = @selector(accessibilityDisplayShouldReduceMotion);
if ([[NSWorkspace sharedWorkspace] respondsToSelector:sel]) {
prefers_reduced_motion =
prefers_reduced_motion_ =
[[NSWorkspace sharedWorkspace] accessibilityDisplayShouldReduceMotion];
}
return prefers_reduced_motion;
}
} // namespace gfx
......@@ -6,6 +6,8 @@
#include <windows.h>
#include "base/message_loop/message_loop.h"
namespace gfx {
// static
......@@ -24,12 +26,15 @@ bool Animation::ScrollAnimationsEnabledBySystem() {
}
// static
bool Animation::PrefersReducedMotion() {
void Animation::UpdatePrefersReducedMotion() {
// prefers_reduced_motion_ should only be modified on the UI thread.
// TODO(crbug.com/927163): DCHECK this assertion once tests are well-behaved.
// We default to assuming that animations are enabled, to avoid impacting the
// experience for users on systems that don't have SPI_GETCLIENTAREAANIMATION.
BOOL win_anim_enabled = true;
SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &win_anim_enabled, 0);
return !win_anim_enabled;
prefers_reduced_motion_ = !win_anim_enabled;
}
} // namespace gfx
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment