Correct immersive mode gestures under rotation

This code does to things to make sure that immersive mode gestures operate
correctly regardless of the screen orientation. The first is to move the
registration of the filter to the root window, which guarantees that all of the
events will be seen by the filter.

The second change is to extend the bounds the filter is watching above by the
maximum bezel side. This makes sure that under rotation swipes that start on the
bezel are still handled.

BUG=241545, 244269
TEST=Rotated screen through all rotations and confirmed that swipe in/out works
     as expected in immersive mode.

Review URL: https://chromiumcodereview.appspot.com/15734011

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@203005 0039d316-1c4b-4281-b951-d872f2087c98
parent bcabac76
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/capture_client.h" #include "ui/aura/client/capture_client.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/screen.h" #include "ui/gfx/screen.h"
...@@ -295,45 +295,6 @@ void ImmersiveModeControllerAsh::AnchoredWidgetManager:: ...@@ -295,45 +295,6 @@ void ImmersiveModeControllerAsh::AnchoredWidgetManager::
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Observer to watch for window restore. views::Widget does not provide a hook
// to observe for window restore, so do this at the Aura level.
class ImmersiveModeControllerAsh::WindowObserver : public aura::WindowObserver {
public:
explicit WindowObserver(ImmersiveModeControllerAsh* controller)
: controller_(controller) {
controller_->native_window_->AddObserver(this);
}
virtual ~WindowObserver() {
controller_->native_window_->RemoveObserver(this);
}
// aura::WindowObserver overrides:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE {
using aura::client::kShowStateKey;
if (key == kShowStateKey) {
// Disable immersive mode when leaving the fullscreen state.
ui::WindowShowState show_state = static_cast<ui::WindowShowState>(
window->GetProperty(kShowStateKey));
if (controller_->IsEnabled() &&
show_state != ui::SHOW_STATE_FULLSCREEN &&
show_state != ui::SHOW_STATE_MINIMIZED) {
controller_->delegate_->FullscreenStateChanged();
}
return;
}
}
private:
ImmersiveModeControllerAsh* controller_; // Not owned.
DISALLOW_COPY_AND_ASSIGN(WindowObserver);
};
////////////////////////////////////////////////////////////////////////////////
ImmersiveModeControllerAsh::ImmersiveModeControllerAsh() ImmersiveModeControllerAsh::ImmersiveModeControllerAsh()
: delegate_(NULL), : delegate_(NULL),
widget_(NULL), widget_(NULL),
...@@ -543,7 +504,7 @@ void ImmersiveModeControllerAsh::OnGestureEvent(ui::GestureEvent* event) { ...@@ -543,7 +504,7 @@ void ImmersiveModeControllerAsh::OnGestureEvent(ui::GestureEvent* event) {
switch (event->type()) { switch (event->type()) {
case ui::ET_GESTURE_SCROLL_BEGIN: case ui::ET_GESTURE_SCROLL_BEGIN:
if (IsNearTopContainer(event->location())) { if (ShouldHandleEvent(event->location())) {
gesture_begun_ = true; gesture_begun_ = true;
event->SetHandled(); event->SetHandled();
} }
...@@ -615,6 +576,36 @@ void ImmersiveModeControllerAsh::OnImplicitAnimationsCompleted() { ...@@ -615,6 +576,36 @@ void ImmersiveModeControllerAsh::OnImplicitAnimationsCompleted() {
OnSlideClosedAnimationCompleted(); OnSlideClosedAnimationCompleted();
} }
////////////////////////////////////////////////////////////////////////////////
// aura::WindowObserver overrides:
void ImmersiveModeControllerAsh::OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) {
using aura::client::kShowStateKey;
if (key == kShowStateKey) {
// Disable immersive mode when leaving the fullscreen state.
ui::WindowShowState show_state = static_cast<ui::WindowShowState>(
window->GetProperty(kShowStateKey));
if (IsEnabled() &&
show_state != ui::SHOW_STATE_FULLSCREEN &&
show_state != ui::SHOW_STATE_MINIMIZED) {
delegate_->FullscreenStateChanged();
}
}
}
void ImmersiveModeControllerAsh::OnWindowAddedToRootWindow(
aura::Window* window) {
DCHECK_EQ(window, native_window_);
UpdatePreTargetHandler();
}
void ImmersiveModeControllerAsh::OnWindowRemovingFromRootWindow(
aura::Window* window) {
DCHECK_EQ(window, native_window_);
UpdatePreTargetHandler();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Testing interface: // Testing interface:
...@@ -661,13 +652,13 @@ void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) { ...@@ -661,13 +652,13 @@ void ImmersiveModeControllerAsh::EnableWindowObservers(bool enable) {
focus_manager->RemoveFocusChangeListener(this); focus_manager->RemoveFocusChangeListener(this);
} }
if (enable) UpdatePreTargetHandler();
native_window_->AddPreTargetHandler(this);
else
native_window_->RemovePreTargetHandler(this);
// The window observer adds and removes itself from the native window. if (enable) {
window_observer_.reset(enable ? new WindowObserver(this) : NULL); native_window_->AddObserver(this);
} else {
native_window_->RemoveObserver(this);
}
if (enable) { if (enable) {
registrar_.Add( registrar_.Add(
...@@ -1027,9 +1018,31 @@ ImmersiveModeControllerAsh::SwipeType ImmersiveModeControllerAsh::GetSwipeType( ...@@ -1027,9 +1018,31 @@ ImmersiveModeControllerAsh::SwipeType ImmersiveModeControllerAsh::GetSwipeType(
return SWIPE_NONE; return SWIPE_NONE;
} }
bool ImmersiveModeControllerAsh::IsNearTopContainer(gfx::Point location) const { bool ImmersiveModeControllerAsh::ShouldHandleEvent(
const gfx::Point& location) const {
// All of the gestures that are of interest start in a region with left &
// right edges agreeing with |top_container_|. When CLOSED it is difficult to
// hit the bounds due to small size of the tab strip, so the hit target needs
// to be extended on the bottom, thus the inset call. Finally there may be a
// bezel sensor off screen logically above |top_container_| thus the test
// needs to include gestures starting above.
gfx::Rect near_bounds = top_container_->GetTargetBoundsInScreen(); gfx::Rect near_bounds = top_container_->GetTargetBoundsInScreen();
if (reveal_state_ == CLOSED) if (reveal_state_ == CLOSED)
near_bounds.Inset(gfx::Insets(0, 0, -kNearTopContainerDistance, 0)); near_bounds.Inset(gfx::Insets(0, 0, -kNearTopContainerDistance, 0));
return near_bounds.Contains(location); return near_bounds.Contains(location) ||
((location.y() < near_bounds.y()) &&
(location.x() >= near_bounds.x()) &&
(location.x() <= near_bounds.right()));
}
void ImmersiveModeControllerAsh::UpdatePreTargetHandler() {
if (!native_window_)
return;
aura::RootWindow* root_window = native_window_->GetRootWindow();
if (!root_window)
return;
if (observers_enabled_)
root_window->AddPreTargetHandler(this);
else
root_window->RemovePreTargetHandler(this);
} }
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/timer.h" #include "base/timer.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "ui/aura/window_observer.h"
#include "ui/base/events/event_handler.h" #include "ui/base/events/event_handler.h"
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/views/focus/focus_manager.h" #include "ui/views/focus/focus_manager.h"
...@@ -40,7 +41,8 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController, ...@@ -40,7 +41,8 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController,
public ui::EventHandler, public ui::EventHandler,
public ui::ImplicitAnimationObserver, public ui::ImplicitAnimationObserver,
public views::FocusChangeListener, public views::FocusChangeListener,
public views::WidgetObserver { public views::WidgetObserver,
public aura::WindowObserver {
public: public:
ImmersiveModeControllerAsh(); ImmersiveModeControllerAsh();
virtual ~ImmersiveModeControllerAsh(); virtual ~ImmersiveModeControllerAsh();
...@@ -95,6 +97,13 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController, ...@@ -95,6 +97,13 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController,
// ui::ImplicitAnimationObserver override: // ui::ImplicitAnimationObserver override:
virtual void OnImplicitAnimationsCompleted() OVERRIDE; virtual void OnImplicitAnimationsCompleted() OVERRIDE;
// aura::WindowObserver overrides:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE;
virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE;
// Testing interface. // Testing interface.
void SetForceHideTabIndicatorsForTest(bool force); void SetForceHideTabIndicatorsForTest(bool force);
void StartRevealForTest(bool hovered); void StartRevealForTest(bool hovered);
...@@ -198,11 +207,16 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController, ...@@ -198,11 +207,16 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController,
SwipeType GetSwipeType(ui::GestureEvent* event) const; SwipeType GetSwipeType(ui::GestureEvent* event) const;
// True when |location| is "near" to the top container. When the top container // True when |location| is "near" to the top container. When the top container
// is not closed "near" means within the displayed bounds. When the top // is not closed "near" means within the displayed bounds or above it. When
// container is closed "near" means either within the displayed bounds or // the top container is closed "near" means either within the displayed
// within a few pixels of it. This allow the container to steal enough pixels // bounds, above it, or within a few pixels below it. This allow the container
// to detect a swipe in. // to steal enough pixels to detect a swipe in and handles the case that there
bool IsNearTopContainer(gfx::Point location) const; // is a bezel sensor above the top container.
bool ShouldHandleEvent(const gfx::Point& location) const;
// Call Add/RemovePreTargerHandler since either the RootWindow has changed or
// the enabled state of observing has changed.
void UpdatePreTargetHandler();
// Injected dependencies. Not owned. // Injected dependencies. Not owned.
Delegate* delegate_; Delegate* delegate_;
...@@ -239,13 +253,9 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController, ...@@ -239,13 +253,9 @@ class ImmersiveModeControllerAsh : public ImmersiveModeController,
// and the active widget. // and the active widget.
scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_; scoped_ptr<ImmersiveRevealedLock> focus_revealed_lock_;
// Native window for the browser, needed to clean up observers. // Native window for the browser.
aura::Window* native_window_; aura::Window* native_window_;
// Observer to disable immersive mode when window leaves the maximized state.
class WindowObserver;
scoped_ptr<WindowObserver> window_observer_;
// Manages widgets which are anchored to the top-of-window views. // Manages widgets which are anchored to the top-of-window views.
class AnchoredWidgetManager; class AnchoredWidgetManager;
scoped_ptr<AnchoredWidgetManager> anchored_widget_manager_; scoped_ptr<AnchoredWidgetManager> anchored_widget_manager_;
......
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