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 3 // found in the LICENSE file. 4 5 #include "content/browser/renderer_host/render_widget_host_view_aura.h" 6 7 #include "base/basictypes.h" 8 #include "base/memory/shared_memory.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "cc/output/compositor_frame.h" 12 #include "cc/output/compositor_frame_metadata.h" 13 #include "cc/output/gl_frame_data.h" 14 #include "content/browser/aura/resize_lock.h" 15 #include "content/browser/browser_thread_impl.h" 16 #include "content/browser/renderer_host/render_widget_host_delegate.h" 17 #include "content/browser/renderer_host/render_widget_host_impl.h" 18 #include "content/common/gpu/gpu_messages.h" 19 #include "content/common/input_messages.h" 20 #include "content/common/view_messages.h" 21 #include "content/public/browser/render_widget_host_view.h" 22 #include "content/public/test/mock_render_process_host.h" 23 #include "content/public/test/test_browser_context.h" 24 #include "ipc/ipc_test_sink.h" 25 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gtest/include/gtest/gtest.h" 27 #include "ui/aura/client/aura_constants.h" 28 #include "ui/aura/client/screen_position_client.h" 29 #include "ui/aura/client/window_tree_client.h" 30 #include "ui/aura/env.h" 31 #include "ui/aura/layout_manager.h" 32 #include "ui/aura/root_window.h" 33 #include "ui/aura/test/aura_test_helper.h" 34 #include "ui/aura/test/test_cursor_client.h" 35 #include "ui/aura/test/test_screen.h" 36 #include "ui/aura/test/test_window_delegate.h" 37 #include "ui/aura/window.h" 38 #include "ui/aura/window_observer.h" 39 #include "ui/base/ui_base_types.h" 40 #include "ui/compositor/compositor.h" 41 #include "ui/compositor/test/test_context_factory.h" 42 #include "ui/events/event.h" 43 #include "ui/events/event_utils.h" 44 45 using testing::_; 46 47 namespace content { 48 namespace { 49 50 // Simple screen position client to test coordinate system conversion. 51 class TestScreenPositionClient 52 : public aura::client::ScreenPositionClient { 53 public: 54 TestScreenPositionClient() {} 55 virtual ~TestScreenPositionClient() {} 56 57 // aura::client::ScreenPositionClient overrides: 58 virtual void ConvertPointToScreen(const aura::Window* window, 59 gfx::Point* point) OVERRIDE { 60 point->Offset(-1, -1); 61 } 62 63 virtual void ConvertPointFromScreen(const aura::Window* window, 64 gfx::Point* point) OVERRIDE { 65 point->Offset(1, 1); 66 } 67 68 virtual void ConvertHostPointToScreen(aura::Window* window, 69 gfx::Point* point) OVERRIDE { 70 ConvertPointToScreen(window, point); 71 } 72 73 virtual void SetBounds(aura::Window* window, 74 const gfx::Rect& bounds, 75 const gfx::Display& display) OVERRIDE { 76 } 77 }; 78 79 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate { 80 public: 81 MockRenderWidgetHostDelegate() {} 82 virtual ~MockRenderWidgetHostDelegate() {} 83 }; 84 85 // Simple observer that keeps track of changes to a window for tests. 86 class TestWindowObserver : public aura::WindowObserver { 87 public: 88 explicit TestWindowObserver(aura::Window* window_to_observe) 89 : window_(window_to_observe) { 90 window_->AddObserver(this); 91 } 92 virtual ~TestWindowObserver() { 93 if (window_) 94 window_->RemoveObserver(this); 95 } 96 97 bool destroyed() const { return destroyed_; } 98 99 // aura::WindowObserver overrides: 100 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { 101 CHECK_EQ(window, window_); 102 destroyed_ = true; 103 window_ = NULL; 104 } 105 106 private: 107 // Window that we're observing, or NULL if it's been destroyed. 108 aura::Window* window_; 109 110 // Was |window_| destroyed? 111 bool destroyed_; 112 113 DISALLOW_COPY_AND_ASSIGN(TestWindowObserver); 114 }; 115 116 class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura { 117 public: 118 FakeRenderWidgetHostViewAura(RenderWidgetHost* widget) 119 : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {} 120 121 virtual ~FakeRenderWidgetHostViewAura() {} 122 123 virtual bool ShouldCreateResizeLock() OVERRIDE { 124 gfx::Size desired_size = window()->bounds().size(); 125 return desired_size != current_frame_size(); 126 } 127 128 virtual scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) 129 OVERRIDE { 130 gfx::Size desired_size = window()->bounds().size(); 131 return scoped_ptr<ResizeLock>( 132 new FakeResizeLock(desired_size, defer_compositor_lock)); 133 } 134 135 void RunOnCompositingDidCommit() { 136 OnCompositingDidCommit(window()->GetDispatcher()->compositor()); 137 } 138 139 // A lock that doesn't actually do anything to the compositor, and does not 140 // time out. 141 class FakeResizeLock : public ResizeLock { 142 public: 143 FakeResizeLock(const gfx::Size new_size, bool defer_compositor_lock) 144 : ResizeLock(new_size, defer_compositor_lock) {} 145 }; 146 147 bool has_resize_lock_; 148 gfx::Size last_frame_size_; 149 }; 150 151 class RenderWidgetHostViewAuraTest : public testing::Test { 152 public: 153 RenderWidgetHostViewAuraTest() 154 : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {} 155 156 virtual void SetUp() { 157 ImageTransportFactory::InitializeForUnitTests( 158 scoped_ptr<ui::ContextFactory>(new ui::TestContextFactory)); 159 aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_)); 160 aura_test_helper_->SetUp(); 161 162 browser_context_.reset(new TestBrowserContext); 163 process_host_ = new MockRenderProcessHost(browser_context_.get()); 164 165 sink_ = &process_host_->sink(); 166 167 parent_host_ = new RenderWidgetHostImpl( 168 &delegate_, process_host_, MSG_ROUTING_NONE, false); 169 parent_view_ = static_cast<RenderWidgetHostViewAura*>( 170 RenderWidgetHostView::CreateViewForWidget(parent_host_)); 171 parent_view_->InitAsChild(NULL); 172 aura::client::ParentWindowWithContext(parent_view_->GetNativeView(), 173 aura_test_helper_->root_window(), 174 gfx::Rect()); 175 176 widget_host_ = new RenderWidgetHostImpl( 177 &delegate_, process_host_, MSG_ROUTING_NONE, false); 178 widget_host_->Init(); 179 widget_host_->OnMessageReceived( 180 ViewHostMsg_DidActivateAcceleratedCompositing(0, true)); 181 view_ = new FakeRenderWidgetHostViewAura(widget_host_); 182 } 183 184 virtual void TearDown() { 185 sink_ = NULL; 186 process_host_ = NULL; 187 if (view_) 188 view_->Destroy(); 189 delete widget_host_; 190 191 parent_view_->Destroy(); 192 delete parent_host_; 193 194 browser_context_.reset(); 195 aura_test_helper_->TearDown(); 196 197 message_loop_.DeleteSoon(FROM_HERE, browser_context_.release()); 198 message_loop_.RunUntilIdle(); 199 ImageTransportFactory::Terminate(); 200 } 201 202 protected: 203 base::MessageLoopForUI message_loop_; 204 BrowserThreadImpl browser_thread_for_ui_; 205 scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_; 206 scoped_ptr<BrowserContext> browser_context_; 207 MockRenderWidgetHostDelegate delegate_; 208 MockRenderProcessHost* process_host_; 209 210 // Tests should set these to NULL if they've already triggered their 211 // destruction. 212 RenderWidgetHostImpl* parent_host_; 213 RenderWidgetHostViewAura* parent_view_; 214 215 // Tests should set these to NULL if they've already triggered their 216 // destruction. 217 RenderWidgetHostImpl* widget_host_; 218 FakeRenderWidgetHostViewAura* view_; 219 220 IPC::TestSink* sink_; 221 222 private: 223 DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraTest); 224 }; 225 226 // A layout manager that always resizes a child to the root window size. 227 class FullscreenLayoutManager : public aura::LayoutManager { 228 public: 229 explicit FullscreenLayoutManager(aura::Window* owner) 230 : owner_(owner) {} 231 virtual ~FullscreenLayoutManager() {} 232 233 // Overridden from aura::LayoutManager: 234 virtual void OnWindowResized() OVERRIDE { 235 aura::Window::Windows::const_iterator i; 236 for (i = owner_->children().begin(); i != owner_->children().end(); ++i) { 237 (*i)->SetBounds(gfx::Rect()); 238 } 239 } 240 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE { 241 child->SetBounds(gfx::Rect()); 242 } 243 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE { 244 } 245 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE { 246 } 247 virtual void OnChildWindowVisibilityChanged(aura::Window* child, 248 bool visible) OVERRIDE { 249 } 250 virtual void SetChildBounds(aura::Window* child, 251 const gfx::Rect& requested_bounds) OVERRIDE { 252 SetChildBoundsDirect(child, gfx::Rect(owner_->bounds().size())); 253 } 254 255 private: 256 aura::Window* owner_; 257 DISALLOW_COPY_AND_ASSIGN(FullscreenLayoutManager); 258 }; 259 260 class MockWindowObserver : public aura::WindowObserver { 261 public: 262 MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&)); 263 }; 264 265 } // namespace 266 267 // Checks that a fullscreen view has the correct show-state and receives the 268 // focus. 269 TEST_F(RenderWidgetHostViewAuraTest, FocusFullscreen) { 270 view_->InitAsFullscreen(parent_view_); 271 aura::Window* window = view_->GetNativeView(); 272 ASSERT_TRUE(window != NULL); 273 EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, 274 window->GetProperty(aura::client::kShowStateKey)); 275 276 // Check that we requested and received the focus. 277 EXPECT_TRUE(window->HasFocus()); 278 279 // Check that we'll also say it's okay to activate the window when there's an 280 // ActivationClient defined. 281 EXPECT_TRUE(view_->ShouldActivate()); 282 } 283 284 // Checks that a popup is positioned correctly relative to its parent using 285 // screen coordinates. 286 TEST_F(RenderWidgetHostViewAuraTest, PositionChildPopup) { 287 TestScreenPositionClient screen_position_client; 288 289 aura::Window* window = parent_view_->GetNativeView(); 290 aura::Window* root = window->GetRootWindow(); 291 aura::client::SetScreenPositionClient(root, &screen_position_client); 292 293 parent_view_->SetBounds(gfx::Rect(10, 10, 800, 600)); 294 gfx::Rect bounds_in_screen = parent_view_->GetViewBounds(); 295 int horiz = bounds_in_screen.width() / 4; 296 int vert = bounds_in_screen.height() / 4; 297 bounds_in_screen.Inset(horiz, vert); 298 299 // Verify that when the popup is initialized for the first time, it correctly 300 // treats the input bounds as screen coordinates. 301 view_->InitAsPopup(parent_view_, bounds_in_screen); 302 303 gfx::Rect final_bounds_in_screen = view_->GetViewBounds(); 304 EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString()); 305 306 // Verify that directly setting the bounds via SetBounds() treats the input 307 // as screen coordinates. 308 bounds_in_screen = gfx::Rect(60, 60, 100, 100); 309 view_->SetBounds(bounds_in_screen); 310 final_bounds_in_screen = view_->GetViewBounds(); 311 EXPECT_EQ(final_bounds_in_screen.ToString(), bounds_in_screen.ToString()); 312 313 // Verify that setting the size does not alter the origin. 314 gfx::Point original_origin = window->bounds().origin(); 315 view_->SetSize(gfx::Size(120, 120)); 316 gfx::Point new_origin = window->bounds().origin(); 317 EXPECT_EQ(original_origin.ToString(), new_origin.ToString()); 318 319 aura::client::SetScreenPositionClient(root, NULL); 320 } 321 322 // Checks that a fullscreen view is destroyed when it loses the focus. 323 TEST_F(RenderWidgetHostViewAuraTest, DestroyFullscreenOnBlur) { 324 view_->InitAsFullscreen(parent_view_); 325 aura::Window* window = view_->GetNativeView(); 326 ASSERT_TRUE(window != NULL); 327 ASSERT_TRUE(window->HasFocus()); 328 329 // After we create and focus another window, the RWHVA's window should be 330 // destroyed. 331 TestWindowObserver observer(window); 332 aura::test::TestWindowDelegate delegate; 333 scoped_ptr<aura::Window> sibling(new aura::Window(&delegate)); 334 sibling->Init(ui::LAYER_TEXTURED); 335 sibling->Show(); 336 window->parent()->AddChild(sibling.get()); 337 sibling->Focus(); 338 ASSERT_TRUE(sibling->HasFocus()); 339 ASSERT_TRUE(observer.destroyed()); 340 341 widget_host_ = NULL; 342 view_ = NULL; 343 } 344 345 // Checks that IME-composition-event state is maintained correctly. 346 TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) { 347 view_->InitAsChild(NULL); 348 view_->Show(); 349 350 ui::CompositionText composition_text; 351 composition_text.text = ASCIIToUTF16("|a|b"); 352 353 // Focused segment 354 composition_text.underlines.push_back( 355 ui::CompositionUnderline(0, 3, 0xff000000, true)); 356 357 // Non-focused segment 358 composition_text.underlines.push_back( 359 ui::CompositionUnderline(3, 4, 0xff000000, false)); 360 361 const ui::CompositionUnderlines& underlines = composition_text.underlines; 362 363 // Caret is at the end. (This emulates Japanese MSIME 2007 and later) 364 composition_text.selection = gfx::Range(4); 365 366 sink_->ClearMessages(); 367 view_->SetCompositionText(composition_text); 368 EXPECT_TRUE(view_->has_composition_text_); 369 { 370 const IPC::Message* msg = 371 sink_->GetFirstMessageMatching(ViewMsg_ImeSetComposition::ID); 372 ASSERT_TRUE(msg != NULL); 373 374 ViewMsg_ImeSetComposition::Param params; 375 ViewMsg_ImeSetComposition::Read(msg, ¶ms); 376 // composition text 377 EXPECT_EQ(composition_text.text, params.a); 378 // underlines 379 ASSERT_EQ(underlines.size(), params.b.size()); 380 for (size_t i = 0; i < underlines.size(); ++i) { 381 EXPECT_EQ(underlines[i].start_offset, params.b[i].startOffset); 382 EXPECT_EQ(underlines[i].end_offset, params.b[i].endOffset); 383 EXPECT_EQ(underlines[i].color, params.b[i].color); 384 EXPECT_EQ(underlines[i].thick, params.b[i].thick); 385 } 386 // highlighted range 387 EXPECT_EQ(4, params.c) << "Should be the same to the caret pos"; 388 EXPECT_EQ(4, params.d) << "Should be the same to the caret pos"; 389 } 390 391 view_->ImeCancelComposition(); 392 EXPECT_FALSE(view_->has_composition_text_); 393 } 394 395 // Checks that touch-event state is maintained correctly. 396 TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { 397 view_->InitAsChild(NULL); 398 view_->Show(); 399 400 // Start with no touch-event handler in the renderer. 401 widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); 402 EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent()); 403 404 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 405 gfx::Point(30, 30), 406 0, 407 ui::EventTimeForNow()); 408 ui::TouchEvent move(ui::ET_TOUCH_MOVED, 409 gfx::Point(20, 20), 410 0, 411 ui::EventTimeForNow()); 412 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, 413 gfx::Point(20, 20), 414 0, 415 ui::EventTimeForNow()); 416 417 view_->OnTouchEvent(&press); 418 EXPECT_FALSE(press.handled()); 419 EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type); 420 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 421 EXPECT_EQ(blink::WebTouchPoint::StatePressed, 422 view_->touch_event_.touches[0].state); 423 424 view_->OnTouchEvent(&move); 425 EXPECT_FALSE(move.handled()); 426 EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type); 427 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 428 EXPECT_EQ(blink::WebTouchPoint::StateMoved, 429 view_->touch_event_.touches[0].state); 430 431 view_->OnTouchEvent(&release); 432 EXPECT_FALSE(release.handled()); 433 EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type); 434 EXPECT_EQ(0U, view_->touch_event_.touchesLength); 435 436 // Now install some touch-event handlers and do the same steps. The touch 437 // events should now be consumed. However, the touch-event state should be 438 // updated as before. 439 widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); 440 EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); 441 442 view_->OnTouchEvent(&press); 443 EXPECT_TRUE(press.stopped_propagation()); 444 EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type); 445 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 446 EXPECT_EQ(blink::WebTouchPoint::StatePressed, 447 view_->touch_event_.touches[0].state); 448 449 view_->OnTouchEvent(&move); 450 EXPECT_TRUE(move.stopped_propagation()); 451 EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type); 452 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 453 EXPECT_EQ(blink::WebTouchPoint::StateMoved, 454 view_->touch_event_.touches[0].state); 455 456 view_->OnTouchEvent(&release); 457 EXPECT_TRUE(release.stopped_propagation()); 458 EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type); 459 EXPECT_EQ(0U, view_->touch_event_.touchesLength); 460 461 // Now start a touch event, and remove the event-handlers before the release. 462 view_->OnTouchEvent(&press); 463 EXPECT_TRUE(press.stopped_propagation()); 464 EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type); 465 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 466 EXPECT_EQ(blink::WebTouchPoint::StatePressed, 467 view_->touch_event_.touches[0].state); 468 469 widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); 470 EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent()); 471 472 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0, 473 base::Time::NowFromSystemTime() - base::Time()); 474 view_->OnTouchEvent(&move2); 475 EXPECT_FALSE(move2.handled()); 476 EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type); 477 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 478 EXPECT_EQ(blink::WebTouchPoint::StateMoved, 479 view_->touch_event_.touches[0].state); 480 481 ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0, 482 base::Time::NowFromSystemTime() - base::Time()); 483 view_->OnTouchEvent(&release2); 484 EXPECT_FALSE(release2.handled()); 485 EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type); 486 EXPECT_EQ(0U, view_->touch_event_.touchesLength); 487 } 488 489 // Checks that touch-events are queued properly when there is a touch-event 490 // handler on the page. 491 TEST_F(RenderWidgetHostViewAuraTest, TouchEventSyncAsync) { 492 view_->InitAsChild(NULL); 493 view_->Show(); 494 495 widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); 496 EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); 497 498 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, 499 gfx::Point(30, 30), 500 0, 501 ui::EventTimeForNow()); 502 ui::TouchEvent move(ui::ET_TOUCH_MOVED, 503 gfx::Point(20, 20), 504 0, 505 ui::EventTimeForNow()); 506 ui::TouchEvent release(ui::ET_TOUCH_RELEASED, 507 gfx::Point(20, 20), 508 0, 509 ui::EventTimeForNow()); 510 511 view_->OnTouchEvent(&press); 512 EXPECT_TRUE(press.stopped_propagation()); 513 EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_.type); 514 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 515 EXPECT_EQ(blink::WebTouchPoint::StatePressed, 516 view_->touch_event_.touches[0].state); 517 518 view_->OnTouchEvent(&move); 519 EXPECT_TRUE(move.stopped_propagation()); 520 EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type); 521 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 522 EXPECT_EQ(blink::WebTouchPoint::StateMoved, 523 view_->touch_event_.touches[0].state); 524 525 // Send the same move event. Since the point hasn't moved, it won't affect the 526 // queue. However, the view should consume the event. 527 view_->OnTouchEvent(&move); 528 EXPECT_TRUE(move.stopped_propagation()); 529 EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_.type); 530 EXPECT_EQ(1U, view_->touch_event_.touchesLength); 531 EXPECT_EQ(blink::WebTouchPoint::StateMoved, 532 view_->touch_event_.touches[0].state); 533 534 view_->OnTouchEvent(&release); 535 EXPECT_TRUE(release.stopped_propagation()); 536 EXPECT_EQ(blink::WebInputEvent::TouchEnd, view_->touch_event_.type); 537 EXPECT_EQ(0U, view_->touch_event_.touchesLength); 538 } 539 540 TEST_F(RenderWidgetHostViewAuraTest, PhysicalBackingSizeWithScale) { 541 view_->InitAsChild(NULL); 542 aura::client::ParentWindowWithContext( 543 view_->GetNativeView(), 544 parent_view_->GetNativeView()->GetRootWindow(), 545 gfx::Rect()); 546 sink_->ClearMessages(); 547 view_->SetSize(gfx::Size(100, 100)); 548 EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString()); 549 EXPECT_EQ(1u, sink_->message_count()); 550 EXPECT_EQ(ViewMsg_Resize::ID, sink_->GetMessageAt(0)->type()); 551 { 552 const IPC::Message* msg = sink_->GetMessageAt(0); 553 EXPECT_EQ(ViewMsg_Resize::ID, msg->type()); 554 ViewMsg_Resize::Param params; 555 ViewMsg_Resize::Read(msg, ¶ms); 556 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size 557 EXPECT_EQ("100x100", 558 params.a.physical_backing_size.ToString()); // backing size 559 } 560 561 widget_host_->ResetSizeAndRepaintPendingFlags(); 562 sink_->ClearMessages(); 563 564 aura_test_helper_->test_screen()->SetDeviceScaleFactor(2.0f); 565 EXPECT_EQ("200x200", view_->GetPhysicalBackingSize().ToString()); 566 // Extra ScreenInfoChanged message for |parent_view_|. 567 EXPECT_EQ(1u, sink_->message_count()); 568 { 569 const IPC::Message* msg = sink_->GetMessageAt(0); 570 EXPECT_EQ(ViewMsg_Resize::ID, msg->type()); 571 ViewMsg_Resize::Param params; 572 ViewMsg_Resize::Read(msg, ¶ms); 573 EXPECT_EQ(2.0f, params.a.screen_info.deviceScaleFactor); 574 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size 575 EXPECT_EQ("200x200", 576 params.a.physical_backing_size.ToString()); // backing size 577 } 578 579 widget_host_->ResetSizeAndRepaintPendingFlags(); 580 sink_->ClearMessages(); 581 582 aura_test_helper_->test_screen()->SetDeviceScaleFactor(1.0f); 583 // Extra ScreenInfoChanged message for |parent_view_|. 584 EXPECT_EQ(1u, sink_->message_count()); 585 EXPECT_EQ("100x100", view_->GetPhysicalBackingSize().ToString()); 586 { 587 const IPC::Message* msg = sink_->GetMessageAt(0); 588 EXPECT_EQ(ViewMsg_Resize::ID, msg->type()); 589 ViewMsg_Resize::Param params; 590 ViewMsg_Resize::Read(msg, ¶ms); 591 EXPECT_EQ(1.0f, params.a.screen_info.deviceScaleFactor); 592 EXPECT_EQ("100x100", params.a.new_size.ToString()); // dip size 593 EXPECT_EQ("100x100", 594 params.a.physical_backing_size.ToString()); // backing size 595 } 596 } 597 598 // Checks that InputMsg_CursorVisibilityChange IPC messages are dispatched 599 // to the renderer at the correct times. 600 TEST_F(RenderWidgetHostViewAuraTest, CursorVisibilityChange) { 601 view_->InitAsChild(NULL); 602 aura::client::ParentWindowWithContext( 603 view_->GetNativeView(), 604 parent_view_->GetNativeView()->GetRootWindow(), 605 gfx::Rect()); 606 view_->SetSize(gfx::Size(100, 100)); 607 608 aura::test::TestCursorClient cursor_client( 609 parent_view_->GetNativeView()->GetRootWindow()); 610 611 cursor_client.AddObserver(view_); 612 613 // Expect a message the first time the cursor is shown. 614 view_->WasShown(); 615 sink_->ClearMessages(); 616 cursor_client.ShowCursor(); 617 EXPECT_EQ(1u, sink_->message_count()); 618 EXPECT_TRUE(sink_->GetUniqueMessageMatching( 619 InputMsg_CursorVisibilityChange::ID)); 620 621 // No message expected if the renderer already knows the cursor is visible. 622 sink_->ClearMessages(); 623 cursor_client.ShowCursor(); 624 EXPECT_EQ(0u, sink_->message_count()); 625 626 // Hiding the cursor should send a message. 627 sink_->ClearMessages(); 628 cursor_client.HideCursor(); 629 EXPECT_EQ(1u, sink_->message_count()); 630 EXPECT_TRUE(sink_->GetUniqueMessageMatching( 631 InputMsg_CursorVisibilityChange::ID)); 632 633 // No message expected if the renderer already knows the cursor is invisible. 634 sink_->ClearMessages(); 635 cursor_client.HideCursor(); 636 EXPECT_EQ(0u, sink_->message_count()); 637 638 // No messages should be sent while the view is invisible. 639 view_->WasHidden(); 640 sink_->ClearMessages(); 641 cursor_client.ShowCursor(); 642 EXPECT_EQ(0u, sink_->message_count()); 643 cursor_client.HideCursor(); 644 EXPECT_EQ(0u, sink_->message_count()); 645 646 // Show the view. Since the cursor was invisible when the view was hidden, 647 // no message should be sent. 648 sink_->ClearMessages(); 649 view_->WasShown(); 650 EXPECT_FALSE(sink_->GetUniqueMessageMatching( 651 InputMsg_CursorVisibilityChange::ID)); 652 653 // No message expected if the renderer already knows the cursor is invisible. 654 sink_->ClearMessages(); 655 cursor_client.HideCursor(); 656 EXPECT_EQ(0u, sink_->message_count()); 657 658 // Showing the cursor should send a message. 659 sink_->ClearMessages(); 660 cursor_client.ShowCursor(); 661 EXPECT_EQ(1u, sink_->message_count()); 662 EXPECT_TRUE(sink_->GetUniqueMessageMatching( 663 InputMsg_CursorVisibilityChange::ID)); 664 665 // No messages should be sent while the view is invisible. 666 view_->WasHidden(); 667 sink_->ClearMessages(); 668 cursor_client.HideCursor(); 669 EXPECT_EQ(0u, sink_->message_count()); 670 671 // Show the view. Since the cursor was visible when the view was hidden, 672 // a message is expected to be sent. 673 sink_->ClearMessages(); 674 view_->WasShown(); 675 EXPECT_TRUE(sink_->GetUniqueMessageMatching( 676 InputMsg_CursorVisibilityChange::ID)); 677 678 cursor_client.RemoveObserver(view_); 679 } 680 681 scoped_ptr<cc::CompositorFrame> MakeGLFrame(float scale_factor, 682 gfx::Size size, 683 gfx::Rect damage) { 684 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame); 685 frame->metadata.device_scale_factor = scale_factor; 686 frame->gl_frame_data.reset(new cc::GLFrameData); 687 frame->gl_frame_data->sync_point = 1; 688 memset(frame->gl_frame_data->mailbox.name, '1', 64); 689 frame->gl_frame_data->size = size; 690 frame->gl_frame_data->sub_buffer_rect = damage; 691 return frame.Pass(); 692 } 693 694 scoped_ptr<cc::CompositorFrame> MakeSoftwareFrame(float scale_factor, 695 gfx::Size size, 696 gfx::Rect damage) { 697 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame); 698 frame->metadata.device_scale_factor = scale_factor; 699 frame->software_frame_data.reset(new cc::SoftwareFrameData); 700 frame->software_frame_data->id = 1; 701 frame->software_frame_data->size = size; 702 frame->software_frame_data->damage_rect = damage; 703 base::SharedMemory shm; 704 shm.CreateAndMapAnonymous(size.GetArea() * 4); 705 shm.GiveToProcess(base::GetCurrentProcessHandle(), 706 &frame->software_frame_data->handle); 707 return frame.Pass(); 708 } 709 710 scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor, 711 gfx::Size size, 712 gfx::Rect damage) { 713 scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame); 714 frame->metadata.device_scale_factor = scale_factor; 715 frame->delegated_frame_data.reset(new cc::DelegatedFrameData); 716 717 scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create(); 718 pass->SetNew(cc::RenderPass::Id(1, 1), 719 gfx::Rect(size), 720 gfx::RectF(damage), 721 gfx::Transform()); 722 frame->delegated_frame_data->render_pass_list.push_back(pass.Pass()); 723 return frame.Pass(); 724 } 725 726 // Resizing in fullscreen mode should send the up-to-date screen info. 727 TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) { 728 aura::Window* root_window = aura_test_helper_->root_window(); 729 root_window->SetLayoutManager(new FullscreenLayoutManager(root_window)); 730 view_->InitAsFullscreen(parent_view_); 731 view_->WasShown(); 732 widget_host_->ResetSizeAndRepaintPendingFlags(); 733 sink_->ClearMessages(); 734 735 // Call WasResized to flush the old screen info. 736 view_->GetRenderWidgetHost()->WasResized(); 737 { 738 // 0 is CreatingNew message. 739 const IPC::Message* msg = sink_->GetMessageAt(0); 740 EXPECT_EQ(ViewMsg_Resize::ID, msg->type()); 741 ViewMsg_Resize::Param params; 742 ViewMsg_Resize::Read(msg, ¶ms); 743 EXPECT_EQ("0,0 800x600", 744 gfx::Rect(params.a.screen_info.availableRect).ToString()); 745 EXPECT_EQ("800x600", params.a.new_size.ToString()); 746 // Resizes are blocked until we swapped a frame of the correct size, and 747 // we've committed it. 748 view_->OnSwapCompositorFrame( 749 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size))); 750 ui::DrawWaiterForTest::WaitForCommit( 751 root_window->GetDispatcher()->compositor()); 752 } 753 754 widget_host_->ResetSizeAndRepaintPendingFlags(); 755 sink_->ClearMessages(); 756 757 // Make sure the corrent screen size is set along in the resize 758 // request when the screen size has changed. 759 aura_test_helper_->test_screen()->SetUIScale(0.5); 760 EXPECT_EQ(1u, sink_->message_count()); 761 { 762 const IPC::Message* msg = sink_->GetMessageAt(0); 763 EXPECT_EQ(ViewMsg_Resize::ID, msg->type()); 764 ViewMsg_Resize::Param params; 765 ViewMsg_Resize::Read(msg, ¶ms); 766 EXPECT_EQ("0,0 1600x1200", 767 gfx::Rect(params.a.screen_info.availableRect).ToString()); 768 EXPECT_EQ("1600x1200", params.a.new_size.ToString()); 769 view_->OnSwapCompositorFrame( 770 0, MakeGLFrame(1.f, params.a.new_size, gfx::Rect(params.a.new_size))); 771 ui::DrawWaiterForTest::WaitForCommit( 772 root_window->GetDispatcher()->compositor()); 773 } 774 } 775 776 // Swapping a frame should notify the window. 777 TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) { 778 gfx::Size view_size(100, 100); 779 gfx::Rect view_rect(view_size); 780 781 view_->InitAsChild(NULL); 782 aura::client::ParentWindowWithContext( 783 view_->GetNativeView(), 784 parent_view_->GetNativeView()->GetRootWindow(), 785 gfx::Rect()); 786 view_->SetSize(view_size); 787 view_->WasShown(); 788 789 MockWindowObserver observer; 790 view_->window_->AddObserver(&observer); 791 792 // Swap a frame through the GPU path. 793 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; 794 params.surface_id = widget_host_->surface_id(); 795 params.route_id = widget_host_->GetRoutingID(); 796 params.mailbox_name = std::string(64, '1'); 797 params.size = view_size; 798 params.scale_factor = 1.f; 799 800 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 801 view_->AcceleratedSurfaceBuffersSwapped(params, 0); 802 testing::Mock::VerifyAndClearExpectations(&observer); 803 804 // DSF = 2 805 params.size = gfx::Size(200, 200); 806 params.scale_factor = 2.f; 807 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 808 view_->AcceleratedSurfaceBuffersSwapped(params, 0); 809 testing::Mock::VerifyAndClearExpectations(&observer); 810 811 // Partial frames though GPU path 812 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params post_params; 813 post_params.surface_id = widget_host_->surface_id(); 814 post_params.route_id = widget_host_->GetRoutingID(); 815 post_params.mailbox_name = std::string(64, '1'); 816 post_params.surface_size = gfx::Size(200, 200); 817 post_params.surface_scale_factor = 2.f; 818 post_params.x = 40; 819 post_params.y = 40; 820 post_params.width = 80; 821 post_params.height = 80; 822 // rect from params is upside down, and is inflated in RWHVA, just because. 823 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, 824 gfx::Rect(19, 39, 42, 42))); 825 view_->AcceleratedSurfacePostSubBuffer(post_params, 0); 826 testing::Mock::VerifyAndClearExpectations(&observer); 827 828 // Composite-to-mailbox path 829 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 830 view_->OnSwapCompositorFrame(0, MakeGLFrame(1.f, view_size, view_rect)); 831 testing::Mock::VerifyAndClearExpectations(&observer); 832 833 // rect from GL frame is upside down, and is inflated in RWHVA, just because. 834 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, 835 gfx::Rect(4, 89, 7, 7))); 836 view_->OnSwapCompositorFrame( 837 0, MakeGLFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5))); 838 testing::Mock::VerifyAndClearExpectations(&observer); 839 840 // Software path 841 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 842 view_->OnSwapCompositorFrame(0, MakeSoftwareFrame(1.f, view_size, view_rect)); 843 testing::Mock::VerifyAndClearExpectations(&observer); 844 845 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, 846 gfx::Rect(5, 5, 5, 5))); 847 view_->OnSwapCompositorFrame( 848 0, MakeSoftwareFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5))); 849 testing::Mock::VerifyAndClearExpectations(&observer); 850 851 // Delegated renderer path 852 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 853 view_->OnSwapCompositorFrame( 854 0, MakeDelegatedFrame(1.f, view_size, view_rect)); 855 testing::Mock::VerifyAndClearExpectations(&observer); 856 857 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, 858 gfx::Rect(5, 5, 5, 5))); 859 view_->OnSwapCompositorFrame( 860 0, MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5))); 861 testing::Mock::VerifyAndClearExpectations(&observer); 862 863 view_->window_->RemoveObserver(&observer); 864 } 865 866 // Skipped frames should not drop their damage. 867 TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) { 868 gfx::Rect view_rect(100, 100); 869 gfx::Size frame_size = view_rect.size(); 870 871 view_->InitAsChild(NULL); 872 aura::client::ParentWindowWithContext( 873 view_->GetNativeView(), 874 parent_view_->GetNativeView()->GetRootWindow(), 875 gfx::Rect()); 876 view_->SetSize(view_rect.size()); 877 878 MockWindowObserver observer; 879 view_->window_->AddObserver(&observer); 880 881 // A full frame of damage. 882 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 883 view_->OnSwapCompositorFrame( 884 0, MakeDelegatedFrame(1.f, frame_size, view_rect)); 885 testing::Mock::VerifyAndClearExpectations(&observer); 886 view_->RunOnCompositingDidCommit(); 887 888 // A partial damage frame. 889 gfx::Rect partial_view_rect(30, 30, 20, 20); 890 EXPECT_CALL(observer, 891 OnWindowPaintScheduled(view_->window_, partial_view_rect)); 892 view_->OnSwapCompositorFrame( 893 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect)); 894 testing::Mock::VerifyAndClearExpectations(&observer); 895 view_->RunOnCompositingDidCommit(); 896 897 // Lock the compositor. Now we should drop frames. 898 view_rect = gfx::Rect(150, 150); 899 view_->SetSize(view_rect.size()); 900 view_->MaybeCreateResizeLock(); 901 902 // This frame is dropped. 903 gfx::Rect dropped_damage_rect_1(10, 20, 30, 40); 904 EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0); 905 view_->OnSwapCompositorFrame( 906 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1)); 907 testing::Mock::VerifyAndClearExpectations(&observer); 908 view_->RunOnCompositingDidCommit(); 909 910 gfx::Rect dropped_damage_rect_2(40, 50, 10, 20); 911 EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0); 912 view_->OnSwapCompositorFrame( 913 0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2)); 914 testing::Mock::VerifyAndClearExpectations(&observer); 915 view_->RunOnCompositingDidCommit(); 916 917 // Unlock the compositor. This frame should damage everything. 918 frame_size = view_rect.size(); 919 920 gfx::Rect new_damage_rect(5, 6, 10, 10); 921 EXPECT_CALL(observer, 922 OnWindowPaintScheduled(view_->window_, view_rect)); 923 view_->OnSwapCompositorFrame( 924 0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect)); 925 testing::Mock::VerifyAndClearExpectations(&observer); 926 view_->RunOnCompositingDidCommit(); 927 928 // A partial damage frame, this should not be dropped. 929 EXPECT_CALL(observer, 930 OnWindowPaintScheduled(view_->window_, partial_view_rect)); 931 view_->OnSwapCompositorFrame( 932 0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect)); 933 testing::Mock::VerifyAndClearExpectations(&observer); 934 view_->RunOnCompositingDidCommit(); 935 936 937 view_->window_->RemoveObserver(&observer); 938 } 939 940 TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) { 941 gfx::Rect view_rect(100, 100); 942 gfx::Size frame_size = view_rect.size(); 943 944 view_->InitAsChild(NULL); 945 aura::client::ParentWindowWithContext( 946 view_->GetNativeView(), 947 parent_view_->GetNativeView()->GetRootWindow(), 948 gfx::Rect()); 949 view_->SetSize(view_rect.size()); 950 951 MockWindowObserver observer; 952 view_->window_->AddObserver(&observer); 953 954 // Swap a frame. 955 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 956 view_->OnSwapCompositorFrame( 957 0, MakeDelegatedFrame(1.f, frame_size, view_rect)); 958 testing::Mock::VerifyAndClearExpectations(&observer); 959 view_->RunOnCompositingDidCommit(); 960 961 // Swap a frame with a different surface id. 962 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 963 view_->OnSwapCompositorFrame( 964 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 965 testing::Mock::VerifyAndClearExpectations(&observer); 966 view_->RunOnCompositingDidCommit(); 967 968 // Swap an empty frame, with a different surface id. 969 view_->OnSwapCompositorFrame( 970 2, MakeDelegatedFrame(1.f, gfx::Size(), gfx::Rect())); 971 testing::Mock::VerifyAndClearExpectations(&observer); 972 view_->RunOnCompositingDidCommit(); 973 974 // Swap another frame, with a different surface id. 975 EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect)); 976 view_->OnSwapCompositorFrame(3, 977 MakeDelegatedFrame(1.f, frame_size, view_rect)); 978 testing::Mock::VerifyAndClearExpectations(&observer); 979 view_->RunOnCompositingDidCommit(); 980 981 view_->window_->RemoveObserver(&observer); 982 } 983 984 TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) { 985 size_t max_renderer_frames = 986 RendererFrameManager::GetInstance()->max_number_of_saved_frames(); 987 ASSERT_LE(2u, max_renderer_frames); 988 size_t renderer_count = max_renderer_frames + 1; 989 gfx::Rect view_rect(100, 100); 990 gfx::Size frame_size = view_rect.size(); 991 992 scoped_ptr<RenderWidgetHostImpl * []> hosts( 993 new RenderWidgetHostImpl* [renderer_count]); 994 scoped_ptr<FakeRenderWidgetHostViewAura * []> views( 995 new FakeRenderWidgetHostViewAura* [renderer_count]); 996 997 // Create a bunch of renderers. 998 for (size_t i = 0; i < renderer_count; ++i) { 999 hosts[i] = new RenderWidgetHostImpl( 1000 &delegate_, process_host_, MSG_ROUTING_NONE, false); 1001 hosts[i]->Init(); 1002 hosts[i]->OnMessageReceived( 1003 ViewHostMsg_DidActivateAcceleratedCompositing(0, true)); 1004 views[i] = new FakeRenderWidgetHostViewAura(hosts[i]); 1005 views[i]->InitAsChild(NULL); 1006 aura::client::ParentWindowWithContext( 1007 views[i]->GetNativeView(), 1008 parent_view_->GetNativeView()->GetRootWindow(), 1009 gfx::Rect()); 1010 views[i]->SetSize(view_rect.size()); 1011 } 1012 1013 // Make each renderer visible, and swap a frame on it, then make it invisible. 1014 for (size_t i = 0; i < renderer_count; ++i) { 1015 views[i]->WasShown(); 1016 views[i]->OnSwapCompositorFrame( 1017 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1018 EXPECT_TRUE(views[i]->frame_provider_); 1019 views[i]->WasHidden(); 1020 } 1021 1022 // There should be max_renderer_frames with a frame in it, and one without it. 1023 // Since the logic is LRU eviction, the first one should be without. 1024 EXPECT_FALSE(views[0]->frame_provider_); 1025 for (size_t i = 1; i < renderer_count; ++i) 1026 EXPECT_TRUE(views[i]->frame_provider_); 1027 1028 // LRU renderer is [0], make it visible, it shouldn't evict anything yet. 1029 views[0]->WasShown(); 1030 EXPECT_FALSE(views[0]->frame_provider_); 1031 EXPECT_TRUE(views[1]->frame_provider_); 1032 1033 // Swap a frame on it, it should evict the next LRU [1]. 1034 views[0]->OnSwapCompositorFrame( 1035 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1036 EXPECT_TRUE(views[0]->frame_provider_); 1037 EXPECT_FALSE(views[1]->frame_provider_); 1038 views[0]->WasHidden(); 1039 1040 // LRU renderer is [1], still hidden. Swap a frame on it, it should evict 1041 // the next LRU [2]. 1042 views[1]->OnSwapCompositorFrame( 1043 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1044 EXPECT_TRUE(views[0]->frame_provider_); 1045 EXPECT_TRUE(views[1]->frame_provider_); 1046 EXPECT_FALSE(views[2]->frame_provider_); 1047 for (size_t i = 3; i < renderer_count; ++i) 1048 EXPECT_TRUE(views[i]->frame_provider_); 1049 1050 // Make all renderers but [0] visible and swap a frame on them, keep [0] 1051 // hidden, it becomes the LRU. 1052 for (size_t i = 1; i < renderer_count; ++i) { 1053 views[i]->WasShown(); 1054 views[i]->OnSwapCompositorFrame( 1055 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1056 EXPECT_TRUE(views[i]->frame_provider_); 1057 } 1058 EXPECT_FALSE(views[0]->frame_provider_); 1059 1060 // Swap a frame on [0], it should be evicted immediately. 1061 views[0]->OnSwapCompositorFrame( 1062 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1063 EXPECT_FALSE(views[0]->frame_provider_); 1064 1065 // Make [0] visible, and swap a frame on it. Nothing should be evicted 1066 // although we're above the limit. 1067 views[0]->WasShown(); 1068 views[0]->OnSwapCompositorFrame( 1069 1, MakeDelegatedFrame(1.f, frame_size, view_rect)); 1070 for (size_t i = 0; i < renderer_count; ++i) 1071 EXPECT_TRUE(views[i]->frame_provider_); 1072 1073 // Make [0] hidden, it should evict its frame. 1074 views[0]->WasHidden(); 1075 EXPECT_FALSE(views[0]->frame_provider_); 1076 1077 for (size_t i = 0; i < renderer_count; ++i) { 1078 views[i]->Destroy(); 1079 delete hosts[i]; 1080 } 1081 } 1082 1083 TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) { 1084 gfx::Rect view_rect(100, 100); 1085 gfx::Size frame_size(100, 100); 1086 1087 view_->InitAsChild(NULL); 1088 aura::client::ParentWindowWithContext( 1089 view_->GetNativeView(), 1090 parent_view_->GetNativeView()->GetRootWindow(), 1091 gfx::Rect()); 1092 view_->SetSize(view_rect.size()); 1093 view_->WasShown(); 1094 1095 // With a 1x DPI UI and 1x DPI Renderer. 1096 view_->OnSwapCompositorFrame( 1097 1, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size))); 1098 1099 // Save the frame provider. 1100 scoped_refptr<cc::DelegatedFrameProvider> frame_provider = 1101 view_->frame_provider_; 1102 1103 // This frame will have the same number of physical pixels, but has a new 1104 // scale on it. 1105 view_->OnSwapCompositorFrame( 1106 1, MakeDelegatedFrame(2.f, frame_size, gfx::Rect(frame_size))); 1107 1108 // When we get a new frame with the same frame size in physical pixels, but a 1109 // different scale, we should generate a new frame provider, as the final 1110 // result will need to be scaled differently to the screen. 1111 EXPECT_NE(frame_provider.get(), view_->frame_provider_.get()); 1112 } 1113 1114 } // namespace content 1115