Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <set> | 6 #include <set> |
| 7 | 7 |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 bool IsTestingSnowLeopard() { | 61 bool IsTestingSnowLeopard() { |
| 62 #if defined(OS_MACOSX) | 62 #if defined(OS_MACOSX) |
| 63 return base::mac::IsOSSnowLeopard(); | 63 return base::mac::IsOSSnowLeopard(); |
| 64 #else | 64 #else |
| 65 return false; | 65 return false; |
| 66 #endif | 66 #endif |
| 67 } | 67 } |
| 68 | 68 |
| 69 } // namespace | 69 } // namespace |
| 70 | 70 |
| 71 // A view that keeps track of the events it receives, optionally consuming them. | |
| 72 class EventCountView : public View { | |
| 73 public: | |
| 74 // Whether to call SetHandled() on events as they are received. For some event | |
| 75 // types, this will allow EventCountView to receives future events in the | |
| 76 // event sequence, such as a drag. | |
| 77 enum HandleMode { | |
| 78 PROPAGATE_EVENTS, | |
| 79 CONSUME_EVENTS | |
| 80 }; | |
| 81 | |
| 82 EventCountView() | |
| 83 : last_flags_(0), | |
| 84 handle_mode_(PROPAGATE_EVENTS) {} | |
| 85 | |
| 86 ~EventCountView() override {} | |
| 87 | |
| 88 int GetEventCount(ui::EventType type) { | |
| 89 return event_count_[type]; | |
| 90 } | |
| 91 | |
| 92 void ResetCounts() { | |
| 93 event_count_.clear(); | |
| 94 } | |
| 95 | |
| 96 int last_flags() const { | |
| 97 return last_flags_; | |
| 98 } | |
| 99 | |
| 100 void set_handle_mode(HandleMode handle_mode) { | |
| 101 handle_mode_ = handle_mode; | |
| 102 } | |
| 103 | |
| 104 protected: | |
| 105 // Overridden from View: | |
| 106 void OnMouseMoved(const ui::MouseEvent& event) override { | |
| 107 // MouseMove events are not re-dispatched from the RootView. | |
| 108 ++event_count_[ui::ET_MOUSE_MOVED]; | |
| 109 last_flags_ = 0; | |
| 110 } | |
| 111 | |
| 112 // Overridden from ui::EventHandler: | |
| 113 void OnKeyEvent(ui::KeyEvent* event) override { RecordEvent(event); } | |
| 114 void OnMouseEvent(ui::MouseEvent* event) override { RecordEvent(event); } | |
| 115 void OnScrollEvent(ui::ScrollEvent* event) override { RecordEvent(event); } | |
| 116 void OnGestureEvent(ui::GestureEvent* event) override { RecordEvent(event); } | |
| 117 | |
| 118 private: | |
| 119 void RecordEvent(ui::Event* event) { | |
| 120 ++event_count_[event->type()]; | |
| 121 last_flags_ = event->flags(); | |
| 122 if (handle_mode_ == CONSUME_EVENTS) | |
| 123 event->SetHandled(); | |
| 124 } | |
| 125 | |
| 126 std::map<ui::EventType, int> event_count_; | |
| 127 int last_flags_; | |
| 128 HandleMode handle_mode_; | |
| 129 | |
| 130 DISALLOW_COPY_AND_ASSIGN(EventCountView); | |
| 131 }; | |
| 132 | |
| 133 // A view that keeps track of the events it receives, and consumes all scroll | 71 // A view that keeps track of the events it receives, and consumes all scroll |
| 134 // gesture events and ui::ET_SCROLL events. | 72 // gesture events and ui::ET_SCROLL events. |
| 135 class ScrollableEventCountView : public EventCountView { | 73 class ScrollableEventCountView : public EventCountView { |
| 136 public: | 74 public: |
| 137 ScrollableEventCountView() {} | 75 ScrollableEventCountView() {} |
| 138 ~ScrollableEventCountView() override {} | 76 ~ScrollableEventCountView() override {} |
| 139 | 77 |
| 140 private: | 78 private: |
| 141 // Overridden from ui::EventHandler: | 79 // Overridden from ui::EventHandler: |
| 142 void OnGestureEvent(ui::GestureEvent* event) override { | 80 void OnGestureEvent(ui::GestureEvent* event) override { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 private: | 138 private: |
| 201 void RecordEvent(const ui::Event& event) { | 139 void RecordEvent(const ui::Event& event) { |
| 202 ++event_count_[event.type()]; | 140 ++event_count_[event.type()]; |
| 203 } | 141 } |
| 204 | 142 |
| 205 std::map<ui::EventType, int> event_count_; | 143 std::map<ui::EventType, int> event_count_; |
| 206 | 144 |
| 207 DISALLOW_COPY_AND_ASSIGN(EventCountHandler); | 145 DISALLOW_COPY_AND_ASSIGN(EventCountHandler); |
| 208 }; | 146 }; |
| 209 | 147 |
| 210 // A helper WidgetDelegate for tests that require hooks into WidgetDelegate | |
| 211 // calls, and removes some of the boilerplate for initializing a Widget. Calls | |
| 212 // Widget::CloseNow() when destroyed if it hasn't already been done. | |
| 213 class TestDesktopWidgetDelegate : public WidgetDelegate { | |
| 214 public: | |
| 215 TestDesktopWidgetDelegate() : widget_(new Widget) {} | |
| 216 | |
| 217 ~TestDesktopWidgetDelegate() override { | |
| 218 if (widget_) | |
| 219 widget_->CloseNow(); | |
| 220 EXPECT_FALSE(widget_); | |
| 221 } | |
| 222 | |
| 223 // Initialize the Widget, adding some meaningful default InitParams. | |
| 224 void InitWidget(Widget::InitParams init_params) { | |
| 225 init_params.delegate = this; | |
| 226 #if !defined(OS_CHROMEOS) | |
| 227 init_params.native_widget = new PlatformDesktopNativeWidget(widget_); | |
| 228 #endif | |
| 229 init_params.bounds = initial_bounds_; | |
| 230 widget_->Init(init_params); | |
| 231 } | |
| 232 | |
| 233 // Set the contents view to be used during Widget initialization. For Widgets | |
| 234 // that use non-client views, this will be the contents_view used to | |
| 235 // initialize the ClientView in WidgetDelegate::CreateClientView(). Otherwise, | |
| 236 // it is the ContentsView of the Widget's RootView. Ownership passes to the | |
| 237 // view hierarchy during InitWidget(). | |
| 238 void set_contents_view(View* contents_view) { | |
| 239 contents_view_ = contents_view; | |
| 240 } | |
| 241 | |
| 242 int window_closing_count() const { return window_closing_count_; } | |
| 243 const gfx::Rect& initial_bounds() { return initial_bounds_; } | |
| 244 | |
| 245 // WidgetDelegate overrides: | |
| 246 void WindowClosing() override { | |
| 247 window_closing_count_++; | |
| 248 widget_ = nullptr; | |
| 249 } | |
| 250 | |
| 251 Widget* GetWidget() override { return widget_; } | |
| 252 const Widget* GetWidget() const override { return widget_; } | |
| 253 | |
| 254 View* GetContentsView() override { | |
| 255 return contents_view_ ? contents_view_ : WidgetDelegate::GetContentsView(); | |
| 256 } | |
| 257 | |
| 258 bool ShouldAdvanceFocusToTopLevelWidget() const override { | |
| 259 return true; // Same default as DefaultWidgetDelegate in widget.cc. | |
| 260 } | |
| 261 | |
| 262 private: | |
| 263 Widget* widget_; | |
| 264 View* contents_view_ = nullptr; | |
| 265 int window_closing_count_ = 0; | |
| 266 gfx::Rect initial_bounds_ = gfx::Rect(100, 100, 200, 200); | |
| 267 | |
| 268 DISALLOW_COPY_AND_ASSIGN(TestDesktopWidgetDelegate); | |
| 269 }; | |
| 270 | |
| 271 TEST_F(WidgetTest, WidgetInitParams) { | 148 TEST_F(WidgetTest, WidgetInitParams) { |
| 272 // Widgets are not transparent by default. | 149 // Widgets are not transparent by default. |
| 273 Widget::InitParams init1; | 150 Widget::InitParams init1; |
| 274 EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity); | 151 EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity); |
| 275 } | 152 } |
| 276 | 153 |
| 277 TEST_F(WidgetTest, NativeWindowProperty) { | 154 TEST_F(WidgetTest, NativeWindowProperty) { |
| 278 const char* key = "foo"; | 155 const char* key = "foo"; |
| 279 int value = 3; | 156 int value = 3; |
| 280 | 157 |
| (...skipping 2766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3047 RunDestroyChildWidgetsTest(true, true); | 2924 RunDestroyChildWidgetsTest(true, true); |
| 3048 } | 2925 } |
| 3049 #endif // !defined(OS_CHROMEOS) | 2926 #endif // !defined(OS_CHROMEOS) |
| 3050 | 2927 |
| 3051 // See description of RunDestroyChildWidgetsTest(). | 2928 // See description of RunDestroyChildWidgetsTest(). |
| 3052 TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) { | 2929 TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) { |
| 3053 RunDestroyChildWidgetsTest(false, false); | 2930 RunDestroyChildWidgetsTest(false, false); |
| 3054 } | 2931 } |
| 3055 | 2932 |
| 3056 #if !defined(OS_CHROMEOS) | 2933 #if !defined(OS_CHROMEOS) |
| 3057 // Provides functionality to create a window modal dialog. | |
| 3058 class ModalDialogDelegate : public DialogDelegateView { | |
| 3059 public: | |
| 3060 ModalDialogDelegate() {} | |
| 3061 ~ModalDialogDelegate() override {} | |
| 3062 | |
| 3063 // WidgetDelegate overrides. | |
| 3064 ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; } | |
| 3065 | |
| 3066 private: | |
| 3067 DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate); | |
| 3068 }; | |
| 3069 | |
| 3070 // This test verifies that whether mouse events when a modal dialog is | |
| 3071 // displayed are eaten or recieved by the dialog. | |
| 3072 TEST_F(WidgetTest, WindowMouseModalityTest) { | |
| 3073 // Create a top level widget. | |
| 3074 Widget top_level_widget; | |
| 3075 Widget::InitParams init_params = | |
| 3076 CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 3077 init_params.show_state = ui::SHOW_STATE_NORMAL; | |
| 3078 gfx::Rect initial_bounds(0, 0, 500, 500); | |
| 3079 init_params.bounds = initial_bounds; | |
| 3080 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 3081 init_params.native_widget = | |
| 3082 new PlatformDesktopNativeWidget(&top_level_widget); | |
| 3083 top_level_widget.Init(init_params); | |
| 3084 top_level_widget.Show(); | |
| 3085 EXPECT_TRUE(top_level_widget.IsVisible()); | |
| 3086 | |
| 3087 // Create a view and validate that a mouse moves makes it to the view. | |
| 3088 EventCountView* widget_view = new EventCountView(); | |
| 3089 widget_view->SetBounds(0, 0, 10, 10); | |
| 3090 top_level_widget.GetRootView()->AddChildView(widget_view); | |
| 3091 | |
| 3092 gfx::Point cursor_location_main(5, 5); | |
| 3093 ui::MouseEvent move_main(ui::ET_MOUSE_MOVED, cursor_location_main, | |
| 3094 cursor_location_main, ui::EventTimeForNow(), | |
| 3095 ui::EF_NONE, ui::EF_NONE); | |
| 3096 ui::EventDispatchDetails details = | |
| 3097 GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main); | |
| 3098 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 3099 | |
| 3100 EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED)); | |
| 3101 widget_view->ResetCounts(); | |
| 3102 | |
| 3103 // Create a modal dialog and validate that a mouse down message makes it to | |
| 3104 // the main view within the dialog. | |
| 3105 | |
| 3106 // This instance will be destroyed when the dialog is destroyed. | |
| 3107 ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate; | |
| 3108 | |
| 3109 Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( | |
| 3110 dialog_delegate, NULL, top_level_widget.GetNativeView()); | |
| 3111 modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); | |
| 3112 EventCountView* dialog_widget_view = new EventCountView(); | |
| 3113 dialog_widget_view->SetBounds(0, 0, 50, 50); | |
| 3114 modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view); | |
| 3115 modal_dialog_widget->Show(); | |
| 3116 EXPECT_TRUE(modal_dialog_widget->IsVisible()); | |
| 3117 | |
| 3118 gfx::Point cursor_location_dialog(100, 100); | |
| 3119 ui::MouseEvent mouse_down_dialog( | |
| 3120 ui::ET_MOUSE_PRESSED, cursor_location_dialog, cursor_location_dialog, | |
| 3121 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); | |
| 3122 details = GetEventProcessor(&top_level_widget)->OnEventFromSource( | |
| 3123 &mouse_down_dialog); | |
| 3124 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 3125 EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED)); | |
| 3126 | |
| 3127 // Send a mouse move message to the main window. It should not be received by | |
| 3128 // the main window as the modal dialog is still active. | |
| 3129 gfx::Point cursor_location_main2(6, 6); | |
| 3130 ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED, cursor_location_main2, | |
| 3131 cursor_location_main2, ui::EventTimeForNow(), | |
| 3132 ui::EF_NONE, ui::EF_NONE); | |
| 3133 details = GetEventProcessor(&top_level_widget)->OnEventFromSource( | |
| 3134 &mouse_down_main); | |
| 3135 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 3136 EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED)); | |
| 3137 | |
| 3138 modal_dialog_widget->CloseNow(); | |
| 3139 top_level_widget.CloseNow(); | |
| 3140 } | |
| 3141 | |
| 3142 // Verifies nativeview visbility matches that of Widget visibility when | 2934 // Verifies nativeview visbility matches that of Widget visibility when |
| 3143 // SetFullscreen is invoked. | 2935 // SetFullscreen is invoked. |
| 3144 TEST_F(WidgetTest, FullscreenStatePropagated) { | 2936 TEST_F(WidgetTest, FullscreenStatePropagated) { |
| 3145 Widget::InitParams init_params = | 2937 Widget::InitParams init_params = |
| 3146 CreateParams(Widget::InitParams::TYPE_WINDOW); | 2938 CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 3147 init_params.show_state = ui::SHOW_STATE_NORMAL; | 2939 init_params.show_state = ui::SHOW_STATE_NORMAL; |
| 3148 init_params.bounds = gfx::Rect(0, 0, 500, 500); | 2940 init_params.bounds = gfx::Rect(0, 0, 500, 500); |
| 3149 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 2941 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 3150 | 2942 |
| 3151 { | 2943 { |
| 3152 Widget top_level_widget; | 2944 Widget top_level_widget; |
| 3153 top_level_widget.Init(init_params); | 2945 top_level_widget.Init(init_params); |
| 3154 top_level_widget.SetFullscreen(true); | 2946 top_level_widget.SetFullscreen(true); |
| 3155 EXPECT_EQ(top_level_widget.IsVisible(), | 2947 EXPECT_EQ(top_level_widget.IsVisible(), |
| 3156 IsNativeWindowVisible(top_level_widget.GetNativeWindow())); | 2948 IsNativeWindowVisible(top_level_widget.GetNativeWindow())); |
| 3157 top_level_widget.CloseNow(); | 2949 top_level_widget.CloseNow(); |
| 3158 } | 2950 } |
| 3159 #if !defined(OS_CHROMEOS) | 2951 #if !defined(OS_CHROMEOS) |
|
tapted
2015/08/03 01:10:46
odd... this is already in #if !defined(OS_CHROMEOS
jackhou1
2015/08/03 05:09:50
Done.
| |
| 3160 { | 2952 { |
| 3161 Widget top_level_widget; | 2953 Widget top_level_widget; |
| 3162 init_params.native_widget = | 2954 init_params.native_widget = |
| 3163 new PlatformDesktopNativeWidget(&top_level_widget); | 2955 new PlatformDesktopNativeWidget(&top_level_widget); |
| 3164 top_level_widget.Init(init_params); | 2956 top_level_widget.Init(init_params); |
| 3165 top_level_widget.SetFullscreen(true); | 2957 top_level_widget.SetFullscreen(true); |
| 3166 EXPECT_EQ(top_level_widget.IsVisible(), | 2958 EXPECT_EQ(top_level_widget.IsVisible(), |
| 3167 IsNativeWindowVisible(top_level_widget.GetNativeWindow())); | 2959 IsNativeWindowVisible(top_level_widget.GetNativeWindow())); |
| 3168 top_level_widget.CloseNow(); | 2960 top_level_widget.CloseNow(); |
| 3169 } | 2961 } |
| 3170 #endif | 2962 #endif |
| 3171 } | 2963 } |
| 3172 #if defined(OS_WIN) | |
| 3173 | |
| 3174 // Tests whether we can activate the top level widget when a modal dialog is | |
| 3175 // active. | |
| 3176 TEST_F(WidgetTest, WindowModalityActivationTest) { | |
| 3177 TestDesktopWidgetDelegate widget_delegate; | |
| 3178 widget_delegate.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW)); | |
| 3179 | |
| 3180 Widget* top_level_widget = widget_delegate.GetWidget(); | |
| 3181 top_level_widget->Show(); | |
| 3182 EXPECT_TRUE(top_level_widget->IsVisible()); | |
| 3183 | |
| 3184 HWND win32_window = views::HWNDForWidget(top_level_widget); | |
| 3185 EXPECT_TRUE(::IsWindow(win32_window)); | |
| 3186 | |
| 3187 // This instance will be destroyed when the dialog is destroyed. | |
| 3188 ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate; | |
| 3189 | |
| 3190 // We should be able to activate the window even if the WidgetDelegate | |
| 3191 // says no, when a modal dialog is active. | |
| 3192 widget_delegate.set_can_activate(false); | |
| 3193 | |
| 3194 Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( | |
| 3195 dialog_delegate, NULL, top_level_widget->GetNativeView()); | |
| 3196 modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); | |
| 3197 modal_dialog_widget->Show(); | |
| 3198 EXPECT_TRUE(modal_dialog_widget->IsVisible()); | |
| 3199 | |
| 3200 LRESULT activate_result = ::SendMessage( | |
| 3201 win32_window, | |
| 3202 WM_MOUSEACTIVATE, | |
| 3203 reinterpret_cast<WPARAM>(win32_window), | |
| 3204 MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT)); | |
| 3205 EXPECT_EQ(activate_result, MA_ACTIVATE); | |
| 3206 | |
| 3207 modal_dialog_widget->CloseNow(); | |
| 3208 } | |
| 3209 #endif // defined(OS_WIN) | |
| 3210 #endif // !defined(OS_CHROMEOS) | 2964 #endif // !defined(OS_CHROMEOS) |
| 3211 | 2965 |
| 3212 namespace { | 2966 namespace { |
| 3213 | 2967 |
| 3214 class FullscreenAwareFrame : public views::NonClientFrameView { | 2968 class FullscreenAwareFrame : public views::NonClientFrameView { |
| 3215 public: | 2969 public: |
| 3216 explicit FullscreenAwareFrame(views::Widget* widget) | 2970 explicit FullscreenAwareFrame(views::Widget* widget) |
| 3217 : widget_(widget), fullscreen_layout_called_(false) {} | 2971 : widget_(widget), fullscreen_layout_called_(false) {} |
| 3218 ~FullscreenAwareFrame() override {} | 2972 ~FullscreenAwareFrame() override {} |
| 3219 | 2973 |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3438 EXPECT_FALSE(widget->IsAlwaysOnTop()); | 3192 EXPECT_FALSE(widget->IsAlwaysOnTop()); |
| 3439 widget->SetAlwaysOnTop(true); | 3193 widget->SetAlwaysOnTop(true); |
| 3440 EXPECT_TRUE(widget->IsAlwaysOnTop()); | 3194 EXPECT_TRUE(widget->IsAlwaysOnTop()); |
| 3441 widget->SetAlwaysOnTop(false); | 3195 widget->SetAlwaysOnTop(false); |
| 3442 EXPECT_FALSE(widget->IsAlwaysOnTop()); | 3196 EXPECT_FALSE(widget->IsAlwaysOnTop()); |
| 3443 widget->CloseNow(); | 3197 widget->CloseNow(); |
| 3444 } | 3198 } |
| 3445 | 3199 |
| 3446 } // namespace test | 3200 } // namespace test |
| 3447 } // namespace views | 3201 } // namespace views |
| OLD | NEW |