diff options
-rw-r--r-- | ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc | 36 | ||||
-rw-r--r-- | chrome/browser/ui/views/apps/native_app_window_views.cc | 24 | ||||
-rw-r--r-- | chrome/browser/ui/views/apps/native_app_window_views.h | 2 | ||||
-rw-r--r-- | ui/app_list/app_list.gyp | 1 | ||||
-rw-r--r-- | ui/app_list/views/app_list_view.cc | 6 | ||||
-rw-r--r-- | ui/keyboard/keyboard_controller.cc | 3 | ||||
-rw-r--r-- | ui/views/bubble/bubble_delegate.h | 1 | ||||
-rw-r--r-- | ui/views/bubble/bubble_window_targeter.cc | 30 | ||||
-rw-r--r-- | ui/views/bubble/bubble_window_targeter.h | 33 | ||||
-rw-r--r-- | ui/views/bubble/bubble_window_targeter_unittest.cc | 116 | ||||
-rw-r--r-- | ui/views/bubble/tray_bubble_view.cc | 4 | ||||
-rw-r--r-- | ui/views/touchui/touch_selection_controller_impl.cc | 5 | ||||
-rw-r--r-- | ui/views/views.gyp | 4 | ||||
-rw-r--r-- | ui/wm/core/masked_window_targeter.cc | 3 | ||||
-rw-r--r-- | ui/wm/public/masked_window_targeter.h | 4 |
15 files changed, 264 insertions, 8 deletions
diff --git a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc b/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc index d109a41..426939a 100644 --- a/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc +++ b/ash/wm/caption_buttons/maximize_bubble_controller_bubble.cc @@ -19,7 +19,7 @@ #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" #include "ui/views/mouse_watcher.h" - +#include "ui/wm/public/masked_window_targeter.h" namespace ash { @@ -262,6 +262,36 @@ gfx::Size MaximizeBubbleBorder::GetMinimumSize() const { std::max(kLineWidth, kArrowHeight) + kLineWidth); } +namespace { + +// MaximizebubbleTargeter ----------------------------------------------------- + +// Window targeter used for the bubble. +class MaximizeBubbleTargeter : public ::wm::MaskedWindowTargeter { + public: + MaximizeBubbleTargeter(aura::Window* window, + MaximizeBubbleBorder* border) + : ::wm::MaskedWindowTargeter(window), + border_(border) { + } + + virtual ~MaximizeBubbleTargeter() {} + + private: + // ::wm::MaskedWindowTargeter: + virtual bool GetHitTestMask(aura::Window* window, + gfx::Path* mask) const OVERRIDE { + border_->GetMask(mask); + return true; + } + + MaximizeBubbleBorder* border_; + + DISALLOW_COPY_AND_ASSIGN(MaximizeBubbleTargeter); +}; + +} // namespace + // BubbleMouseWatcherHost ----------------------------------------------------- @@ -359,6 +389,10 @@ MaximizeBubbleControllerBubble::MaximizeBubbleControllerBubble( else StartFade(true); + aura::Window* window = bubble_widget_->GetNativeWindow(); + window->set_event_targeter(scoped_ptr<ui::EventTargeter>( + new MaximizeBubbleTargeter(window, bubble_border_))); + ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( ash::UMA_WINDOW_MAXIMIZE_BUTTON_SHOW_BUBBLE); diff --git a/chrome/browser/ui/views/apps/native_app_window_views.cc b/chrome/browser/ui/views/apps/native_app_window_views.cc index 3b66ed6..bb28fc5 100644 --- a/chrome/browser/ui/views/apps/native_app_window_views.cc +++ b/chrome/browser/ui/views/apps/native_app_window_views.cc @@ -65,6 +65,7 @@ #if defined(USE_AURA) #include "ui/aura/window.h" +#include "ui/wm/public/masked_window_targeter.h" #endif using apps::ShellWindow; @@ -204,6 +205,29 @@ class NativeAppWindowStateDelegate : public ash::wm::WindowStateDelegate, }; #endif // USE_ASH +class ShapedNativeAppWindowTargeter : public wm::MaskedWindowTargeter { + public: + ShapedNativeAppWindowTargeter(aura::Window* window, + NativeAppWindowViews* app_window) + : wm::MaskedWindowTargeter(window), + app_window_(app_window) { + } + + virtual ~ShapedNativeAppWindowTargeter() {} + + private: + // wm::MaskedWindowTargeter: + virtual bool GetHitTestMask(aura::Window* window, + gfx::Path* mask) const OVERRIDE { + SkRegion* shape = app_window_->shape(); + return shape ? shape->getBoundaryPath(mask) : false; + } + + NativeAppWindowViews* app_window_; + + DISALLOW_COPY_AND_ASSIGN(ShapedNativeAppWindowTargeter); +}; + } // namespace NativeAppWindowViews::NativeAppWindowViews() diff --git a/chrome/browser/ui/views/apps/native_app_window_views.h b/chrome/browser/ui/views/apps/native_app_window_views.h index f2ce0cb..62d5d2a 100644 --- a/chrome/browser/ui/views/apps/native_app_window_views.h +++ b/chrome/browser/ui/views/apps/native_app_window_views.h @@ -64,6 +64,8 @@ class NativeAppWindowViews : public apps::NativeAppWindow, void Init(apps::ShellWindow* shell_window, const apps::ShellWindow::CreateParams& create_params); + SkRegion* shape() { return shape_.get(); } + protected: // Called before views::Widget::Init() to allow subclasses to customize // the InitParams that would be passed. diff --git a/ui/app_list/app_list.gyp b/ui/app_list/app_list.gyp index 6b070bc..6ddddb7 100644 --- a/ui/app_list/app_list.gyp +++ b/ui/app_list/app_list.gyp @@ -145,6 +145,7 @@ '../events/events.gyp:events', '../views/controls/webview/webview.gyp:webview', '../views/views.gyp:views', + '../wm/wm.gyp:wm_public', ], }, { # toolkit_views==0 'sources/': [ diff --git a/ui/app_list/views/app_list_view.cc b/ui/app_list/views/app_list_view.cc index f712b84..b023847 100644 --- a/ui/app_list/views/app_list_view.cc +++ b/ui/app_list/views/app_list_view.cc @@ -27,6 +27,7 @@ #include "ui/gfx/path.h" #include "ui/gfx/skia_util.h" #include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/bubble/bubble_window_targeter.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" @@ -308,11 +309,14 @@ void AppListView::InitAsBubbleInternal(gfx::NativeView parent, SetBubbleArrow(arrow); #if defined(USE_AURA) - GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true); + aura::Window* window = GetWidget()->GetNativeWindow(); + window->layer()->SetMasksToBounds(true); GetBubbleFrameView()->set_background(new AppListBackground( GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), app_list_main_view_)); set_background(NULL); + window->set_event_targeter(scoped_ptr<ui::EventTargeter>( + new views::BubbleWindowTargeter(this))); #else set_background(new AppListBackground( GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(), diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 9b0b3d1..15d5208 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc @@ -50,11 +50,12 @@ class KeyboardContainerTargeter : public wm::MaskedWindowTargeter { private: // wm::MaskedWindowTargeter: - virtual void GetHitTestMask(aura::Window* window, + virtual bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const OVERRIDE { gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() : KeyboardBoundsFromWindowBounds(window->bounds()); mask->addRect(RectToSkRect(keyboard_bounds)); + return true; } keyboard::KeyboardControllerProxy* proxy_; diff --git a/ui/views/bubble/bubble_delegate.h b/ui/views/bubble/bubble_delegate.h index 4bf8ff6..3a38bf9 100644 --- a/ui/views/bubble/bubble_delegate.h +++ b/ui/views/bubble/bubble_delegate.h @@ -158,6 +158,7 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView, private: friend class BubbleBorderDelegate; + friend class BubbleWindowTargeter; FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate); FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest); diff --git a/ui/views/bubble/bubble_window_targeter.cc b/ui/views/bubble/bubble_window_targeter.cc new file mode 100644 index 0000000..19e0c85 --- /dev/null +++ b/ui/views/bubble/bubble_window_targeter.cc @@ -0,0 +1,30 @@ +// 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 "ui/views/bubble/bubble_window_targeter.h" + +#include "ui/aura/window.h" +#include "ui/gfx/path.h" +#include "ui/gfx/skia_util.h" +#include "ui/views/bubble/bubble_delegate.h" +#include "ui/views/bubble/bubble_frame_view.h" + +namespace views { + +BubbleWindowTargeter::BubbleWindowTargeter(BubbleDelegateView* bubble) + : wm::MaskedWindowTargeter(bubble->GetWidget()->GetNativeView()), + bubble_(bubble) { +} + +BubbleWindowTargeter::~BubbleWindowTargeter() { +} + +bool BubbleWindowTargeter::GetHitTestMask(aura::Window* window, + gfx::Path* mask) const { + mask->addRect( + gfx::RectToSkRect(bubble_->GetBubbleFrameView()->GetContentsBounds())); + return true; +} + +} // namespace views diff --git a/ui/views/bubble/bubble_window_targeter.h b/ui/views/bubble/bubble_window_targeter.h new file mode 100644 index 0000000..09a96c7 --- /dev/null +++ b/ui/views/bubble/bubble_window_targeter.h @@ -0,0 +1,33 @@ +// 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 "ui/views/views_export.h" +#include "ui/wm/public/masked_window_targeter.h" + +namespace aura { +class Window; +} + +namespace views { +class BubbleDelegateView; + +// A convenient window-targeter that uses a mask based on the content-bounds of +// the bubble-frame. +class VIEWS_EXPORT BubbleWindowTargeter + : public NON_EXPORTED_BASE(wm::MaskedWindowTargeter) { + public: + explicit BubbleWindowTargeter(BubbleDelegateView* bubble); + virtual ~BubbleWindowTargeter(); + + private: + // wm::MaskedWindowTargeter: + virtual bool GetHitTestMask(aura::Window* window, + gfx::Path* mask) const OVERRIDE; + + views::BubbleDelegateView* bubble_; + + DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeter); +}; + +} // namespace views diff --git a/ui/views/bubble/bubble_window_targeter_unittest.cc b/ui/views/bubble/bubble_window_targeter_unittest.cc new file mode 100644 index 0000000..bdd233d --- /dev/null +++ b/ui/views/bubble/bubble_window_targeter_unittest.cc @@ -0,0 +1,116 @@ +// 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 "ui/views/bubble/bubble_window_targeter.h" + +#include "ui/aura/root_window.h" +#include "ui/aura/window.h" +#include "ui/views/bubble/bubble_border.h" +#include "ui/views/bubble/bubble_delegate.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget.h" + +namespace views { + +namespace { + +class WidgetOwnsNativeBubble : public BubbleDelegateView { + public: + WidgetOwnsNativeBubble(View* content, BubbleBorder::Arrow arrow) + : BubbleDelegateView(content, arrow) { + } + + virtual ~WidgetOwnsNativeBubble() {} + + private: + // BubbleDelegateView: + virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params, + Widget* widget) const OVERRIDE { + params->ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + } + + DISALLOW_COPY_AND_ASSIGN(WidgetOwnsNativeBubble); +}; + +} // namespace + +class BubbleWindowTargeterTest : public ViewsTestBase { + public: + BubbleWindowTargeterTest() + : bubble_delegate_(NULL) { + } + virtual ~BubbleWindowTargeterTest() {} + + virtual void SetUp() OVERRIDE { + ViewsTestBase::SetUp(); + CreateAnchorWidget(); + CreateBubbleWidget(); + + anchor_widget()->Show(); + bubble_widget()->Show(); + } + + virtual void TearDown() OVERRIDE { + bubble_delegate_ = NULL; + bubble_widget_.reset(); + anchor_.reset(); + ViewsTestBase::TearDown(); + } + + Widget* anchor_widget() { return anchor_.get(); } + Widget* bubble_widget() { return bubble_widget_.get(); } + BubbleDelegateView* bubble_delegate() { return bubble_delegate_; } + + private: + void CreateAnchorWidget() { + anchor_.reset(new Widget()); + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + anchor_->Init(params); + } + + void CreateBubbleWidget() { + bubble_delegate_ = new WidgetOwnsNativeBubble( + anchor_->GetContentsView(), BubbleBorder::NONE); + bubble_delegate_->set_color(SK_ColorGREEN); + bubble_widget_.reset(BubbleDelegateView::CreateBubble(bubble_delegate_)); + } + + scoped_ptr<Widget> anchor_; + scoped_ptr<Widget> bubble_widget_; + BubbleDelegateView* bubble_delegate_; + + DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeterTest); +}; + +TEST_F(BubbleWindowTargeterTest, HitTest) { + ui::EventTarget* root = bubble_widget()->GetNativeWindow()->GetRootWindow(); + ui::EventTargeter* targeter = root->GetEventTargeter(); + aura::Window* bubble_window = bubble_widget()->GetNativeWindow(); + gfx::Rect bubble_bounds = bubble_window->GetBoundsInRootWindow(); + + { + bubble_delegate()->set_margins(gfx::Insets()); + ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(), + bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE); + EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1)); + } + { + bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20)); + ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(), + bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE); + EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1)); + } + + bubble_window->set_event_targeter(scoped_ptr<ui::EventTargeter>( + new BubbleWindowTargeter(bubble_delegate()))); + { + bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20)); + ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(), + bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE); + EXPECT_NE(bubble_window, targeter->FindTargetForEvent(root, &move1)); + } +} + +} // namespace views diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc index 3f947ab..4b67515 100644 --- a/ui/views/bubble/tray_bubble_view.cc +++ b/ui/views/bubble/tray_bubble_view.cc @@ -11,6 +11,7 @@ #include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" +#include "ui/aura/window.h" #include "ui/base/accessibility/accessible_view_state.h" #include "ui/base/l10n/l10n_util.h" #include "ui/compositor/layer.h" @@ -22,6 +23,7 @@ #include "ui/gfx/rect.h" #include "ui/gfx/skia_util.h" #include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/bubble/bubble_window_targeter.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" @@ -354,6 +356,8 @@ void TrayBubbleView::InitializeAndShowBubble() { layer()->parent()->SetMaskLayer(bubble_content_mask_->layer()); GetWidget()->Show(); + GetWidget()->GetNativeWindow()->set_event_targeter( + scoped_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this))); UpdateBubble(); } diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc index 11868f6..c87eb82 100644 --- a/ui/views/touchui/touch_selection_controller_impl.cc +++ b/ui/views/touchui/touch_selection_controller_impl.cc @@ -127,7 +127,7 @@ class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter { private: // wm::MaskedWindowTargeter: - virtual void GetHitTestMask(aura::Window* window, + virtual bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const OVERRIDE; EditingHandleView* handle_view_; @@ -300,7 +300,7 @@ TouchHandleWindowTargeter::TouchHandleWindowTargeter( handle_view_(handle_view) { } -void TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window, +bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window, gfx::Path* mask) const { const gfx::Rect& selection_rect = handle_view_->selection_rect(); gfx::Size image_size = GetHandleImageSize(); @@ -308,6 +308,7 @@ void TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window, SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding, SkIntToScalar(selection_rect.height() + image_size.height() + kSelectionHandleVertPadding)); + return true; } TouchSelectionControllerImpl::TouchSelectionControllerImpl( diff --git a/ui/views/views.gyp b/ui/views/views.gyp index e0d5f0d..a9d9e617 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -64,6 +64,8 @@ 'bubble/bubble_delegate.h', 'bubble/bubble_frame_view.cc', 'bubble/bubble_frame_view.h', + 'bubble/bubble_window_targeter.cc', + 'bubble/bubble_window_targeter.h', 'bubble/tray_bubble_view.cc', 'bubble/tray_bubble_view.h', 'button_drag_utils.cc', @@ -726,6 +728,7 @@ '../resources/ui_resources.gyp:ui_test_pak', '../ui.gyp:ui', '../ui_unittests.gyp:ui_test_support', + '../wm/wm.gyp:wm_public', 'views', 'views_test_support', ], @@ -739,6 +742,7 @@ 'bubble/bubble_border_unittest.cc', 'bubble/bubble_delegate_unittest.cc', 'bubble/bubble_frame_view_unittest.cc', + 'bubble/bubble_window_targeter_unittest.cc', 'controls/button/custom_button_unittest.cc', 'controls/button/image_button_unittest.cc', 'controls/button/label_button_unittest.cc', diff --git a/ui/wm/core/masked_window_targeter.cc b/ui/wm/core/masked_window_targeter.cc index 3de6140..c6277fb 100644 --- a/ui/wm/core/masked_window_targeter.cc +++ b/ui/wm/core/masked_window_targeter.cc @@ -20,7 +20,8 @@ bool MaskedWindowTargeter::EventLocationInsideBounds( const ui::LocatedEvent& event) const { if (window == masked_window_) { gfx::Path mask; - GetHitTestMask(window, &mask); + if (!GetHitTestMask(window, &mask)) + return WindowTargeter::EventLocationInsideBounds(window, event); gfx::Size size = window->bounds().size(); SkRegion clip_region; diff --git a/ui/wm/public/masked_window_targeter.h b/ui/wm/public/masked_window_targeter.h index edb050f..ad3140d3 100644 --- a/ui/wm/public/masked_window_targeter.h +++ b/ui/wm/public/masked_window_targeter.h @@ -20,8 +20,8 @@ class MaskedWindowTargeter : public aura::WindowTargeter { protected: // Sets the hit-test mask for |window| in |mask| (in |window|'s local - // coordinate system). - virtual void GetHitTestMask(aura::Window* window, gfx::Path* mask) const = 0; + // coordinate system). Returns whether a valid mask has been set in |mask|. + virtual bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const = 0; // aura::WindowTargeter: virtual bool EventLocationInsideBounds( |