diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-28 23:22:12 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-28 23:22:12 +0000 |
commit | 410af261442c970060db95c5a82ef44424179f6d (patch) | |
tree | 621c668d6c5d92d5608bb52adaa0298f8b9f7243 | |
parent | 5cc1b6590873a23e33a6a14ff8e992f3dba69679 (diff) | |
download | chromium_src-410af261442c970060db95c5a82ef44424179f6d.zip chromium_src-410af261442c970060db95c5a82ef44424179f6d.tar.gz chromium_src-410af261442c970060db95c5a82ef44424179f6d.tar.bz2 |
ash: Fix hit-testing when windows are in immersive fullscreen mode.
If a window is in an immersive fullscreen mode, then touch events towards the
top of the screen should not reach the child window, because the window can
consume the touch events, and in that case, the top-container of the window
cannot be revealed using touch-drag gesture.
The CL moves ResizeHandleWindowTargeter out of FrameBorderHitTestController
into its own file, and updates it so that it can be used for immersive mode
fullscreen windows in ImmersiveFullscreenController.
BUG=318879
R=jamescook@chromium.org, pkotwicz@chromium.org
Review URL: https://codereview.chromium.org/143453005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247518 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/ash.gyp | 2 | ||||
-rw-r--r-- | ash/ash_constants.cc | 2 | ||||
-rw-r--r-- | ash/ash_constants.h | 4 | ||||
-rw-r--r-- | ash/wm/custom_frame_view_ash.cc | 2 | ||||
-rw-r--r-- | ash/wm/frame_border_hit_test_controller.cc | 88 | ||||
-rw-r--r-- | ash/wm/immersive_fullscreen_controller.cc | 11 | ||||
-rw-r--r-- | ash/wm/immersive_fullscreen_controller_unittest.cc | 143 | ||||
-rw-r--r-- | ash/wm/resize_handle_window_targeter.cc | 99 | ||||
-rw-r--r-- | ash/wm/resize_handle_window_targeter.h | 56 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc | 25 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/immersive_mode_controller_ash.h | 7 | ||||
-rw-r--r-- | chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc | 73 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 3 |
13 files changed, 293 insertions, 222 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index b14c275..a8c2e59 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -543,6 +543,8 @@ 'wm/partial_screenshot_view.h', 'wm/power_button_controller.cc', 'wm/power_button_controller.h', + 'wm/resize_handle_window_targeter.cc', + 'wm/resize_handle_window_targeter.h', 'wm/resize_shadow.cc', 'wm/resize_shadow.h', 'wm/resize_shadow_controller.cc', diff --git a/ash/ash_constants.cc b/ash/ash_constants.cc index 82501f2..d8551d1 100644 --- a/ash/ash_constants.cc +++ b/ash/ash_constants.cc @@ -18,4 +18,6 @@ const SkColor kChromeOsBootColor = SkColorSetRGB(0xfe, 0xfe, 0xfe); const SkColor kFocusBorderColor = SkColorSetRGB(64, 128, 250); +const int kImmersiveFullscreenTopEdgeInset = 8; + } // namespace ash diff --git a/ash/ash_constants.h b/ash/ash_constants.h index cad4354..f139032 100644 --- a/ash/ash_constants.h +++ b/ash/ash_constants.h @@ -33,6 +33,10 @@ extern const SkColor kChromeOsBootColor; // The border color of keyboard focus for launcher items and system tray. extern const SkColor kFocusBorderColor; +// How many pixels are reserved for touch-events towards the top of an +// immersive-fullscreen window. +extern const int kImmersiveFullscreenTopEdgeInset; + } // namespace ash #endif // ASH_ASH_CONSTANTS_H_ diff --git a/ash/wm/custom_frame_view_ash.cc b/ash/wm/custom_frame_view_ash.cc index 50e9e23..5b8a36c 100644 --- a/ash/wm/custom_frame_view_ash.cc +++ b/ash/wm/custom_frame_view_ash.cc @@ -394,7 +394,7 @@ CustomFrameViewAsh::CustomFrameViewAsh(views::Widget* frame) if (!window_state->HasDelegate()) { window_state->SetDelegate(scoped_ptr<wm::WindowStateDelegate>( new CustomFrameViewAshWindowStateDelegate( - window_state, this)).Pass()); + window_state, this))); } } diff --git a/ash/wm/frame_border_hit_test_controller.cc b/ash/wm/frame_border_hit_test_controller.cc index 5504d2a..0b730fb 100644 --- a/ash/wm/frame_border_hit_test_controller.cc +++ b/ash/wm/frame_border_hit_test_controller.cc @@ -6,7 +6,7 @@ #include "ash/ash_constants.h" #include "ash/wm/header_painter.h" -#include "ash/wm/window_state.h" +#include "ash/wm/resize_handle_window_targeter.h" #include "ash/wm/window_state_observer.h" #include "ui/aura/env.h" #include "ui/aura/window.h" @@ -19,90 +19,6 @@ namespace ash { -namespace { - -// To allow easy resize, the resize handles should slightly overlap the content -// area of non-maximized and non-fullscreen windows. -class ResizeHandleWindowTargeter : public wm::WindowStateObserver, - public aura::WindowObserver, - public aura::WindowTargeter { - public: - explicit ResizeHandleWindowTargeter(aura::Window* window) - : window_(window) { - wm::WindowState* window_state = wm::GetWindowState(window_); - OnWindowShowTypeChanged(window_state, wm::SHOW_TYPE_DEFAULT); - window_state->AddObserver(this); - window_->AddObserver(this); - } - - virtual ~ResizeHandleWindowTargeter() { - if (window_) { - window_->RemoveObserver(this); - wm::GetWindowState(window_)->RemoveObserver(this); - } - } - - private: - // wm::WindowStateObserver: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE { - if (window_state->IsMaximizedOrFullscreen()) { - frame_border_inset_ = gfx::Insets(); - } else { - frame_border_inset_ = gfx::Insets(kResizeInsideBoundsSize, - kResizeInsideBoundsSize, - kResizeInsideBoundsSize, - kResizeInsideBoundsSize); - } - } - - // aura::WindowObserver: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { - CHECK_EQ(window_, window); - wm::GetWindowState(window_)->RemoveObserver(this); - window_ = NULL; - } - - // aura::WindowTargeter: - virtual ui::EventTarget* FindTargetForLocatedEvent( - ui::EventTarget* root, - ui::LocatedEvent* event) OVERRIDE { - // If the event falls very close to the inside of the frame border, then - // target the window itself, so that the window can be resized easily. - aura::Window* window = static_cast<aura::Window*>(root); - if (window == window_ && !frame_border_inset_.empty()) { - gfx::Rect bounds = gfx::Rect(window_->bounds().size()); - bounds.Inset(frame_border_inset_); - if (!bounds.Contains(event->location())) - return window_; - } - return aura::WindowTargeter::FindTargetForLocatedEvent(root, event); - } - - virtual bool SubtreeShouldBeExploredForEvent( - ui::EventTarget* target, - const ui::LocatedEvent& event) OVERRIDE { - if (target == window_) { - // Defer to the parent's targeter on whether |window_| should be able to - // receive the event. - ui::EventTarget* parent = target->GetParentTarget(); - if (parent) { - ui::EventTargeter* targeter = parent->GetEventTargeter(); - if (targeter) - return targeter->SubtreeShouldBeExploredForEvent(target, event); - } - } - return aura::WindowTargeter::SubtreeShouldBeExploredForEvent(target, event); - } - - aura::Window* window_; - gfx::Insets frame_border_inset_; - - DISALLOW_COPY_AND_ASSIGN(ResizeHandleWindowTargeter); -}; - -} // namespace - FrameBorderHitTestController::FrameBorderHitTestController(views::Widget* frame) : frame_window_(frame->GetNativeWindow()) { gfx::Insets mouse_outer_insets(-kResizeOutsideBoundsSize, @@ -116,7 +32,7 @@ FrameBorderHitTestController::FrameBorderHitTestController(views::Widget* frame) touch_outer_insets); frame_window_->set_event_targeter(scoped_ptr<ui::EventTargeter>( - new ResizeHandleWindowTargeter(frame_window_))); + new ResizeHandleWindowTargeter(frame_window_, NULL))); } FrameBorderHitTestController::~FrameBorderHitTestController() { diff --git a/ash/wm/immersive_fullscreen_controller.cc b/ash/wm/immersive_fullscreen_controller.cc index b31c8b8..92697ed 100644 --- a/ash/wm/immersive_fullscreen_controller.cc +++ b/ash/wm/immersive_fullscreen_controller.cc @@ -6,7 +6,9 @@ #include <set> +#include "ash/ash_constants.h" #include "ash/shell.h" +#include "ash/wm/resize_handle_window_targeter.h" #include "ash/wm/window_state.h" #include "base/metrics/histogram.h" #include "ui/aura/client/activation_client.h" @@ -49,11 +51,6 @@ const int kMouseRevealDelayMs = 200; // without holding the cursor completely still. const int kMouseRevealXThresholdPixels = 3; -// How many pixels a gesture can start away from |top_container_| when in -// closed state and still be considered near it. This is needed to overcome -// issues with poor location values near the edge of the display. -const int kNearTopContainerDistance = 8; - // Used to multiply x value of an update in check to determine if gesture is // vertical. This is used to make sure that gesture is close to vertical instead // of just more vertical then horizontal. @@ -258,6 +255,8 @@ void ImmersiveFullscreenController::Init(Delegate* delegate, top_container_ = top_container; widget_ = widget; native_window_ = widget_->GetNativeWindow(); + native_window_->set_event_targeter(scoped_ptr<ui::EventTargeter>( + new ResizeHandleWindowTargeter(native_window_, this))); } void ImmersiveFullscreenController::SetEnabled(WindowType window_type, @@ -901,7 +900,7 @@ bool ImmersiveFullscreenController::ShouldHandleGestureEvent( // When the top-of-window views are not fully revealed, handle gestures which // start in the top few pixels of the screen. gfx::Rect hit_bounds_in_screen(GetDisplayBoundsInScreen(native_window_)); - hit_bounds_in_screen.set_height(kNearTopContainerDistance); + hit_bounds_in_screen.set_height(kImmersiveFullscreenTopEdgeInset); if (hit_bounds_in_screen.Contains(location)) return true; diff --git a/ash/wm/immersive_fullscreen_controller_unittest.cc b/ash/wm/immersive_fullscreen_controller_unittest.cc index 3172034..ef0a605 100644 --- a/ash/wm/immersive_fullscreen_controller_unittest.cc +++ b/ash/wm/immersive_fullscreen_controller_unittest.cc @@ -15,9 +15,13 @@ #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/test/event_generator.h" +#include "ui/aura/test/test_event_handler.h" +#include "ui/aura/test/test_window_delegate.h" #include "ui/aura/window.h" +#include "ui/events/event_utils.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/views/bubble/bubble_delegate.h" +#include "ui/views/controls/native/native_view_host.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -75,6 +79,21 @@ class MockImmersiveFullscreenControllerDelegate DISALLOW_COPY_AND_ASSIGN(MockImmersiveFullscreenControllerDelegate); }; +class ConsumeEventHandler : public aura::test::TestEventHandler { + public: + ConsumeEventHandler() {} + virtual ~ConsumeEventHandler() {} + + private: + virtual void OnEvent(ui::Event* event) OVERRIDE { + aura::test::TestEventHandler::OnEvent(event); + if (event->cancelable()) + event->SetHandled(); + } + + DISALLOW_COPY_AND_ASSIGN(ConsumeEventHandler); +}; + } // namespace ///////////////////////////////////////////////////////////////////////////// @@ -83,21 +102,30 @@ class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { public: enum Modality { MODALITY_MOUSE, - MODALITY_TOUCH, - MODALITY_GESTURE + MODALITY_GESTURE_TAP, + MODALITY_GESTURE_SCROLL }; - ImmersiveFullscreenControllerTest() : widget_(NULL), top_container_(NULL) {} + ImmersiveFullscreenControllerTest() + : widget_(NULL), + top_container_(NULL), + content_view_(NULL) {} virtual ~ImmersiveFullscreenControllerTest() {} ImmersiveFullscreenController* controller() { return controller_.get(); } + views::NativeViewHost* content_view() { + return content_view_; + } + views::View* top_container() { return top_container_; } + views::Widget* widget() { return widget_; } + aura::Window* window() { return widget_->GetNativeWindow(); } @@ -127,9 +155,14 @@ class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); + gfx::Size window_size = widget_->GetWindowBoundsInScreen().size(); + content_view_ = new views::NativeViewHost(); + content_view_->SetBounds(0, 0, window_size.width(), window_size.height()); + widget_->GetContentsView()->AddChildView(content_view_); + top_container_ = new views::View(); top_container_->SetBounds( - 0, 0, widget_->GetWindowBoundsInScreen().width(), 100); + 0, 0, window_size.width(), 100); top_container_->SetFocusable(true); widget_->GetContentsView()->AddChildView(top_container_); @@ -152,7 +185,7 @@ class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { // Attempt to reveal the top-of-window views via |modality|. // The top-of-window views can only be revealed via mouse hover or a gesture. void AttemptReveal(Modality modality) { - ASSERT_NE(modality, MODALITY_TOUCH); + ASSERT_NE(modality, MODALITY_GESTURE_TAP); AttemptRevealStateChange(true, modality); } @@ -196,22 +229,25 @@ class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { MoveMouse(event_position.x(), event_position.y()); break; } - case MODALITY_TOUCH: { + case MODALITY_GESTURE_TAP: { gfx::Point screen_position = event_position; views::View::ConvertPointToScreen(top_container_, &screen_position); - aura::test::EventGenerator& event_generator(GetEventGenerator()); event_generator.MoveTouch(event_position); event_generator.PressTouch(); event_generator.ReleaseTouch(); break; } - case MODALITY_GESTURE: { - aura::client::GetCursorClient(CurrentContext())->DisableMouseEvents(); - ImmersiveFullscreenController::SwipeType swipe_type = revealed ? - ImmersiveFullscreenController::SWIPE_OPEN : - ImmersiveFullscreenController::SWIPE_CLOSE; - controller_->UpdateRevealedLocksForSwipe(swipe_type); + case MODALITY_GESTURE_SCROLL: { + gfx::Point start(0, revealed ? 0 : top_container_->height() - 2); + gfx::Vector2d scroll_delta(0, 40); + gfx::Point end = revealed ? start + scroll_delta : start - scroll_delta; + views::View::ConvertPointToScreen(top_container_, &start); + views::View::ConvertPointToScreen(top_container_, &end); + aura::test::EventGenerator& event_generator(GetEventGenerator()); + event_generator.GestureScrollSequence( + start, end, + base::TimeDelta::FromMilliseconds(30), 1); break; } } @@ -220,7 +256,8 @@ class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase { scoped_ptr<ImmersiveFullscreenController> controller_; scoped_ptr<MockImmersiveFullscreenControllerDelegate> delegate_; views::Widget* widget_; // Owned by the native widget. - views::View* top_container_; // Owned by |root_view_|. + views::View* top_container_; // Owned by |widget_|'s root-view. + views::NativeViewHost* content_view_; // Owned by |widget_|'s root-view. DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenControllerTest); }; @@ -615,7 +652,7 @@ TEST_F(ImmersiveFullscreenControllerTest, DifferentModalityEnterExit) { EXPECT_FALSE(controller()->IsRevealed()); // Initiate reveal via gesture, end reveal via mouse. - AttemptReveal(MODALITY_GESTURE); + AttemptReveal(MODALITY_GESTURE_SCROLL); EXPECT_TRUE(controller()->IsRevealed()); MoveMouse(1, 1); EXPECT_TRUE(controller()->IsRevealed()); @@ -623,21 +660,21 @@ TEST_F(ImmersiveFullscreenControllerTest, DifferentModalityEnterExit) { EXPECT_FALSE(controller()->IsRevealed()); // Initiate reveal via gesture, end reveal via touch. - AttemptReveal(MODALITY_GESTURE); + AttemptReveal(MODALITY_GESTURE_SCROLL); EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_TOUCH); + AttemptUnreveal(MODALITY_GESTURE_TAP); EXPECT_FALSE(controller()->IsRevealed()); // Initiate reveal via mouse, end reveal via gesture. AttemptReveal(MODALITY_MOUSE); EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); + AttemptUnreveal(MODALITY_GESTURE_SCROLL); EXPECT_FALSE(controller()->IsRevealed()); // Initiate reveal via mouse, end reveal via touch. AttemptReveal(MODALITY_MOUSE); EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_TOUCH); + AttemptUnreveal(MODALITY_GESTURE_TAP); EXPECT_FALSE(controller()->IsRevealed()); } @@ -652,7 +689,7 @@ TEST_F(ImmersiveFullscreenControllerTest, EndRevealViaGesture) { AttemptReveal(MODALITY_MOUSE); top_container()->RequestFocus(); EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); + AttemptUnreveal(MODALITY_GESTURE_SCROLL); EXPECT_FALSE(controller()->IsRevealed()); // The top-of-window views should no longer have focus. Clearing focus is @@ -666,12 +703,76 @@ TEST_F(ImmersiveFullscreenControllerTest, EndRevealViaGesture) { scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock( ImmersiveFullscreenController::ANIMATE_REVEAL_NO)); EXPECT_TRUE(controller()->IsRevealed()); - AttemptUnreveal(MODALITY_GESTURE); + AttemptUnreveal(MODALITY_GESTURE_SCROLL); EXPECT_TRUE(controller()->IsRevealed()); lock.reset(); EXPECT_FALSE(controller()->IsRevealed()); } +// Tests that touch-gesture can be used to reveal the top-of-window views when +// the child window consumes all events. +TEST_F(ImmersiveFullscreenControllerTest, RevealViaGestureChildConsumesEvents) { + // Enabling initially hides the top views. + SetEnabled(true); + EXPECT_TRUE(controller()->IsEnabled()); + EXPECT_FALSE(controller()->IsRevealed()); + + aura::test::TestWindowDelegate child_delegate; + scoped_ptr<aura::Window> child( + CreateTestWindowInShellWithDelegateAndType(&child_delegate, + ui::wm::WINDOW_TYPE_CONTROL, + 1234, + gfx::Rect())); + content_view()->Attach(child.get()); + child->Show(); + + ConsumeEventHandler handler; + child->AddPreTargetHandler(&handler); + + // Reveal the top views using a touch-scroll gesture. The child window should + // not receive the touch events. + AttemptReveal(MODALITY_GESTURE_SCROLL); + EXPECT_TRUE(controller()->IsRevealed()); + EXPECT_EQ(0, handler.num_touch_events()); + + AttemptUnreveal(MODALITY_GESTURE_TAP); + EXPECT_FALSE(controller()->IsRevealed()); + EXPECT_GT(handler.num_touch_events(), 0); + child->RemovePreTargetHandler(&handler); +} + +// Make sure touch events towards the top of the window do not leak through to +// windows underneath. +TEST_F(ImmersiveFullscreenControllerTest, EventsDoNotLeakToWindowUnderneath) { + gfx::Rect window_bounds = window()->GetBoundsInScreen(); + aura::test::TestWindowDelegate child_delegate; + scoped_ptr<aura::Window> behind(CreateTestWindowInShellWithDelegate( + &child_delegate, 1234, window_bounds)); + behind->Show(); + behind->SetBounds(window_bounds); + widget()->StackAbove(behind.get()); + + // Make sure the windows are aligned on top. + EXPECT_EQ(behind->GetBoundsInScreen().y(), window()->GetBoundsInScreen().y()); + int top = behind->GetBoundsInScreen().y(); + + ui::TouchEvent touch(ui::ET_TOUCH_MOVED, gfx::Point(10, top), 0, + ui::EventTimeForNow()); + ui::EventTarget* root = window()->GetRootWindow(); + ui::EventTargeter* targeter = root->GetEventTargeter(); + EXPECT_EQ(window(), targeter->FindTargetForEvent(root, &touch)); + + SetEnabled(true); + EXPECT_FALSE(controller()->IsRevealed()); + // Make sure the windows are still aligned on top. + EXPECT_EQ(behind->GetBoundsInScreen().y(), window()->GetBoundsInScreen().y()); + top = behind->GetBoundsInScreen().y(); + ui::TouchEvent touch2(ui::ET_TOUCH_MOVED, gfx::Point(10, top), 0, + ui::EventTimeForNow()); + // The event should still be targeted to window(). + EXPECT_EQ(window(), targeter->FindTargetForEvent(root, &touch2)); +} + // Do not test under windows because focus testing is not reliable on // Windows. (crbug.com/79493) #if !defined(OS_WIN) diff --git a/ash/wm/resize_handle_window_targeter.cc b/ash/wm/resize_handle_window_targeter.cc new file mode 100644 index 0000000..144e0fd --- /dev/null +++ b/ash/wm/resize_handle_window_targeter.cc @@ -0,0 +1,99 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/resize_handle_window_targeter.h" + +#include "ash/ash_constants.h" +#include "ash/wm/immersive_fullscreen_controller.h" +#include "ash/wm/window_state.h" +#include "ui/aura/window.h" + +namespace ash { + +ResizeHandleWindowTargeter::ResizeHandleWindowTargeter( + aura::Window* window, + ImmersiveFullscreenController* controller) + : window_(window), + immersive_controller_(controller) { + wm::WindowState* window_state = wm::GetWindowState(window_); + OnWindowShowTypeChanged(window_state, wm::SHOW_TYPE_DEFAULT); + window_state->AddObserver(this); + window_->AddObserver(this); +} + +ResizeHandleWindowTargeter::~ResizeHandleWindowTargeter() { + if (window_) { + window_->RemoveObserver(this); + wm::GetWindowState(window_)->RemoveObserver(this); + } +} + +void ResizeHandleWindowTargeter::OnWindowShowTypeChanged( + wm::WindowState* window_state, + wm::WindowShowType old_type) { + if (window_state->IsMaximizedOrFullscreen()) { + frame_border_inset_ = gfx::Insets(); + } else { + frame_border_inset_ = gfx::Insets(kResizeInsideBoundsSize, + kResizeInsideBoundsSize, + kResizeInsideBoundsSize, + kResizeInsideBoundsSize); + } +} + +void ResizeHandleWindowTargeter::OnWindowDestroying(aura::Window* window) { + CHECK_EQ(window_, window); + wm::GetWindowState(window_)->RemoveObserver(this); + window_ = NULL; +} + +ui::EventTarget* ResizeHandleWindowTargeter::FindTargetForLocatedEvent( + ui::EventTarget* root, + ui::LocatedEvent* event) { + aura::Window* window = static_cast<aura::Window*>(root); + if (window == window_) { + gfx::Insets insets; + if (immersive_controller_ && immersive_controller_->IsEnabled() && + !immersive_controller_->IsRevealed() && + event->IsTouchEvent()) { + // If the window is in immersive fullscreen, and top-of-window views are + // not revealed, then touch events towards the top of the window + // should not reach the child window so that touch gestures can be used to + // reveal the top-of-windows views. This is needed because the child + // window may consume touch events and prevent touch-scroll gesture from + // being generated. + insets = gfx::Insets(kImmersiveFullscreenTopEdgeInset, 0, 0, 0); + } else { + // If the event falls very close to the inside of the frame border, then + // target the window itself, so that the window can be resized easily. + insets = frame_border_inset_; + } + + if (!insets.empty()) { + gfx::Rect bounds = gfx::Rect(window_->bounds().size()); + bounds.Inset(insets); + if (!bounds.Contains(event->location())) + return window_; + } + } + return aura::WindowTargeter::FindTargetForLocatedEvent(root, event); +} + +bool ResizeHandleWindowTargeter::SubtreeShouldBeExploredForEvent( + ui::EventTarget* target, + const ui::LocatedEvent& event) { + if (target == window_) { + // Defer to the parent's targeter on whether |window_| should be able to + // receive the event. + ui::EventTarget* parent = target->GetParentTarget(); + if (parent) { + ui::EventTargeter* targeter = parent->GetEventTargeter(); + if (targeter) + return targeter->SubtreeShouldBeExploredForEvent(target, event); + } + } + return aura::WindowTargeter::SubtreeShouldBeExploredForEvent(target, event); +} + +} // namespace ash diff --git a/ash/wm/resize_handle_window_targeter.h b/ash/wm/resize_handle_window_targeter.h new file mode 100644 index 0000000..828d2fc --- /dev/null +++ b/ash/wm/resize_handle_window_targeter.h @@ -0,0 +1,56 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_RESIZE_HANDLE_WINDOW_TARGETER_H_ +#define ASH_WM_RESIZE_HANDLE_WINDOW_TARGETER_H_ + +#include "ash/wm/window_state_observer.h" +#include "ui/aura/window_observer.h" +#include "ui/aura/window_targeter.h" +#include "ui/gfx/geometry/insets.h" + +namespace ash { + +class ImmersiveFullscreenController; + +// To allow easy resize, the resize handles should slightly overlap the content +// area of non-maximized and non-fullscreen windows. For immersive fullscreen +// windows, this targeter makes sure that touch-events towards the top of the +// screen are targeted to the window itself (instead of a child window that may +// otherwise have been targeted) when the top-of-window views are not revealed. +class ResizeHandleWindowTargeter : public wm::WindowStateObserver, + public aura::WindowObserver, + public aura::WindowTargeter { + public: + ResizeHandleWindowTargeter(aura::Window* window, + ImmersiveFullscreenController* immersive); + virtual ~ResizeHandleWindowTargeter(); + + private: + // wm::WindowStateObserver: + virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, + wm::WindowShowType old_type) OVERRIDE; + // aura::WindowObserver: + virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; + + // aura::WindowTargeter: + virtual ui::EventTarget* FindTargetForLocatedEvent( + ui::EventTarget* root, + ui::LocatedEvent* event) OVERRIDE; + virtual bool SubtreeShouldBeExploredForEvent( + ui::EventTarget* target, + const ui::LocatedEvent& event) OVERRIDE; + + // The targeter does not take ownership of |window_| or + // |immersive_controller_|. + aura::Window* window_; + gfx::Insets frame_border_inset_; + ImmersiveFullscreenController* immersive_controller_; + + DISALLOW_COPY_AND_ASSIGN(ResizeHandleWindowTargeter); +}; + +} // namespace ash + +#endif // ASH_WM_RESIZE_HANDLE_WINDOW_TARGETER_H_ diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc index 8880b27b..adb88d4 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc @@ -26,12 +26,6 @@ namespace { // "pop" as the 3-pixel tall "light bar" style tab strip becomes visible. const int kAnimationOffsetY = 3; -// The height of the region in pixels at the top edge of the screen in which to -// steal touch events targetted at the web contents while in immersive -// fullscreen. This region is used to allow us to get edge gestures even if the -// web contents consumes all touch events. -const int kStealTouchEventsFromWebContentsRegionHeightPx = 8; - // Converts from ImmersiveModeController::AnimateReveal to // ash::ImmersiveFullscreenController::AnimateReveal. ash::ImmersiveFullscreenController::AnimateReveal @@ -153,21 +147,6 @@ void ImmersiveModeControllerAsh::LayoutBrowserRootView() { widget->GetRootView()->Layout(); } -void ImmersiveModeControllerAsh::SetRenderWindowTopInsetsForTouch( - int top_inset) { - content::WebContents* contents = browser_view_->GetActiveWebContents(); - if (contents) { - aura::Window* window = contents->GetView()->GetContentNativeView(); - // |window| is NULL if the renderer crashed. - if (window) { - gfx::Insets inset(top_inset, 0, 0, 0); - window->SetHitTestBoundsOverrideOuter( - window->hit_test_bounds_override_outer_mouse(), - inset); - } - } -} - bool ImmersiveModeControllerAsh::UpdateTabIndicators() { bool has_tabstrip = browser_view_->IsBrowserTypeNormal(); if (!IsEnabled() || !has_tabstrip) { @@ -190,7 +169,6 @@ void ImmersiveModeControllerAsh::OnImmersiveRevealStarted() { visible_fraction_ = 0; browser_view_->top_container()->SetPaintToLayer(true); UpdateTabIndicators(); - SetRenderWindowTopInsetsForTouch(0); LayoutBrowserRootView(); FOR_EACH_OBSERVER(Observer, observers_, OnImmersiveRevealStarted()); } @@ -199,15 +177,12 @@ void ImmersiveModeControllerAsh::OnImmersiveRevealEnded() { visible_fraction_ = 0; browser_view_->top_container()->SetPaintToLayer(false); UpdateTabIndicators(); - SetRenderWindowTopInsetsForTouch( - kStealTouchEventsFromWebContentsRegionHeightPx); LayoutBrowserRootView(); } void ImmersiveModeControllerAsh::OnImmersiveFullscreenExited() { browser_view_->top_container()->SetPaintToLayer(false); UpdateTabIndicators(); - SetRenderWindowTopInsetsForTouch(0); LayoutBrowserRootView(); } diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h index 7f69334..2358a60 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.h @@ -50,13 +50,6 @@ class ImmersiveModeControllerAsh // Updates the browser root view's layout including window caption controls. void LayoutBrowserRootView(); - // Shrinks or expands the touch hit test by updating insets for the render - // window depending on if top_inset is positive or negative respectively. - // Used to ensure that touch events at the top of the screen go to the top - // container so a slide gesture can be generated when the content window is - // consuming all touch events sent to it. - void SetRenderWindowTopInsetsForTouch(int top_inset); - // Updates whether the tab strip is painted in a short "light bar" style. // Returns true if the visibility of the tab indicators has changed. bool UpdateTabIndicators(); diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc deleted file mode 100644 index 41311ca..0000000 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/frame/immersive_mode_controller.h" - -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_view.h" -#include "ui/aura/window.h" - -// TODO(jamescook): If immersive mode becomes popular on CrOS, consider porting -// it to other Aura platforms (win_aura, linux_aura). http://crbug.com/163931 -class ImmersiveModeControllerAshTest : public InProcessBrowserTest { - public: - ImmersiveModeControllerAshTest() : browser_view_(NULL), controller_(NULL) {} - virtual ~ImmersiveModeControllerAshTest() {} - - BrowserView* browser_view() { return browser_view_; } - ImmersiveModeController* controller() { return controller_; } - - // content::BrowserTestBase overrides: - virtual void SetUpOnMainThread() OVERRIDE { - browser_view_ = static_cast<BrowserView*>(browser()->window()); - controller_ = browser_view_->immersive_mode_controller(); - controller_->SetupForTest(); - } - - private: - BrowserView* browser_view_; - ImmersiveModeController* controller_; - - DISALLOW_COPY_AND_ASSIGN(ImmersiveModeControllerAshTest); -}; - -// Validate top container touch insets are being updated at the correct time in -// immersive mode. -IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerAshTest, - ImmersiveTopContainerInsets) { - content::WebContents* contents = browser_view()->GetActiveWebContents(); - aura::Window* window = contents->GetView()->GetContentNativeView(); - - // Turning immersive mode on sets positive top touch insets on the render view - // window. - chrome::ToggleFullscreenMode(browser()); - ASSERT_TRUE(browser_view()->IsFullscreen()); - ASSERT_TRUE(controller()->IsEnabled()); - ASSERT_FALSE(controller()->IsRevealed()); - EXPECT_TRUE(window->hit_test_bounds_override_outer_touch().top() > 0); - - // Trigger a reveal resets insets as now the touch target for the top - // container is large enough. - scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock( - ImmersiveModeController::ANIMATE_REVEAL_NO)); - EXPECT_TRUE(controller()->IsRevealed()); - EXPECT_TRUE(window->hit_test_bounds_override_outer_touch().top() == 0); - - // End reveal by moving the mouse off the top-of-window views. We - // should see the top insets being positive again to allow a bigger touch - // target. - lock.reset(); - EXPECT_FALSE(controller()->IsRevealed()); - EXPECT_TRUE(window->hit_test_bounds_override_outer_touch().top() > 0); - - // Disabling immersive mode resets the top touch insets to 0. - chrome::ToggleFullscreenMode(browser()); - ASSERT_FALSE(browser_view()->IsFullscreen()); - ASSERT_FALSE(controller()->IsEnabled()); - EXPECT_TRUE(window->hit_test_bounds_override_outer_touch().top() == 0); -} diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index fae7bf4..91858e1 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1467,7 +1467,6 @@ 'browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc', 'browser/ui/views/frame/browser_view_browsertest.cc', 'browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc', - 'browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc', 'browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc', 'browser/ui/views/new_avatar_menu_button_browsertest.cc', 'browser/ui/views/select_file_dialog_extension_browsertest.cc', @@ -1774,7 +1773,6 @@ 'browser/notifications/login_state_notification_blocker_chromeos_browsertest.cc', 'browser/ui/ash/caps_lock_delegate_chromeos_browsertest.cc', 'browser/ui/views/select_file_dialog_extension_browsertest.cc', - 'browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc', 'test/data/webui/certificate_viewer_dialog_test.js', 'test/data/webui/certificate_viewer_ui_test-inl.h', ], @@ -1885,7 +1883,6 @@ 'browser/ui/ash/shelf_browsertest.cc', 'browser/ui/views/frame/app_non_client_frame_view_ash_browsertest.cc', 'browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc', - 'browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc', ], }, { # else: OS != "win" 'sources!': [ |