| 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/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 3170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3181 reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( | 3181 reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue( |
| 3182 widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(), | 3182 widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(), |
| 3183 ui::WindowEventTarget::kWin32InputEventTarget)); | 3183 ui::WindowEventTarget::kWin32InputEventTarget)); |
| 3184 EXPECT_NE(nullptr, target); | 3184 EXPECT_NE(nullptr, target); |
| 3185 bool handled = false; | 3185 bool handled = false; |
| 3186 target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled); | 3186 target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled); |
| 3187 target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled); | 3187 target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled); |
| 3188 target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled); | 3188 target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled); |
| 3189 widget.CloseNow(); | 3189 widget.CloseNow(); |
| 3190 } | 3190 } |
| 3191 | |
| 3192 // Provides functionality to subclass a window and keep track of messages | |
| 3193 // received. | |
| 3194 class SubclassWindowHelper { | |
| 3195 public: | |
| 3196 explicit SubclassWindowHelper(HWND window) | |
| 3197 : window_(window), | |
| 3198 message_to_destroy_on_(0) { | |
| 3199 EXPECT_EQ(instance_, nullptr); | |
| 3200 instance_ = this; | |
| 3201 EXPECT_TRUE(Subclass()); | |
| 3202 } | |
| 3203 | |
| 3204 ~SubclassWindowHelper() { | |
| 3205 Unsubclass(); | |
| 3206 instance_ = nullptr; | |
| 3207 } | |
| 3208 | |
| 3209 // Returns true if the |message| passed in was received. | |
| 3210 bool received_message(unsigned int message) { | |
| 3211 return (messages_.find(message) != messages_.end()); | |
| 3212 } | |
| 3213 | |
| 3214 void Clear() { | |
| 3215 messages_.clear(); | |
| 3216 } | |
| 3217 | |
| 3218 void set_message_to_destroy_on(unsigned int message) { | |
| 3219 message_to_destroy_on_ = message; | |
| 3220 } | |
| 3221 | |
| 3222 private: | |
| 3223 bool Subclass() { | |
| 3224 old_proc_ = reinterpret_cast<WNDPROC>( | |
| 3225 ::SetWindowLongPtr(window_, | |
| 3226 GWLP_WNDPROC, | |
| 3227 reinterpret_cast<LONG_PTR>(WndProc))); | |
| 3228 return old_proc_ != nullptr; | |
| 3229 } | |
| 3230 | |
| 3231 void Unsubclass() { | |
| 3232 ::SetWindowLongPtr(window_, | |
| 3233 GWLP_WNDPROC, | |
| 3234 reinterpret_cast<LONG_PTR>(old_proc_)); | |
| 3235 } | |
| 3236 | |
| 3237 static LRESULT CALLBACK WndProc(HWND window, | |
| 3238 unsigned int message, | |
| 3239 WPARAM w_param, | |
| 3240 LPARAM l_param) { | |
| 3241 EXPECT_NE(instance_, nullptr); | |
| 3242 EXPECT_EQ(window, instance_->window_); | |
| 3243 | |
| 3244 // Keep track of messags received for this window. | |
| 3245 instance_->messages_.insert(message); | |
| 3246 | |
| 3247 LRESULT ret = ::CallWindowProc(instance_->old_proc_, window, message, | |
| 3248 w_param, l_param); | |
| 3249 if (message == instance_->message_to_destroy_on_) { | |
| 3250 instance_->Unsubclass(); | |
| 3251 ::DestroyWindow(window); | |
| 3252 } | |
| 3253 return ret; | |
| 3254 } | |
| 3255 | |
| 3256 WNDPROC old_proc_; | |
| 3257 HWND window_; | |
| 3258 static SubclassWindowHelper* instance_; | |
| 3259 std::set<unsigned int> messages_; | |
| 3260 unsigned int message_to_destroy_on_; | |
| 3261 | |
| 3262 DISALLOW_COPY_AND_ASSIGN(SubclassWindowHelper); | |
| 3263 }; | |
| 3264 | |
| 3265 SubclassWindowHelper* SubclassWindowHelper::instance_ = nullptr; | |
| 3266 | |
| 3267 // This test validates whether the WM_SYSCOMMAND message for SC_MOVE is | |
| 3268 // received when we post a WM_NCLBUTTONDOWN message for the caption in the | |
| 3269 // following scenarios:- | |
| 3270 // 1. Posting a WM_NCMOUSEMOVE message for a different location. | |
| 3271 // 2. Posting a WM_NCMOUSEMOVE message with a different hittest code. | |
| 3272 // 3. Posting a WM_MOUSEMOVE message. | |
| 3273 // Disabled because of flaky timeouts: http://crbug.com/592742 | |
| 3274 TEST_F(WidgetTest, DISABLED_SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) { | |
| 3275 Widget widget; | |
| 3276 Widget::InitParams params = | |
| 3277 CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 3278 params.native_widget = | |
| 3279 CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); | |
| 3280 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 3281 widget.Init(params); | |
| 3282 widget.SetBounds(gfx::Rect(0, 0, 200, 200)); | |
| 3283 widget.Show(); | |
| 3284 ::SetCursorPos(500, 500); | |
| 3285 | |
| 3286 HWND window = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(); | |
| 3287 | |
| 3288 SubclassWindowHelper subclass_helper(window); | |
| 3289 | |
| 3290 // Posting just a WM_NCLBUTTONDOWN message should not result in a | |
| 3291 // WM_SYSCOMMAND | |
| 3292 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3293 RunPendingMessages(); | |
| 3294 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3295 EXPECT_FALSE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3296 | |
| 3297 subclass_helper.Clear(); | |
| 3298 // Posting a WM_NCLBUTTONDOWN message followed by a WM_NCMOUSEMOVE at the | |
| 3299 // same location should not result in a WM_SYSCOMMAND message. | |
| 3300 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3301 ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3302 RunPendingMessages(); | |
| 3303 | |
| 3304 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3305 EXPECT_TRUE(subclass_helper.received_message(WM_NCMOUSEMOVE)); | |
| 3306 EXPECT_FALSE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3307 | |
| 3308 subclass_helper.Clear(); | |
| 3309 // Posting a WM_NCLBUTTONDOWN message followed by a WM_NCMOUSEMOVE at a | |
| 3310 // different location should result in a WM_SYSCOMMAND message. | |
| 3311 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3312 ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(110, 110)); | |
| 3313 RunPendingMessages(); | |
| 3314 | |
| 3315 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3316 EXPECT_TRUE(subclass_helper.received_message(WM_NCMOUSEMOVE)); | |
| 3317 EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3318 | |
| 3319 subclass_helper.Clear(); | |
| 3320 // Posting a WM_NCLBUTTONDOWN message followed by a WM_NCMOUSEMOVE at a | |
| 3321 // different location with a different hittest code should result in a | |
| 3322 // WM_SYSCOMMAND message. | |
| 3323 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3324 ::PostMessage(window, WM_NCMOUSEMOVE, HTTOP, MAKELPARAM(110, 102)); | |
| 3325 RunPendingMessages(); | |
| 3326 | |
| 3327 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3328 EXPECT_TRUE(subclass_helper.received_message(WM_NCMOUSEMOVE)); | |
| 3329 EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3330 | |
| 3331 subclass_helper.Clear(); | |
| 3332 // Posting a WM_NCLBUTTONDOWN message followed by a WM_MOUSEMOVE should | |
| 3333 // result in a WM_SYSCOMMAND message. | |
| 3334 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3335 ::PostMessage(window, WM_MOUSEMOVE, HTCLIENT, MAKELPARAM(110, 110)); | |
| 3336 RunPendingMessages(); | |
| 3337 | |
| 3338 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3339 EXPECT_TRUE(subclass_helper.received_message(WM_MOUSEMOVE)); | |
| 3340 EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3341 | |
| 3342 widget.CloseNow(); | |
| 3343 } | |
| 3344 | |
| 3345 // This test validates that destroying the window in the context of the | |
| 3346 // WM_SYSCOMMAND message with SC_MOVE does not crash. | |
| 3347 // Disabled because of flaky timeouts: http://crbug.com/592742 | |
| 3348 TEST_F(WidgetTest, DISABLED_DestroyInSysCommandNCLButtonDownOnCaption) { | |
| 3349 Widget widget; | |
| 3350 Widget::InitParams params = | |
| 3351 CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 3352 params.native_widget = | |
| 3353 CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr); | |
| 3354 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 3355 widget.Init(params); | |
| 3356 widget.SetBounds(gfx::Rect(0, 0, 200, 200)); | |
| 3357 widget.Show(); | |
| 3358 ::SetCursorPos(500, 500); | |
| 3359 | |
| 3360 HWND window = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(); | |
| 3361 | |
| 3362 SubclassWindowHelper subclass_helper(window); | |
| 3363 | |
| 3364 // Destroying the window in the context of the WM_SYSCOMMAND message | |
| 3365 // should not crash. | |
| 3366 subclass_helper.set_message_to_destroy_on(WM_SYSCOMMAND); | |
| 3367 | |
| 3368 ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100)); | |
| 3369 ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(110, 110)); | |
| 3370 RunPendingMessages(); | |
| 3371 | |
| 3372 EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN)); | |
| 3373 EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND)); | |
| 3374 | |
| 3375 widget.CloseNow(); | |
| 3376 } | |
| 3377 | |
| 3378 #endif | 3191 #endif |
| 3379 | 3192 |
| 3380 // Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent. | 3193 // Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent. |
| 3381 TEST_F(WidgetTest, AlwaysOnTop) { | 3194 TEST_F(WidgetTest, AlwaysOnTop) { |
| 3382 WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); | 3195 WidgetAutoclosePtr widget(CreateTopLevelNativeWidget()); |
| 3383 EXPECT_FALSE(widget->IsAlwaysOnTop()); | 3196 EXPECT_FALSE(widget->IsAlwaysOnTop()); |
| 3384 widget->SetAlwaysOnTop(true); | 3197 widget->SetAlwaysOnTop(true); |
| 3385 EXPECT_TRUE(widget->IsAlwaysOnTop()); | 3198 EXPECT_TRUE(widget->IsAlwaysOnTop()); |
| 3386 widget->SetAlwaysOnTop(false); | 3199 widget->SetAlwaysOnTop(false); |
| 3387 EXPECT_FALSE(widget->IsAlwaysOnTop()); | 3200 EXPECT_FALSE(widget->IsAlwaysOnTop()); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3497 // Moving the child to a different widget should call the removals observer. | 3310 // Moving the child to a different widget should call the removals observer. |
| 3498 WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); | 3311 WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget()); |
| 3499 widget2->client_view()->AddChildView(child); | 3312 widget2->client_view()->AddChildView(child); |
| 3500 EXPECT_TRUE(removals_observer.DidRemoveView(child)); | 3313 EXPECT_TRUE(removals_observer.DidRemoveView(child)); |
| 3501 | 3314 |
| 3502 widget->RemoveRemovalsObserver(&removals_observer); | 3315 widget->RemoveRemovalsObserver(&removals_observer); |
| 3503 } | 3316 } |
| 3504 | 3317 |
| 3505 } // namespace test | 3318 } // namespace test |
| 3506 } // namespace views | 3319 } // namespace views |
| OLD | NEW |