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/auto_reset.h" 8 #include "base/basictypes.h" 9 #include "base/bind.h" 10 #include "base/callback_helpers.h" 11 #include "base/command_line.h" 12 #include "base/debug/trace_event.h" 13 #include "base/logging.h" 14 #include "base/message_loop/message_loop.h" 15 #include "base/strings/string_number_conversions.h" 16 #include "cc/layers/delegated_frame_provider.h" 17 #include "cc/output/compositor_frame.h" 18 #include "cc/output/compositor_frame_ack.h" 19 #include "cc/output/copy_output_request.h" 20 #include "cc/output/copy_output_result.h" 21 #include "cc/resources/texture_mailbox.h" 22 #include "cc/trees/layer_tree_settings.h" 23 #include "content/browser/accessibility/browser_accessibility_manager.h" 24 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 25 #include "content/browser/aura/compositor_resize_lock.h" 26 #include "content/browser/gpu/compositor_util.h" 27 #include "content/browser/renderer_host/backing_store_aura.h" 28 #include "content/browser/renderer_host/dip_util.h" 29 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h" 30 #include "content/browser/renderer_host/overscroll_controller.h" 31 #include "content/browser/renderer_host/render_view_host_delegate.h" 32 #include "content/browser/renderer_host/render_widget_host_impl.h" 33 #include "content/browser/renderer_host/ui_events_helper.h" 34 #include "content/browser/renderer_host/web_input_event_aura.h" 35 #include "content/common/gpu/client/gl_helper.h" 36 #include "content/common/gpu/gpu_messages.h" 37 #include "content/common/view_messages.h" 38 #include "content/port/browser/render_widget_host_view_frame_subscriber.h" 39 #include "content/port/browser/render_widget_host_view_port.h" 40 #include "content/public/browser/browser_thread.h" 41 #include "content/public/browser/content_browser_client.h" 42 #include "content/public/browser/render_process_host.h" 43 #include "content/public/browser/render_view_host.h" 44 #include "content/public/browser/user_metrics.h" 45 #include "content/public/common/content_switches.h" 46 #include "media/base/video_util.h" 47 #include "skia/ext/image_operations.h" 48 #include "third_party/WebKit/public/platform/WebScreenInfo.h" 49 #include "third_party/WebKit/public/web/WebCompositionUnderline.h" 50 #include "third_party/WebKit/public/web/WebInputEvent.h" 51 #include "ui/aura/client/activation_client.h" 52 #include "ui/aura/client/aura_constants.h" 53 #include "ui/aura/client/cursor_client.h" 54 #include "ui/aura/client/cursor_client_observer.h" 55 #include "ui/aura/client/focus_client.h" 56 #include "ui/aura/client/screen_position_client.h" 57 #include "ui/aura/client/tooltip_client.h" 58 #include "ui/aura/client/window_tree_client.h" 59 #include "ui/aura/client/window_types.h" 60 #include "ui/aura/env.h" 61 #include "ui/aura/root_window.h" 62 #include "ui/aura/window.h" 63 #include "ui/aura/window_observer.h" 64 #include "ui/aura/window_tracker.h" 65 #include "ui/base/clipboard/scoped_clipboard_writer.h" 66 #include "ui/base/hit_test.h" 67 #include "ui/base/ime/input_method.h" 68 #include "ui/base/ui_base_types.h" 69 #include "ui/compositor/layer.h" 70 #include "ui/events/event.h" 71 #include "ui/events/event_utils.h" 72 #include "ui/events/gestures/gesture_recognizer.h" 73 #include "ui/gfx/canvas.h" 74 #include "ui/gfx/display.h" 75 #include "ui/gfx/rect_conversions.h" 76 #include "ui/gfx/screen.h" 77 #include "ui/gfx/size_conversions.h" 78 #include "ui/gfx/skia_util.h" 79 80 #if defined(OS_WIN) 81 #include "base/win/windows_version.h" 82 #include "content/browser/accessibility/browser_accessibility_manager_win.h" 83 #include "content/browser/accessibility/browser_accessibility_win.h" 84 #include "content/common/plugin_constants_win.h" 85 #include "ui/base/win/hidden_window.h" 86 #include "ui/gfx/gdi_util.h" 87 #include "ui/gfx/win/dpi.h" 88 #endif 89 90 using gfx::RectToSkIRect; 91 using gfx::SkIRectToRect; 92 93 using blink::WebScreenInfo; 94 using blink::WebTouchEvent; 95 96 namespace content { 97 98 namespace { 99 100 void MailboxReleaseCallback(scoped_ptr<base::SharedMemory> shared_memory, 101 unsigned sync_point, bool lost_resource) { 102 // NOTE: shared_memory will get released when we go out of scope. 103 } 104 105 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting 106 // the border of the view, in order to get valid movement information. However, 107 // forcing the cursor back to the center of the view after each mouse move 108 // doesn't work well. It reduces the frequency of useful mouse move messages 109 // significantly. Therefore, we move the cursor to the center of the view only 110 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width 111 // of the border area, in percentage of the corresponding dimension. 112 const int kMouseLockBorderPercentage = 15; 113 114 // When accelerated compositing is enabled and a widget resize is pending, 115 // we delay further resizes of the UI. The following constant is the maximum 116 // length of time that we should delay further UI resizes while waiting for a 117 // resized frame from a renderer. 118 const int kResizeLockTimeoutMs = 67; 119 120 #if defined(OS_WIN) 121 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance. 122 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner"; 123 124 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) { 125 RenderWidgetHostViewAura* widget = 126 reinterpret_cast<RenderWidgetHostViewAura*>(param); 127 if (GetProp(window, kWidgetOwnerProperty) == widget) { 128 // Properties set on HWNDs must be removed to avoid leaks. 129 RemoveProp(window, kWidgetOwnerProperty); 130 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window); 131 } 132 return TRUE; 133 } 134 135 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) { 136 RenderWidgetHostViewAura* widget = 137 reinterpret_cast<RenderWidgetHostViewAura*>(param); 138 if (GetProp(window, kWidgetOwnerProperty) == widget) 139 SetParent(window, ui::GetHiddenWindow()); 140 return TRUE; 141 } 142 143 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) { 144 RenderWidgetHostViewAura* widget = 145 reinterpret_cast<RenderWidgetHostViewAura*>(param); 146 147 if (GetProp(window, kWidgetOwnerProperty) == widget && 148 widget->GetNativeView()->GetDispatcher()) { 149 HWND parent = widget->GetNativeView()->GetDispatcher()->host()-> 150 GetAcceleratedWidget(); 151 SetParent(window, parent); 152 } 153 return TRUE; 154 } 155 156 struct CutoutRectsParams { 157 RenderWidgetHostViewAura* widget; 158 std::vector<gfx::Rect> cutout_rects; 159 std::map<HWND, WebPluginGeometry>* geometry; 160 }; 161 162 // Used to update the region for the windowed plugin to draw in. We start with 163 // the clip rect from the renderer, then remove the cutout rects from the 164 // renderer, and then remove the transient windows from the root window and the 165 // constrained windows from the parent window. 166 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) { 167 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param); 168 169 if (GetProp(window, kWidgetOwnerProperty) == params->widget) { 170 // First calculate the offset of this plugin from the root window, since 171 // the cutouts are relative to the root window. 172 HWND parent = params->widget->GetNativeView()->GetDispatcher()-> 173 host()->GetAcceleratedWidget(); 174 POINT offset; 175 offset.x = offset.y = 0; 176 MapWindowPoints(window, parent, &offset, 1); 177 178 // Now get the cached clip rect and cutouts for this plugin window that came 179 // from the renderer. 180 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin(); 181 while (i != params->geometry->end() && 182 i->second.window != window && 183 GetParent(i->second.window) != window) { 184 ++i; 185 } 186 187 if (i == params->geometry->end()) { 188 NOTREACHED(); 189 return TRUE; 190 } 191 192 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(), 193 i->second.clip_rect.y(), 194 i->second.clip_rect.right(), 195 i->second.clip_rect.bottom()); 196 // We start with the cutout rects that came from the renderer, then add the 197 // ones that came from transient and constrained windows. 198 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects; 199 for (size_t i = 0; i < params->cutout_rects.size(); ++i) { 200 gfx::Rect offset_cutout = params->cutout_rects[i]; 201 offset_cutout.Offset(-offset.x, -offset.y); 202 cutout_rects.push_back(offset_cutout); 203 } 204 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects); 205 // If we don't have any cutout rects then no point in messing with the 206 // window region. 207 if (cutout_rects.size()) 208 SetWindowRgn(window, hrgn, TRUE); 209 } 210 return TRUE; 211 } 212 213 // A callback function for EnumThreadWindows to enumerate and dismiss 214 // any owned popup windows. 215 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { 216 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg); 217 218 if (::IsWindowVisible(window)) { 219 const HWND owner = ::GetWindow(window, GW_OWNER); 220 if (toplevel_hwnd == owner) { 221 ::PostMessage(window, WM_CANCELMODE, 0, 0); 222 } 223 } 224 225 return TRUE; 226 } 227 #endif 228 229 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event, 230 blink::WebTouchPoint* point) { 231 if (point->state != blink::WebTouchPoint::StateReleased && 232 point->state != blink::WebTouchPoint::StateCancelled) 233 return; 234 --event->touchesLength; 235 for (unsigned i = point - event->touches; 236 i < event->touchesLength; 237 ++i) { 238 event->touches[i] = event->touches[i + 1]; 239 } 240 } 241 242 bool CanRendererHandleEvent(const ui::MouseEvent* event) { 243 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) 244 return false; 245 246 #if defined(OS_WIN) 247 // Renderer cannot handle WM_XBUTTON or NC events. 248 switch (event->native_event().message) { 249 case WM_XBUTTONDOWN: 250 case WM_XBUTTONUP: 251 case WM_XBUTTONDBLCLK: 252 case WM_NCMOUSELEAVE: 253 case WM_NCMOUSEMOVE: 254 case WM_NCLBUTTONDOWN: 255 case WM_NCLBUTTONUP: 256 case WM_NCLBUTTONDBLCLK: 257 case WM_NCRBUTTONDOWN: 258 case WM_NCRBUTTONUP: 259 case WM_NCRBUTTONDBLCLK: 260 case WM_NCMBUTTONDOWN: 261 case WM_NCMBUTTONUP: 262 case WM_NCMBUTTONDBLCLK: 263 case WM_NCXBUTTONDOWN: 264 case WM_NCXBUTTONUP: 265 case WM_NCXBUTTONDBLCLK: 266 return false; 267 default: 268 break; 269 } 270 #endif 271 return true; 272 } 273 274 // We don't mark these as handled so that they're sent back to the 275 // DefWindowProc so it can generate WM_APPCOMMAND as necessary. 276 bool IsXButtonUpEvent(const ui::MouseEvent* event) { 277 #if defined(OS_WIN) 278 switch (event->native_event().message) { 279 case WM_XBUTTONUP: 280 case WM_NCXBUTTONUP: 281 return true; 282 } 283 #endif 284 return false; 285 } 286 287 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) { 288 const gfx::Display display = window ? 289 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) : 290 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay(); 291 results->rect = display.bounds(); 292 results->availableRect = display.work_area(); 293 // TODO(derat|oshima): Don't hardcode this. Get this from display object. 294 results->depth = 24; 295 results->depthPerComponent = 8; 296 results->deviceScaleFactor = display.device_scale_factor(); 297 } 298 299 bool ShouldSendPinchGesture() { 300 #if defined(OS_WIN) 301 if (base::win::GetVersion() >= base::win::VERSION_WIN8) 302 return true; 303 #endif 304 static bool pinch_allowed = 305 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableViewport) || 306 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnablePinch); 307 return pinch_allowed; 308 } 309 310 bool PointerEventActivates(const ui::Event& event) { 311 if (event.type() == ui::ET_MOUSE_PRESSED) 312 return true; 313 314 if (event.type() == ui::ET_GESTURE_BEGIN) { 315 const ui::GestureEvent& gesture = 316 static_cast<const ui::GestureEvent&>(event); 317 return gesture.details().touch_points() == 1; 318 } 319 320 return false; 321 } 322 323 // Swap ack for the renderer when kCompositeToMailbox is enabled. 324 void SendCompositorFrameAck( 325 int32 route_id, 326 uint32 output_surface_id, 327 int renderer_host_id, 328 const gpu::Mailbox& received_mailbox, 329 const gfx::Size& received_size, 330 bool skip_frame, 331 const scoped_refptr<ui::Texture>& texture_to_produce) { 332 cc::CompositorFrameAck ack; 333 ack.gl_frame_data.reset(new cc::GLFrameData()); 334 DCHECK(!texture_to_produce.get() || !skip_frame); 335 if (texture_to_produce.get()) { 336 std::string mailbox_name = texture_to_produce->Produce(); 337 std::copy(mailbox_name.data(), 338 mailbox_name.data() + mailbox_name.length(), 339 reinterpret_cast<char*>(ack.gl_frame_data->mailbox.name)); 340 ack.gl_frame_data->size = texture_to_produce->size(); 341 ack.gl_frame_data->sync_point = 342 content::ImageTransportFactory::GetInstance()->InsertSyncPoint(); 343 } else if (skip_frame) { 344 // Skip the frame, i.e. tell the producer to reuse the same buffer that 345 // we just received. 346 ack.gl_frame_data->size = received_size; 347 ack.gl_frame_data->mailbox = received_mailbox; 348 } 349 350 RenderWidgetHostImpl::SendSwapCompositorFrameAck( 351 route_id, output_surface_id, renderer_host_id, ack); 352 } 353 354 void AcknowledgeBufferForGpu( 355 int32 route_id, 356 int gpu_host_id, 357 const std::string& received_mailbox, 358 bool skip_frame, 359 const scoped_refptr<ui::Texture>& texture_to_produce) { 360 AcceleratedSurfaceMsg_BufferPresented_Params ack; 361 uint32 sync_point = 0; 362 DCHECK(!texture_to_produce.get() || !skip_frame); 363 if (texture_to_produce.get()) { 364 ack.mailbox_name = texture_to_produce->Produce(); 365 sync_point = 366 content::ImageTransportFactory::GetInstance()->InsertSyncPoint(); 367 } else if (skip_frame) { 368 ack.mailbox_name = received_mailbox; 369 ack.sync_point = 0; 370 } 371 372 ack.sync_point = sync_point; 373 RenderWidgetHostImpl::AcknowledgeBufferPresent( 374 route_id, gpu_host_id, ack); 375 } 376 377 } // namespace 378 379 // We need to watch for mouse events outside a Web Popup or its parent 380 // and dismiss the popup for certain events. 381 class RenderWidgetHostViewAura::EventFilterForPopupExit : 382 public ui::EventHandler { 383 public: 384 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva) 385 : rwhva_(rwhva) { 386 DCHECK(rwhva_); 387 aura::Window* root_window = rwhva_->window_->GetRootWindow(); 388 DCHECK(root_window); 389 root_window->AddPreTargetHandler(this); 390 } 391 392 virtual ~EventFilterForPopupExit() { 393 aura::Window* root_window = rwhva_->window_->GetRootWindow(); 394 DCHECK(root_window); 395 root_window->RemovePreTargetHandler(this); 396 } 397 398 // Overridden from ui::EventHandler 399 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { 400 rwhva_->ApplyEventFilterForPopupExit(event); 401 } 402 403 private: 404 RenderWidgetHostViewAura* rwhva_; 405 406 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit); 407 }; 408 409 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit( 410 ui::MouseEvent* event) { 411 if (in_shutdown_ || is_fullscreen_) 412 return; 413 414 if (event->type() != ui::ET_MOUSE_PRESSED || !event->target()) 415 return; 416 417 aura::Window* target = static_cast<aura::Window*>(event->target()); 418 if (target != window_ && 419 (!popup_parent_host_view_ || 420 target != popup_parent_host_view_->window_)) { 421 // Note: popup_parent_host_view_ may be NULL when there are multiple 422 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup(). 423 in_shutdown_ = true; 424 host_->Shutdown(); 425 } 426 } 427 428 // We have to implement the WindowObserver interface on a separate object 429 // because clang doesn't like implementing multiple interfaces that have 430 // methods with the same name. This object is owned by the 431 // RenderWidgetHostViewAura. 432 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver { 433 public: 434 explicit WindowObserver(RenderWidgetHostViewAura* view) 435 : view_(view) { 436 view_->window_->AddObserver(this); 437 } 438 439 virtual ~WindowObserver() { 440 view_->window_->RemoveObserver(this); 441 } 442 443 // Overridden from aura::WindowObserver: 444 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE { 445 if (window == view_->window_) 446 view_->AddedToRootWindow(); 447 } 448 449 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE { 450 if (window == view_->window_) 451 view_->RemovingFromRootWindow(); 452 } 453 454 private: 455 RenderWidgetHostViewAura* view_; 456 457 DISALLOW_COPY_AND_ASSIGN(WindowObserver); 458 }; 459 460 //////////////////////////////////////////////////////////////////////////////// 461 // RenderWidgetHostViewAura, public: 462 463 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) 464 : host_(RenderWidgetHostImpl::From(host)), 465 window_(new aura::Window(this)), 466 in_shutdown_(false), 467 in_bounds_changed_(false), 468 is_fullscreen_(false), 469 popup_parent_host_view_(NULL), 470 popup_child_host_view_(NULL), 471 is_loading_(false), 472 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), 473 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), 474 can_compose_inline_(true), 475 has_composition_text_(false), 476 accept_return_character_(false), 477 last_output_surface_id_(0), 478 pending_delegated_ack_count_(0), 479 skipped_frames_(false), 480 last_swapped_surface_scale_factor_(1.f), 481 paint_canvas_(NULL), 482 synthetic_move_sent_(false), 483 accelerated_compositing_state_changed_(false), 484 can_lock_compositor_(YES), 485 cursor_visibility_state_in_renderer_(UNKNOWN), 486 paint_observer_(NULL), 487 touch_editing_client_(NULL), 488 delegated_frame_evictor_(new DelegatedFrameEvictor(this)), 489 weak_ptr_factory_(this) { 490 host_->SetView(this); 491 window_observer_.reset(new WindowObserver(this)); 492 aura::client::SetTooltipText(window_, &tooltip_); 493 aura::client::SetActivationDelegate(window_, this); 494 aura::client::SetActivationChangeObserver(window_, this); 495 aura::client::SetFocusChangeObserver(window_, this); 496 gfx::Screen::GetScreenFor(window_)->AddObserver(this); 497 software_frame_manager_.reset(new SoftwareFrameManager( 498 weak_ptr_factory_.GetWeakPtr())); 499 #if defined(OS_WIN) 500 plugin_parent_window_ = NULL; 501 #endif 502 } 503 504 //////////////////////////////////////////////////////////////////////////////// 505 // RenderWidgetHostViewAura, RenderWidgetHostView implementation: 506 507 void RenderWidgetHostViewAura::InitAsChild( 508 gfx::NativeView parent_view) { 509 window_->Init(ui::LAYER_TEXTURED); 510 window_->SetName("RenderWidgetHostViewAura"); 511 } 512 513 void RenderWidgetHostViewAura::InitAsPopup( 514 RenderWidgetHostView* parent_host_view, 515 const gfx::Rect& bounds_in_screen) { 516 popup_parent_host_view_ = 517 static_cast<RenderWidgetHostViewAura*>(parent_host_view); 518 519 RenderWidgetHostViewAura* old_child = 520 popup_parent_host_view_->popup_child_host_view_; 521 if (old_child) { 522 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or 523 // similar mechanism to ensure a second popup doesn't cause the first one 524 // to never get a chance to filter events. See crbug.com/160589. 525 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_); 526 popup_parent_host_view_->window_->RemoveTransientChild(old_child->window_); 527 old_child->popup_parent_host_view_ = NULL; 528 } 529 popup_parent_host_view_->popup_child_host_view_ = this; 530 window_->SetType(aura::client::WINDOW_TYPE_MENU); 531 window_->Init(ui::LAYER_TEXTURED); 532 window_->SetName("RenderWidgetHostViewAura"); 533 534 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow(); 535 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen); 536 // Setting the transient child allows for the popup to get mouse events when 537 // in a system modal dialog. 538 // This fixes crbug.com/328593. 539 popup_parent_host_view_->window_->AddTransientChild(window_); 540 541 SetBounds(bounds_in_screen); 542 Show(); 543 } 544 545 void RenderWidgetHostViewAura::InitAsFullscreen( 546 RenderWidgetHostView* reference_host_view) { 547 is_fullscreen_ = true; 548 window_->SetType(aura::client::WINDOW_TYPE_NORMAL); 549 window_->Init(ui::LAYER_TEXTURED); 550 window_->SetName("RenderWidgetHostViewAura"); 551 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 552 553 aura::Window* parent = NULL; 554 gfx::Rect bounds; 555 if (reference_host_view) { 556 aura::Window* reference_window = 557 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_; 558 if (reference_window) { 559 host_tracker_.reset(new aura::WindowTracker); 560 host_tracker_->Add(reference_window); 561 } 562 gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 563 GetDisplayNearestWindow(reference_window); 564 parent = reference_window->GetRootWindow(); 565 bounds = display.bounds(); 566 } 567 aura::client::ParentWindowWithContext(window_, parent, bounds); 568 Show(); 569 Focus(); 570 } 571 572 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const { 573 return host_; 574 } 575 576 void RenderWidgetHostViewAura::WasShown() { 577 DCHECK(host_); 578 if (!host_->is_hidden()) 579 return; 580 host_->WasShown(); 581 software_frame_manager_->SetVisibility(true); 582 delegated_frame_evictor_->SetVisible(true); 583 584 aura::Window* root = window_->GetRootWindow(); 585 if (root) { 586 aura::client::CursorClient* cursor_client = 587 aura::client::GetCursorClient(root); 588 if (cursor_client) 589 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible()); 590 } 591 592 if (!current_surface_.get() && host_->is_accelerated_compositing_active() && 593 !released_front_lock_.get()) { 594 ui::Compositor* compositor = GetCompositor(); 595 if (compositor) 596 released_front_lock_ = compositor->GetCompositorLock(); 597 } 598 599 #if defined(OS_WIN) 600 LPARAM lparam = reinterpret_cast<LPARAM>(this); 601 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam); 602 603 if (::IsWindow(plugin_parent_window_)) { 604 gfx::Rect window_bounds = window_->GetBoundsInRootWindow(); 605 ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(), 606 window_bounds.y(), window_bounds.width(), 607 window_bounds.height(), 0); 608 } 609 #endif 610 } 611 612 void RenderWidgetHostViewAura::WasHidden() { 613 if (!host_ || host_->is_hidden()) 614 return; 615 host_->WasHidden(); 616 software_frame_manager_->SetVisibility(false); 617 delegated_frame_evictor_->SetVisible(false); 618 released_front_lock_ = NULL; 619 620 #if defined(OS_WIN) 621 constrained_rects_.clear(); 622 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 623 if (dispatcher) { 624 HWND parent = dispatcher->host()->GetAcceleratedWidget(); 625 LPARAM lparam = reinterpret_cast<LPARAM>(this); 626 627 EnumChildWindows(parent, HideWindowsCallback, lparam); 628 } 629 if (::IsWindow(plugin_parent_window_)) 630 ::SetWindowPos(plugin_parent_window_, NULL, 0, 0, 0, 0, 0); 631 #endif 632 } 633 634 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) { 635 // For a SetSize operation, we don't care what coordinate system the origin 636 // of the window is in, it's only important to make sure that the origin 637 // remains constant after the operation. 638 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size)); 639 } 640 641 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) { 642 gfx::Point relative_origin(rect.origin()); 643 644 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but 645 // Window::SetBounds() takes parent coordinates, so do the conversion here. 646 aura::Window* root = window_->GetRootWindow(); 647 if (root) { 648 aura::client::ScreenPositionClient* screen_position_client = 649 aura::client::GetScreenPositionClient(root); 650 if (screen_position_client) { 651 screen_position_client->ConvertPointFromScreen( 652 window_->parent(), &relative_origin); 653 } 654 } 655 656 InternalSetBounds(gfx::Rect(relative_origin, rect.size())); 657 } 658 659 void RenderWidgetHostViewAura::MaybeCreateResizeLock() { 660 if (!ShouldCreateResizeLock()) 661 return; 662 DCHECK(window_->GetDispatcher()); 663 DCHECK(window_->GetDispatcher()->compositor()); 664 665 // Listen to changes in the compositor lock state. 666 ui::Compositor* compositor = window_->GetDispatcher()->compositor(); 667 if (!compositor->HasObserver(this)) 668 compositor->AddObserver(this); 669 670 bool defer_compositor_lock = 671 can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || 672 can_lock_compositor_ == NO_PENDING_COMMIT; 673 674 if (can_lock_compositor_ == YES) 675 can_lock_compositor_ = YES_DID_LOCK; 676 677 resize_lock_ = CreateResizeLock(defer_compositor_lock); 678 } 679 680 bool RenderWidgetHostViewAura::ShouldCreateResizeLock() { 681 // On Windows while resizing, the the resize locks makes us mis-paint a white 682 // vertical strip (including the non-client area) if the content composition 683 // is lagging the UI composition. So here we disable the throttling so that 684 // the UI bits can draw ahead of the content thereby reducing the amount of 685 // whiteout. Because this causes the content to be drawn at wrong sizes while 686 // resizing we compensate by blocking the UI thread in Compositor::Draw() by 687 // issuing a FinishAllRendering() if we are resizing. 688 #if defined (OS_WIN) 689 return false; 690 #endif 691 692 if (resize_lock_) 693 return false; 694 695 if (host_->should_auto_resize()) 696 return false; 697 if (!host_->is_accelerated_compositing_active()) 698 return false; 699 700 gfx::Size desired_size = window_->bounds().size(); 701 if (desired_size == current_frame_size_) 702 return false; 703 704 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 705 if (!dispatcher) 706 return false; 707 708 ui::Compositor* compositor = dispatcher->compositor(); 709 if (!compositor) 710 return false; 711 712 return true; 713 } 714 715 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock( 716 bool defer_compositor_lock) { 717 gfx::Size desired_size = window_->bounds().size(); 718 return scoped_ptr<ResizeLock>(new CompositorResizeLock( 719 window_->GetDispatcher(), 720 desired_size, 721 defer_compositor_lock, 722 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs))); 723 } 724 725 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const { 726 return window_; 727 } 728 729 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const { 730 #if defined(OS_WIN) 731 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 732 if (dispatcher) 733 return reinterpret_cast<gfx::NativeViewId>( 734 dispatcher->host()->GetAcceleratedWidget()); 735 #endif 736 return static_cast<gfx::NativeViewId>(NULL); 737 } 738 739 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() { 740 #if defined(OS_WIN) 741 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 742 if (!dispatcher) 743 return static_cast<gfx::NativeViewAccessible>(NULL); 744 HWND hwnd = dispatcher->host()->GetAcceleratedWidget(); 745 746 BrowserAccessibilityManager* manager = 747 GetOrCreateBrowserAccessibilityManager(); 748 if (manager) 749 return manager->GetRoot()->ToBrowserAccessibilityWin(); 750 #endif 751 752 NOTIMPLEMENTED(); 753 return static_cast<gfx::NativeViewAccessible>(NULL); 754 } 755 756 BrowserAccessibilityManager* 757 RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() { 758 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager(); 759 if (manager) 760 return manager; 761 762 #if defined(OS_WIN) 763 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 764 if (!dispatcher) 765 return NULL; 766 HWND hwnd = dispatcher->host()->GetAcceleratedWidget(); 767 768 // The accessible_parent may be NULL at this point. The WebContents will pass 769 // it down to this instance (by way of the RenderViewHost and 770 // RenderWidgetHost) when it is known. This instance will then set it on its 771 // BrowserAccessibilityManager. 772 gfx::NativeViewAccessible accessible_parent = 773 host_->GetParentNativeViewAccessible(); 774 775 manager = new BrowserAccessibilityManagerWin( 776 hwnd, accessible_parent, 777 BrowserAccessibilityManagerWin::GetEmptyDocument(), this); 778 #else 779 manager = BrowserAccessibilityManager::Create( 780 BrowserAccessibilityManager::GetEmptyDocument(), this); 781 #endif 782 783 SetBrowserAccessibilityManager(manager); 784 return manager; 785 } 786 787 void RenderWidgetHostViewAura::SetKeyboardFocus() { 788 #if defined(OS_WIN) 789 if (CanFocus()) { 790 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 791 if (dispatcher) 792 ::SetFocus(dispatcher->host()->GetAcceleratedWidget()); 793 } 794 #endif 795 } 796 797 void RenderWidgetHostViewAura::MovePluginWindows( 798 const gfx::Vector2d& scroll_offset, 799 const std::vector<WebPluginGeometry>& plugin_window_moves) { 800 #if defined(OS_WIN) 801 // We need to clip the rectangle to the tab's viewport, otherwise we will draw 802 // over the browser UI. 803 if (!window_->GetRootWindow()) { 804 DCHECK(plugin_window_moves.empty()); 805 return; 806 } 807 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget(); 808 gfx::Rect view_bounds = window_->GetBoundsInRootWindow(); 809 std::vector<WebPluginGeometry> moves = plugin_window_moves; 810 811 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(), 812 view_bounds.height()); 813 814 for (size_t i = 0; i < moves.size(); ++i) { 815 gfx::Rect clip(moves[i].clip_rect); 816 gfx::Vector2d view_port_offset( 817 moves[i].window_rect.OffsetFromOrigin() + scroll_offset); 818 clip.Offset(view_port_offset); 819 clip.Intersect(view_port); 820 clip.Offset(-view_port_offset); 821 moves[i].clip_rect = clip; 822 823 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin()); 824 825 plugin_window_moves_[moves[i].window] = moves[i]; 826 827 // constrained_rects_ are relative to the root window. We want to convert 828 // them to be relative to the plugin window. 829 for (size_t j = 0; j < constrained_rects_.size(); ++j) { 830 gfx::Rect offset_cutout = constrained_rects_[j]; 831 offset_cutout -= moves[i].window_rect.OffsetFromOrigin(); 832 moves[i].cutout_rects.push_back(offset_cutout); 833 } 834 } 835 836 MovePluginWindowsHelper(parent, moves); 837 838 // Make sure each plugin window (or its wrapper if it exists) has a pointer to 839 // |this|. 840 for (size_t i = 0; i < moves.size(); ++i) { 841 HWND window = moves[i].window; 842 if (GetParent(window) != parent) { 843 window = GetParent(window); 844 } 845 if (!GetProp(window, kWidgetOwnerProperty)) 846 SetProp(window, kWidgetOwnerProperty, this); 847 } 848 #endif // defined(OS_WIN) 849 } 850 851 void RenderWidgetHostViewAura::Focus() { 852 // Make sure we have a FocusClient before attempting to Focus(). In some 853 // situations we may not yet be in a valid Window hierarchy (such as reloading 854 // after out of memory discarded the tab). 855 aura::client::FocusClient* client = aura::client::GetFocusClient(window_); 856 if (client) 857 window_->Focus(); 858 } 859 860 void RenderWidgetHostViewAura::Blur() { 861 window_->Blur(); 862 } 863 864 bool RenderWidgetHostViewAura::HasFocus() const { 865 return window_->HasFocus(); 866 } 867 868 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const { 869 return CanCopyToBitmap() || !!host_->GetBackingStore(false); 870 } 871 872 void RenderWidgetHostViewAura::Show() { 873 window_->Show(); 874 WasShown(); 875 } 876 877 void RenderWidgetHostViewAura::Hide() { 878 window_->Hide(); 879 WasHidden(); 880 } 881 882 bool RenderWidgetHostViewAura::IsShowing() { 883 return window_->IsVisible(); 884 } 885 886 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const { 887 // This is the size that we want the renderer to produce. While we're waiting 888 // for the correct frame (i.e. during a resize), don't change the size so that 889 // we don't pipeline more resizes than we can handle. 890 gfx::Rect bounds(window_->GetBoundsInScreen()); 891 if (resize_lock_.get()) 892 return gfx::Rect(bounds.origin(), resize_lock_->expected_size()); 893 else 894 return bounds; 895 } 896 897 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) { 898 RenderWidgetHostViewBase::SetBackground(background); 899 host_->SetBackground(background); 900 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque()); 901 } 902 903 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) { 904 current_cursor_ = cursor; 905 const gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 906 GetDisplayNearestWindow(window_); 907 current_cursor_.SetDisplayInfo(display); 908 UpdateCursorIfOverSelf(); 909 } 910 911 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) { 912 if (is_loading_ && !is_loading && paint_observer_) 913 paint_observer_->OnPageLoadComplete(); 914 is_loading_ = is_loading; 915 UpdateCursorIfOverSelf(); 916 } 917 918 void RenderWidgetHostViewAura::TextInputTypeChanged( 919 ui::TextInputType type, 920 ui::TextInputMode input_mode, 921 bool can_compose_inline) { 922 if (text_input_type_ != type || 923 text_input_mode_ != input_mode || 924 can_compose_inline_ != can_compose_inline) { 925 text_input_type_ = type; 926 text_input_mode_ = input_mode; 927 can_compose_inline_ = can_compose_inline; 928 if (GetInputMethod()) 929 GetInputMethod()->OnTextInputTypeChanged(this); 930 if (touch_editing_client_) 931 touch_editing_client_->OnTextInputTypeChanged(text_input_type_); 932 } 933 } 934 935 void RenderWidgetHostViewAura::ImeCancelComposition() { 936 if (GetInputMethod()) 937 GetInputMethod()->CancelComposition(this); 938 has_composition_text_ = false; 939 } 940 941 void RenderWidgetHostViewAura::ImeCompositionRangeChanged( 942 const gfx::Range& range, 943 const std::vector<gfx::Rect>& character_bounds) { 944 composition_character_bounds_ = character_bounds; 945 } 946 947 void RenderWidgetHostViewAura::DidUpdateBackingStore( 948 const gfx::Rect& scroll_rect, 949 const gfx::Vector2d& scroll_delta, 950 const std::vector<gfx::Rect>& copy_rects, 951 const ui::LatencyInfo& latency_info) { 952 if (accelerated_compositing_state_changed_) 953 UpdateExternalTexture(); 954 955 software_latency_info_.MergeWith(latency_info); 956 957 // Use the state of the RenderWidgetHost and not the window as the two may 958 // differ. In particular if the window is hidden but the renderer isn't and we 959 // ignore the update and the window is made visible again the layer isn't 960 // marked as dirty and we show the wrong thing. 961 // We do this after UpdateExternalTexture() so that when we become visible 962 // we're not drawing a stale texture. 963 if (host_->is_hidden()) 964 return; 965 966 gfx::Rect clip_rect; 967 if (paint_canvas_) { 968 SkRect sk_clip_rect; 969 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect)) 970 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect)); 971 } 972 973 if (!scroll_rect.IsEmpty()) 974 SchedulePaintIfNotInClip(scroll_rect, clip_rect); 975 976 #if defined(OS_WIN) 977 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 978 #endif 979 for (size_t i = 0; i < copy_rects.size(); ++i) { 980 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect); 981 if (rect.IsEmpty()) 982 continue; 983 984 SchedulePaintIfNotInClip(rect, clip_rect); 985 986 #if defined(OS_WIN) 987 if (dispatcher) { 988 // Send the invalid rect in screen coordinates. 989 gfx::Rect screen_rect = GetViewBounds(); 990 gfx::Rect invalid_screen_rect(rect); 991 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y()); 992 HWND hwnd = dispatcher->host()->GetAcceleratedWidget(); 993 PaintPluginWindowsHelper(hwnd, invalid_screen_rect); 994 } 995 #endif // defined(OS_WIN) 996 } 997 } 998 999 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status, 1000 int error_code) { 1001 UpdateCursorIfOverSelf(); 1002 Destroy(); 1003 } 1004 1005 void RenderWidgetHostViewAura::Destroy() { 1006 // Beware, this function is not called on all destruction paths. It will 1007 // implicitly end up calling ~RenderWidgetHostViewAura though, so all 1008 // destruction/cleanup code should happen there, not here. 1009 in_shutdown_ = true; 1010 delete window_; 1011 } 1012 1013 void RenderWidgetHostViewAura::SetTooltipText( 1014 const base::string16& tooltip_text) { 1015 tooltip_ = tooltip_text; 1016 aura::Window* root_window = window_->GetRootWindow(); 1017 aura::client::TooltipClient* tooltip_client = 1018 aura::client::GetTooltipClient(root_window); 1019 if (tooltip_client) { 1020 tooltip_client->UpdateTooltip(window_); 1021 // Content tooltips should be visible indefinitely. 1022 tooltip_client->SetTooltipShownTimeout(window_, 0); 1023 } 1024 } 1025 1026 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text, 1027 size_t offset, 1028 const gfx::Range& range) { 1029 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); 1030 1031 #if defined(USE_X11) && !defined(OS_CHROMEOS) 1032 if (text.empty() || range.is_empty()) 1033 return; 1034 1035 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. 1036 ui::ScopedClipboardWriter clipboard_writer( 1037 ui::Clipboard::GetForCurrentThread(), 1038 ui::CLIPBOARD_TYPE_SELECTION); 1039 clipboard_writer.WriteText(text); 1040 #endif // defined(USE_X11) && !defined(OS_CHROMEOS) 1041 } 1042 1043 void RenderWidgetHostViewAura::SelectionBoundsChanged( 1044 const ViewHostMsg_SelectionBounds_Params& params) { 1045 if (selection_anchor_rect_ == params.anchor_rect && 1046 selection_focus_rect_ == params.focus_rect) 1047 return; 1048 1049 selection_anchor_rect_ = params.anchor_rect; 1050 selection_focus_rect_ = params.focus_rect; 1051 1052 if (GetInputMethod()) 1053 GetInputMethod()->OnCaretBoundsChanged(this); 1054 1055 if (touch_editing_client_) { 1056 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_, 1057 selection_focus_rect_); 1058 } 1059 } 1060 1061 void RenderWidgetHostViewAura::ScrollOffsetChanged() { 1062 aura::Window* root = window_->GetRootWindow(); 1063 if (!root) 1064 return; 1065 aura::client::CursorClient* cursor_client = 1066 aura::client::GetCursorClient(root); 1067 if (cursor_client && !cursor_client->IsCursorVisible()) 1068 cursor_client->DisableMouseEvents(); 1069 } 1070 1071 BackingStore* RenderWidgetHostViewAura::AllocBackingStore( 1072 const gfx::Size& size) { 1073 return new BackingStoreAura(host_, size); 1074 } 1075 1076 void RenderWidgetHostViewAura::CopyFromCompositingSurface( 1077 const gfx::Rect& src_subrect, 1078 const gfx::Size& dst_size, 1079 const base::Callback<void(bool, const SkBitmap&)>& callback) { 1080 if (!CanCopyToBitmap()) { 1081 callback.Run(false, SkBitmap()); 1082 return; 1083 } 1084 1085 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size); 1086 scoped_ptr<cc::CopyOutputRequest> request = 1087 cc::CopyOutputRequest::CreateRequest(base::Bind( 1088 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult, 1089 dst_size_in_pixel, 1090 callback)); 1091 gfx::Rect src_subrect_in_pixel = 1092 ConvertRectToPixel(current_device_scale_factor_, src_subrect); 1093 request->set_area(src_subrect_in_pixel); 1094 window_->layer()->RequestCopyOfOutput(request.Pass()); 1095 } 1096 1097 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame( 1098 const gfx::Rect& src_subrect, 1099 const scoped_refptr<media::VideoFrame>& target, 1100 const base::Callback<void(bool)>& callback) { 1101 if (!CanCopyToVideoFrame()) { 1102 callback.Run(false); 1103 return; 1104 } 1105 1106 // Try get a texture to reuse. 1107 scoped_refptr<OwnedMailbox> subscriber_texture; 1108 if (frame_subscriber_) { 1109 if (!idle_frame_subscriber_textures_.empty()) { 1110 subscriber_texture = idle_frame_subscriber_textures_.back(); 1111 idle_frame_subscriber_textures_.pop_back(); 1112 } else if (GLHelper* helper = 1113 ImageTransportFactory::GetInstance()->GetGLHelper()) { 1114 subscriber_texture = new OwnedMailbox(helper); 1115 } 1116 } 1117 1118 scoped_ptr<cc::CopyOutputRequest> request = 1119 cc::CopyOutputRequest::CreateRequest(base::Bind( 1120 &RenderWidgetHostViewAura:: 1121 CopyFromCompositingSurfaceHasResultForVideo, 1122 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class. 1123 subscriber_texture, 1124 target, 1125 callback)); 1126 gfx::Rect src_subrect_in_pixel = 1127 ConvertRectToPixel(current_device_scale_factor_, src_subrect); 1128 request->set_area(src_subrect_in_pixel); 1129 if (subscriber_texture) { 1130 request->SetTextureMailbox(cc::TextureMailbox( 1131 subscriber_texture->mailbox(), subscriber_texture->sync_point())); 1132 } 1133 window_->layer()->RequestCopyOfOutput(request.Pass()); 1134 } 1135 1136 bool RenderWidgetHostViewAura::CanCopyToBitmap() const { 1137 return GetCompositor() && window_->layer()->has_external_content(); 1138 } 1139 1140 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const { 1141 return GetCompositor() && 1142 window_->layer()->has_external_content() && 1143 host_->is_accelerated_compositing_active(); 1144 } 1145 1146 bool RenderWidgetHostViewAura::CanSubscribeFrame() const { 1147 return true; 1148 } 1149 1150 void RenderWidgetHostViewAura::BeginFrameSubscription( 1151 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { 1152 frame_subscriber_ = subscriber.Pass(); 1153 } 1154 1155 void RenderWidgetHostViewAura::EndFrameSubscription() { 1156 idle_frame_subscriber_textures_.clear(); 1157 frame_subscriber_.reset(); 1158 } 1159 1160 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() { 1161 // Delay processing the state change until we either get a software frame if 1162 // switching to software mode or receive a buffers swapped notification 1163 // if switching to accelerated mode. 1164 // Sometimes (e.g. on a page load) the renderer will spuriously disable then 1165 // re-enable accelerated compositing, causing us to flash. 1166 // TODO(piman): factor the enable/disable accelerated compositing message into 1167 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have 1168 // fewer inconsistent temporary states. 1169 accelerated_compositing_state_changed_ = true; 1170 } 1171 1172 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id, 1173 int route_id) { 1174 } 1175 1176 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const { 1177 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME || 1178 can_lock_compositor_ == NO_PENDING_COMMIT || 1179 !resize_lock_.get()) 1180 return false; 1181 1182 return size_in_dip != resize_lock_->expected_size(); 1183 } 1184 1185 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) { 1186 if (HasDisplayPropertyChanged(window_)) 1187 host_->InvalidateScreenInfo(); 1188 1189 // Don't recursively call SetBounds if this bounds update is the result of 1190 // a Window::SetBoundsInternal call. 1191 if (!in_bounds_changed_) 1192 window_->SetBounds(rect); 1193 host_->WasResized(); 1194 MaybeCreateResizeLock(); 1195 if (touch_editing_client_) { 1196 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_, 1197 selection_focus_rect_); 1198 } 1199 #if defined(OS_WIN) 1200 // Create the dummy plugin parent window which will be passed as the 1201 // container window to windowless plugins. 1202 // Plugins like Flash assume the container window which is returned via the 1203 // NPNVnetscapeWindow property corresponds to the bounds of the webpage. 1204 // This is not true in Aura where we have only HWND which is the main Aura 1205 // window. If we return this window to plugins like Flash then it causes the 1206 // coordinate translations done by these plugins to break. 1207 if (!plugin_parent_window_ && GetNativeViewId()) { 1208 plugin_parent_window_ = ::CreateWindowEx( 1209 0, L"Static", NULL, WS_CHILDWINDOW, 0, 0, 0, 0, 1210 reinterpret_cast<HWND>(GetNativeViewId()), NULL, NULL, NULL); 1211 if (::IsWindow(plugin_parent_window_)) 1212 ::SetProp(plugin_parent_window_, content::kPluginDummyParentProperty, 1213 reinterpret_cast<HANDLE>(true)); 1214 } 1215 if (::IsWindow(plugin_parent_window_)) { 1216 gfx::Rect window_bounds = window_->GetBoundsInRootWindow(); 1217 ::SetWindowPos(plugin_parent_window_, NULL, window_bounds.x(), 1218 window_bounds.y(), window_bounds.width(), 1219 window_bounds.height(), 0); 1220 } 1221 #endif 1222 } 1223 1224 void RenderWidgetHostViewAura::CheckResizeLock() { 1225 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_) 1226 return; 1227 1228 // Since we got the size we were looking for, unlock the compositor. But delay 1229 // the release of the lock until we've kicked a frame with the new texture, to 1230 // avoid resizing the UI before we have a chance to draw a "good" frame. 1231 resize_lock_->UnlockCompositor(); 1232 ui::Compositor* compositor = GetCompositor(); 1233 if (compositor) { 1234 if (!compositor->HasObserver(this)) 1235 compositor->AddObserver(this); 1236 } 1237 } 1238 1239 void RenderWidgetHostViewAura::UpdateExternalTexture() { 1240 // Delay processing accelerated compositing state change till here where we 1241 // act upon the state change. (Clear the external texture if switching to 1242 // software mode or set the external texture if going to accelerated mode). 1243 if (accelerated_compositing_state_changed_) 1244 accelerated_compositing_state_changed_ = false; 1245 1246 bool is_compositing_active = host_->is_accelerated_compositing_active(); 1247 if (is_compositing_active && current_surface_.get()) { 1248 window_->layer()->SetExternalTexture(current_surface_.get()); 1249 current_frame_size_ = ConvertSizeToDIP( 1250 current_surface_->device_scale_factor(), current_surface_->size()); 1251 CheckResizeLock(); 1252 software_frame_manager_->DiscardCurrentFrame(); 1253 } else if (is_compositing_active && 1254 software_frame_manager_->HasCurrentFrame()) { 1255 cc::TextureMailbox mailbox; 1256 scoped_ptr<cc::SingleReleaseCallback> callback; 1257 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback); 1258 window_->layer()->SetTextureMailbox(mailbox, 1259 callback.Pass(), 1260 last_swapped_surface_scale_factor_); 1261 current_frame_size_ = ConvertSizeToDIP(last_swapped_surface_scale_factor_, 1262 mailbox.shared_memory_size()); 1263 CheckResizeLock(); 1264 } else { 1265 window_->layer()->SetShowPaintedContent(); 1266 resize_lock_.reset(); 1267 host_->WasResized(); 1268 software_frame_manager_->DiscardCurrentFrame(); 1269 } 1270 } 1271 1272 bool RenderWidgetHostViewAura::SwapBuffersPrepare( 1273 const gfx::Rect& surface_rect, 1274 float surface_scale_factor, 1275 const gfx::Rect& damage_rect, 1276 const std::string& mailbox_name, 1277 const BufferPresentedCallback& ack_callback) { 1278 if (last_swapped_surface_size_ != surface_rect.size()) { 1279 // The surface could have shrunk since we skipped an update, in which 1280 // case we can expect a full update. 1281 DLOG_IF(ERROR, damage_rect != surface_rect) << "Expected full damage rect"; 1282 skipped_damage_.setEmpty(); 1283 last_swapped_surface_size_ = surface_rect.size(); 1284 last_swapped_surface_scale_factor_ = surface_scale_factor; 1285 } 1286 1287 if (ShouldSkipFrame(ConvertSizeToDIP(surface_scale_factor, 1288 surface_rect.size())) || 1289 mailbox_name.empty()) { 1290 skipped_damage_.op(RectToSkIRect(damage_rect), SkRegion::kUnion_Op); 1291 ack_callback.Run(true, scoped_refptr<ui::Texture>()); 1292 return false; 1293 } 1294 1295 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 1296 current_surface_ = 1297 factory->CreateTransportClient(surface_scale_factor); 1298 if (!current_surface_.get()) { 1299 LOG(ERROR) << "Failed to create ImageTransport texture"; 1300 ack_callback.Run(true, scoped_refptr<ui::Texture>()); 1301 return false; 1302 } 1303 1304 current_surface_->Consume(mailbox_name, surface_rect.size()); 1305 released_front_lock_ = NULL; 1306 UpdateExternalTexture(); 1307 1308 return true; 1309 } 1310 1311 void RenderWidgetHostViewAura::SwapBuffersCompleted( 1312 const BufferPresentedCallback& ack_callback, 1313 const scoped_refptr<ui::Texture>& texture_to_return) { 1314 ui::Compositor* compositor = GetCompositor(); 1315 if (!compositor) { 1316 ack_callback.Run(false, texture_to_return); 1317 } else { 1318 AddOnCommitCallbackAndDisableLocks( 1319 base::Bind(ack_callback, false, texture_to_return)); 1320 } 1321 1322 DidReceiveFrameFromRenderer(); 1323 } 1324 1325 void RenderWidgetHostViewAura::DidReceiveFrameFromRenderer() { 1326 if (frame_subscriber() && CanCopyToVideoFrame()) { 1327 const base::Time present_time = base::Time::Now(); 1328 scoped_refptr<media::VideoFrame> frame; 1329 RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback; 1330 if (frame_subscriber()->ShouldCaptureFrame(present_time, 1331 &frame, &callback)) { 1332 CopyFromCompositingSurfaceToVideoFrame( 1333 gfx::Rect(current_frame_size_), 1334 frame, 1335 base::Bind(callback, present_time)); 1336 } 1337 } 1338 } 1339 1340 #if defined(OS_WIN) 1341 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects( 1342 const std::vector<gfx::Rect>& rects) { 1343 // Check this before setting constrained_rects_, so that next time they're set 1344 // and we have a root window we don't early return. 1345 if (!window_->GetDispatcher()) 1346 return; 1347 1348 if (rects == constrained_rects_) 1349 return; 1350 1351 constrained_rects_ = rects; 1352 1353 HWND parent = window_->GetDispatcher()->host()->GetAcceleratedWidget(); 1354 CutoutRectsParams params; 1355 params.widget = this; 1356 params.cutout_rects = constrained_rects_; 1357 params.geometry = &plugin_window_moves_; 1358 LPARAM lparam = reinterpret_cast<LPARAM>(¶ms); 1359 EnumChildWindows(parent, SetCutoutRectsCallback, lparam); 1360 } 1361 #endif 1362 1363 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( 1364 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, 1365 int gpu_host_id) { 1366 BufferPresentedCallback ack_callback = base::Bind( 1367 &AcknowledgeBufferForGpu, 1368 params_in_pixel.route_id, 1369 gpu_host_id, 1370 params_in_pixel.mailbox_name); 1371 BuffersSwapped(params_in_pixel.size, 1372 gfx::Rect(params_in_pixel.size), 1373 params_in_pixel.scale_factor, 1374 params_in_pixel.mailbox_name, 1375 params_in_pixel.latency_info, 1376 ack_callback); 1377 } 1378 1379 void RenderWidgetHostViewAura::SwapDelegatedFrame( 1380 uint32 output_surface_id, 1381 scoped_ptr<cc::DelegatedFrameData> frame_data, 1382 float frame_device_scale_factor, 1383 const ui::LatencyInfo& latency_info) { 1384 DCHECK_NE(0u, frame_data->render_pass_list.size()); 1385 1386 cc::RenderPass* root_pass = frame_data->render_pass_list.back(); 1387 1388 gfx::Size frame_size = root_pass->output_rect.size(); 1389 gfx::Size frame_size_in_dip = 1390 ConvertSizeToDIP(frame_device_scale_factor, frame_size); 1391 1392 gfx::Rect damage_rect = gfx::ToEnclosingRect(root_pass->damage_rect); 1393 damage_rect.Intersect(gfx::Rect(frame_size)); 1394 gfx::Rect damage_rect_in_dip = 1395 ConvertRectToDIP(frame_device_scale_factor, damage_rect); 1396 1397 software_frame_manager_->DiscardCurrentFrame(); 1398 1399 if (ShouldSkipFrame(frame_size_in_dip)) { 1400 cc::CompositorFrameAck ack; 1401 cc::TransferableResource::ReturnResources(frame_data->resource_list, 1402 &ack.resources); 1403 RenderWidgetHostImpl::SendSwapCompositorFrameAck( 1404 host_->GetRoutingID(), output_surface_id, 1405 host_->GetProcess()->GetID(), ack); 1406 skipped_frames_ = true; 1407 return; 1408 } 1409 1410 if (skipped_frames_) { 1411 skipped_frames_ = false; 1412 damage_rect = gfx::Rect(frame_size); 1413 damage_rect_in_dip = gfx::Rect(frame_size_in_dip); 1414 1415 // Give the same damage rect to the compositor. 1416 cc::RenderPass* root_pass = frame_data->render_pass_list.back(); 1417 root_pass->damage_rect = damage_rect; 1418 } 1419 1420 if (output_surface_id != last_output_surface_id_) { 1421 // Resource ids are scoped by the output surface. 1422 // If the originating output surface doesn't match the last one, it 1423 // indicates the renderer's output surface may have been recreated, in which 1424 // case we should recreate the DelegatedRendererLayer, to avoid matching 1425 // resources from the old one with resources from the new one which would 1426 // have the same id. Changing the layer to showing painted content destroys 1427 // the DelegatedRendererLayer. 1428 EvictDelegatedFrame(); 1429 1430 // Drop the cc::DelegatedFrameResourceCollection so that we will not return 1431 // any resources from the old output surface with the new output surface id. 1432 if (resource_collection_.get()) { 1433 resource_collection_->SetClient(NULL); 1434 1435 if (resource_collection_->LoseAllResources()) 1436 SendReturnedDelegatedResources(last_output_surface_id_); 1437 1438 resource_collection_ = NULL; 1439 } 1440 last_output_surface_id_ = output_surface_id; 1441 } 1442 if (frame_size.IsEmpty()) { 1443 DCHECK_EQ(0u, frame_data->resource_list.size()); 1444 EvictDelegatedFrame(); 1445 } else { 1446 if (!resource_collection_) { 1447 resource_collection_ = new cc::DelegatedFrameResourceCollection; 1448 resource_collection_->SetClient(this); 1449 } 1450 // If the physical frame size changes, we need a new |frame_provider_|. If 1451 // the physical frame size is the same, but the size in DIP changed, we 1452 // need to adjust the scale at which the frames will be drawn, and we do 1453 // this by making a new |frame_provider_| also to ensure the scale change 1454 // is presented in sync with the new frame content. 1455 if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() || 1456 frame_size_in_dip != current_frame_size_) { 1457 frame_provider_ = new cc::DelegatedFrameProvider( 1458 resource_collection_.get(), frame_data.Pass()); 1459 window_->layer()->SetShowDelegatedContent(frame_provider_.get(), 1460 frame_size_in_dip); 1461 } else { 1462 frame_provider_->SetFrameData(frame_data.Pass()); 1463 } 1464 } 1465 released_front_lock_ = NULL; 1466 current_frame_size_ = frame_size_in_dip; 1467 CheckResizeLock(); 1468 1469 if (paint_observer_) 1470 paint_observer_->OnUpdateCompositorContent(); 1471 window_->SchedulePaintInRect(damage_rect_in_dip); 1472 1473 pending_delegated_ack_count_++; 1474 1475 ui::Compositor* compositor = GetCompositor(); 1476 if (!compositor) { 1477 SendDelegatedFrameAck(output_surface_id); 1478 } else { 1479 compositor->SetLatencyInfo(latency_info); 1480 AddOnCommitCallbackAndDisableLocks( 1481 base::Bind(&RenderWidgetHostViewAura::SendDelegatedFrameAck, 1482 AsWeakPtr(), 1483 output_surface_id)); 1484 } 1485 DidReceiveFrameFromRenderer(); 1486 if (frame_provider_.get()) 1487 delegated_frame_evictor_->SwappedFrame(!host_->is_hidden()); 1488 // Note: the frame may have been evicted immediately. 1489 } 1490 1491 void RenderWidgetHostViewAura::SendDelegatedFrameAck(uint32 output_surface_id) { 1492 cc::CompositorFrameAck ack; 1493 if (resource_collection_) 1494 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 1495 RenderWidgetHostImpl::SendSwapCompositorFrameAck(host_->GetRoutingID(), 1496 output_surface_id, 1497 host_->GetProcess()->GetID(), 1498 ack); 1499 DCHECK_GT(pending_delegated_ack_count_, 0); 1500 pending_delegated_ack_count_--; 1501 } 1502 1503 void RenderWidgetHostViewAura::UnusedResourcesAreAvailable() { 1504 if (pending_delegated_ack_count_) 1505 return; 1506 1507 SendReturnedDelegatedResources(last_output_surface_id_); 1508 } 1509 1510 void RenderWidgetHostViewAura::SendReturnedDelegatedResources( 1511 uint32 output_surface_id) { 1512 cc::CompositorFrameAck ack; 1513 if (resource_collection_) 1514 resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources); 1515 DCHECK(!ack.resources.empty()); 1516 RenderWidgetHostImpl::SendReclaimCompositorResources( 1517 host_->GetRoutingID(), 1518 output_surface_id, 1519 host_->GetProcess()->GetID(), 1520 ack); 1521 } 1522 1523 void RenderWidgetHostViewAura::EvictDelegatedFrame() { 1524 window_->layer()->SetShowPaintedContent(); 1525 frame_provider_ = NULL; 1526 delegated_frame_evictor_->DiscardedFrame(); 1527 } 1528 1529 void RenderWidgetHostViewAura::SwapSoftwareFrame( 1530 uint32 output_surface_id, 1531 scoped_ptr<cc::SoftwareFrameData> frame_data, 1532 float frame_device_scale_factor, 1533 const ui::LatencyInfo& latency_info) { 1534 const gfx::Size& frame_size = frame_data->size; 1535 const gfx::Rect& damage_rect = frame_data->damage_rect; 1536 gfx::Size frame_size_in_dip = 1537 ConvertSizeToDIP(frame_device_scale_factor, frame_size); 1538 if (ShouldSkipFrame(frame_size_in_dip)) { 1539 ReleaseSoftwareFrame(output_surface_id, frame_data->id); 1540 SendSoftwareFrameAck(output_surface_id); 1541 return; 1542 } 1543 1544 if (!software_frame_manager_->SwapToNewFrame( 1545 output_surface_id, 1546 frame_data.get(), 1547 frame_device_scale_factor, 1548 host_->GetProcess()->GetHandle())) { 1549 ReleaseSoftwareFrame(output_surface_id, frame_data->id); 1550 SendSoftwareFrameAck(output_surface_id); 1551 return; 1552 } 1553 1554 if (last_swapped_surface_size_ != frame_size) { 1555 DLOG_IF(ERROR, damage_rect != gfx::Rect(frame_size)) 1556 << "Expected full damage rect"; 1557 } 1558 last_swapped_surface_size_ = frame_size; 1559 last_swapped_surface_scale_factor_ = frame_device_scale_factor; 1560 1561 cc::TextureMailbox mailbox; 1562 scoped_ptr<cc::SingleReleaseCallback> callback; 1563 software_frame_manager_->GetCurrentFrameMailbox(&mailbox, &callback); 1564 DCHECK(mailbox.IsSharedMemory()); 1565 current_frame_size_ = frame_size_in_dip; 1566 1567 released_front_lock_ = NULL; 1568 CheckResizeLock(); 1569 window_->layer()->SetTextureMailbox(mailbox, 1570 callback.Pass(), 1571 frame_device_scale_factor); 1572 window_->SchedulePaintInRect( 1573 ConvertRectToDIP(frame_device_scale_factor, damage_rect)); 1574 1575 ui::Compositor* compositor = GetCompositor(); 1576 if (compositor) { 1577 compositor->SetLatencyInfo(latency_info); 1578 AddOnCommitCallbackAndDisableLocks( 1579 base::Bind(&RenderWidgetHostViewAura::SendSoftwareFrameAck, 1580 AsWeakPtr(), 1581 output_surface_id)); 1582 } else { 1583 SendSoftwareFrameAck(output_surface_id); 1584 } 1585 if (paint_observer_) 1586 paint_observer_->OnUpdateCompositorContent(); 1587 DidReceiveFrameFromRenderer(); 1588 1589 software_frame_manager_->SwapToNewFrameComplete(!host_->is_hidden()); 1590 } 1591 1592 void RenderWidgetHostViewAura::SendSoftwareFrameAck(uint32 output_surface_id) { 1593 unsigned software_frame_id = 0; 1594 if (released_software_frame_ && 1595 released_software_frame_->output_surface_id == output_surface_id) { 1596 software_frame_id = released_software_frame_->frame_id; 1597 released_software_frame_.reset(); 1598 } 1599 1600 cc::CompositorFrameAck ack; 1601 ack.last_software_frame_id = software_frame_id; 1602 RenderWidgetHostImpl::SendSwapCompositorFrameAck( 1603 host_->GetRoutingID(), output_surface_id, 1604 host_->GetProcess()->GetID(), ack); 1605 SendReclaimSoftwareFrames(); 1606 } 1607 1608 void RenderWidgetHostViewAura::SendReclaimSoftwareFrames() { 1609 if (!released_software_frame_) 1610 return; 1611 cc::CompositorFrameAck ack; 1612 ack.last_software_frame_id = released_software_frame_->frame_id; 1613 RenderWidgetHostImpl::SendReclaimCompositorResources( 1614 host_->GetRoutingID(), 1615 released_software_frame_->output_surface_id, 1616 host_->GetProcess()->GetID(), 1617 ack); 1618 released_software_frame_.reset(); 1619 } 1620 1621 void RenderWidgetHostViewAura::ReleaseSoftwareFrame( 1622 uint32 output_surface_id, 1623 unsigned software_frame_id) { 1624 SendReclaimSoftwareFrames(); 1625 DCHECK(!released_software_frame_); 1626 released_software_frame_.reset(new ReleasedFrameInfo( 1627 output_surface_id, software_frame_id)); 1628 } 1629 1630 void RenderWidgetHostViewAura::OnSwapCompositorFrame( 1631 uint32 output_surface_id, 1632 scoped_ptr<cc::CompositorFrame> frame) { 1633 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame"); 1634 if (frame->delegated_frame_data) { 1635 SwapDelegatedFrame(output_surface_id, 1636 frame->delegated_frame_data.Pass(), 1637 frame->metadata.device_scale_factor, 1638 frame->metadata.latency_info); 1639 return; 1640 } 1641 1642 if (frame->software_frame_data) { 1643 SwapSoftwareFrame(output_surface_id, 1644 frame->software_frame_data.Pass(), 1645 frame->metadata.device_scale_factor, 1646 frame->metadata.latency_info); 1647 return; 1648 } 1649 1650 if (!frame->gl_frame_data || frame->gl_frame_data->mailbox.IsZero()) 1651 return; 1652 1653 BufferPresentedCallback ack_callback = base::Bind( 1654 &SendCompositorFrameAck, 1655 host_->GetRoutingID(), output_surface_id, host_->GetProcess()->GetID(), 1656 frame->gl_frame_data->mailbox, frame->gl_frame_data->size); 1657 1658 if (!frame->gl_frame_data->sync_point) { 1659 LOG(ERROR) << "CompositorFrame without sync point. Skipping frame..."; 1660 ack_callback.Run(true, scoped_refptr<ui::Texture>()); 1661 return; 1662 } 1663 1664 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 1665 factory->WaitSyncPoint(frame->gl_frame_data->sync_point); 1666 1667 std::string mailbox_name( 1668 reinterpret_cast<const char*>(frame->gl_frame_data->mailbox.name), 1669 sizeof(frame->gl_frame_data->mailbox.name)); 1670 BuffersSwapped(frame->gl_frame_data->size, 1671 frame->gl_frame_data->sub_buffer_rect, 1672 frame->metadata.device_scale_factor, 1673 mailbox_name, 1674 frame->metadata.latency_info, 1675 ack_callback); 1676 } 1677 1678 #if defined(OS_WIN) 1679 void RenderWidgetHostViewAura::SetParentNativeViewAccessible( 1680 gfx::NativeViewAccessible accessible_parent) { 1681 if (GetBrowserAccessibilityManager()) { 1682 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin() 1683 ->set_parent_iaccessible(accessible_parent); 1684 } 1685 } 1686 1687 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin() 1688 const { 1689 return reinterpret_cast<gfx::NativeViewId>(plugin_parent_window_); 1690 } 1691 #endif 1692 1693 void RenderWidgetHostViewAura::BuffersSwapped( 1694 const gfx::Size& surface_size, 1695 const gfx::Rect& damage_rect, 1696 float surface_scale_factor, 1697 const std::string& mailbox_name, 1698 const ui::LatencyInfo& latency_info, 1699 const BufferPresentedCallback& ack_callback) { 1700 scoped_refptr<ui::Texture> previous_texture(current_surface_); 1701 const gfx::Rect surface_rect = gfx::Rect(surface_size); 1702 software_frame_manager_->DiscardCurrentFrame(); 1703 1704 if (!SwapBuffersPrepare(surface_rect, 1705 surface_scale_factor, 1706 damage_rect, 1707 mailbox_name, 1708 ack_callback)) { 1709 return; 1710 } 1711 1712 SkRegion damage(RectToSkIRect(damage_rect)); 1713 if (!skipped_damage_.isEmpty()) { 1714 damage.op(skipped_damage_, SkRegion::kUnion_Op); 1715 skipped_damage_.setEmpty(); 1716 } 1717 1718 DCHECK(surface_rect.Contains(SkIRectToRect(damage.getBounds()))); 1719 ui::Texture* current_texture = current_surface_.get(); 1720 1721 const gfx::Size surface_size_in_pixel = surface_size; 1722 DLOG_IF(ERROR, previous_texture.get() && 1723 previous_texture->size() != current_texture->size() && 1724 SkIRectToRect(damage.getBounds()) != surface_rect) << 1725 "Expected full damage rect after size change"; 1726 if (previous_texture.get() && !previous_damage_.isEmpty() && 1727 previous_texture->size() == current_texture->size()) { 1728 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 1729 GLHelper* gl_helper = factory->GetGLHelper(); 1730 gl_helper->CopySubBufferDamage( 1731 current_texture->PrepareTexture(), 1732 previous_texture->PrepareTexture(), 1733 damage, 1734 previous_damage_); 1735 } 1736 previous_damage_ = damage; 1737 1738 ui::Compositor* compositor = GetCompositor(); 1739 if (compositor) { 1740 // Co-ordinates come in OpenGL co-ordinate space. 1741 // We need to convert to layer space. 1742 gfx::Rect rect_to_paint = 1743 ConvertRectToDIP(surface_scale_factor, 1744 gfx::Rect(damage_rect.x(), 1745 surface_size_in_pixel.height() - 1746 damage_rect.y() - damage_rect.height(), 1747 damage_rect.width(), 1748 damage_rect.height())); 1749 1750 // Damage may not have been DIP aligned, so inflate damage to compensate 1751 // for any round-off error. 1752 rect_to_paint.Inset(-1, -1); 1753 rect_to_paint.Intersect(window_->bounds()); 1754 1755 if (paint_observer_) 1756 paint_observer_->OnUpdateCompositorContent(); 1757 window_->SchedulePaintInRect(rect_to_paint); 1758 compositor->SetLatencyInfo(latency_info); 1759 } 1760 1761 SwapBuffersCompleted(ack_callback, previous_texture); 1762 } 1763 1764 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( 1765 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, 1766 int gpu_host_id) { 1767 gfx::Rect damage_rect(params_in_pixel.x, 1768 params_in_pixel.y, 1769 params_in_pixel.width, 1770 params_in_pixel.height); 1771 BufferPresentedCallback ack_callback = 1772 base::Bind(&AcknowledgeBufferForGpu, 1773 params_in_pixel.route_id, 1774 gpu_host_id, 1775 params_in_pixel.mailbox_name); 1776 BuffersSwapped(params_in_pixel.surface_size, 1777 damage_rect, 1778 params_in_pixel.surface_scale_factor, 1779 params_in_pixel.mailbox_name, 1780 params_in_pixel.latency_info, 1781 ack_callback); 1782 } 1783 1784 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() { 1785 } 1786 1787 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() { 1788 // This really tells us to release the frontbuffer. 1789 if (current_surface_.get()) { 1790 ui::Compositor* compositor = GetCompositor(); 1791 if (compositor) { 1792 // We need to wait for a commit to clear to guarantee that all we 1793 // will not issue any more GL referencing the previous surface. 1794 AddOnCommitCallbackAndDisableLocks( 1795 base::Bind(&RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor, 1796 AsWeakPtr(), 1797 current_surface_)); // Hold a ref so the texture will not 1798 // get deleted until after commit. 1799 } 1800 current_surface_ = NULL; 1801 UpdateExternalTexture(); 1802 } 1803 } 1804 1805 bool RenderWidgetHostViewAura::HasAcceleratedSurface( 1806 const gfx::Size& desired_size) { 1807 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't 1808 // matter what is returned here as GetBackingStore is the only caller of this 1809 // method. TODO(jbates) implement this if other Aura code needs it. 1810 return false; 1811 } 1812 1813 void RenderWidgetHostViewAura::SetSurfaceNotInUseByCompositor( 1814 scoped_refptr<ui::Texture>) { 1815 } 1816 1817 // static 1818 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult( 1819 const gfx::Size& dst_size_in_pixel, 1820 const base::Callback<void(bool, const SkBitmap&)>& callback, 1821 scoped_ptr<cc::CopyOutputResult> result) { 1822 if (result->IsEmpty() || result->size().IsEmpty()) { 1823 callback.Run(false, SkBitmap()); 1824 return; 1825 } 1826 1827 if (result->HasTexture()) { 1828 PrepareTextureCopyOutputResult(dst_size_in_pixel, callback, result.Pass()); 1829 return; 1830 } 1831 1832 DCHECK(result->HasBitmap()); 1833 PrepareBitmapCopyOutputResult(dst_size_in_pixel, callback, result.Pass()); 1834 } 1835 1836 static void CopyFromCompositingSurfaceFinished( 1837 const base::Callback<void(bool, const SkBitmap&)>& callback, 1838 scoped_ptr<cc::SingleReleaseCallback> release_callback, 1839 scoped_ptr<SkBitmap> bitmap, 1840 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock, 1841 bool result) { 1842 bitmap_pixels_lock.reset(); 1843 release_callback->Run(0, false); 1844 callback.Run(result, *bitmap); 1845 } 1846 1847 // static 1848 void RenderWidgetHostViewAura::PrepareTextureCopyOutputResult( 1849 const gfx::Size& dst_size_in_pixel, 1850 const base::Callback<void(bool, const SkBitmap&)>& callback, 1851 scoped_ptr<cc::CopyOutputResult> result) { 1852 base::ScopedClosureRunner scoped_callback_runner( 1853 base::Bind(callback, false, SkBitmap())); 1854 1855 DCHECK(result->HasTexture()); 1856 if (!result->HasTexture()) 1857 return; 1858 1859 scoped_ptr<SkBitmap> bitmap(new SkBitmap); 1860 bitmap->setConfig(SkBitmap::kARGB_8888_Config, 1861 dst_size_in_pixel.width(), dst_size_in_pixel.height(), 1862 0, kOpaque_SkAlphaType); 1863 if (!bitmap->allocPixels()) 1864 return; 1865 1866 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 1867 GLHelper* gl_helper = factory->GetGLHelper(); 1868 if (!gl_helper) 1869 return; 1870 1871 scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock( 1872 new SkAutoLockPixels(*bitmap)); 1873 uint8* pixels = static_cast<uint8*>(bitmap->getPixels()); 1874 1875 cc::TextureMailbox texture_mailbox; 1876 scoped_ptr<cc::SingleReleaseCallback> release_callback; 1877 result->TakeTexture(&texture_mailbox, &release_callback); 1878 DCHECK(texture_mailbox.IsTexture()); 1879 if (!texture_mailbox.IsTexture()) 1880 return; 1881 1882 ignore_result(scoped_callback_runner.Release()); 1883 1884 gl_helper->CropScaleReadbackAndCleanMailbox( 1885 texture_mailbox.name(), 1886 texture_mailbox.sync_point(), 1887 result->size(), 1888 gfx::Rect(result->size()), 1889 dst_size_in_pixel, 1890 pixels, 1891 base::Bind(&CopyFromCompositingSurfaceFinished, 1892 callback, 1893 base::Passed(&release_callback), 1894 base::Passed(&bitmap), 1895 base::Passed(&bitmap_pixels_lock))); 1896 } 1897 1898 // static 1899 void RenderWidgetHostViewAura::PrepareBitmapCopyOutputResult( 1900 const gfx::Size& dst_size_in_pixel, 1901 const base::Callback<void(bool, const SkBitmap&)>& callback, 1902 scoped_ptr<cc::CopyOutputResult> result) { 1903 DCHECK(result->HasBitmap()); 1904 1905 base::ScopedClosureRunner scoped_callback_runner( 1906 base::Bind(callback, false, SkBitmap())); 1907 if (!result->HasBitmap()) 1908 return; 1909 1910 scoped_ptr<SkBitmap> source = result->TakeBitmap(); 1911 DCHECK(source); 1912 if (!source) 1913 return; 1914 1915 ignore_result(scoped_callback_runner.Release()); 1916 1917 SkBitmap bitmap = skia::ImageOperations::Resize( 1918 *source, 1919 skia::ImageOperations::RESIZE_BEST, 1920 dst_size_in_pixel.width(), 1921 dst_size_in_pixel.height()); 1922 callback.Run(true, bitmap); 1923 } 1924 1925 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo( 1926 base::WeakPtr<RenderWidgetHostViewAura> rwhva, 1927 const base::Callback<void(bool)>& callback, 1928 scoped_refptr<OwnedMailbox> subscriber_texture, 1929 scoped_ptr<cc::SingleReleaseCallback> release_callback, 1930 bool result) { 1931 callback.Run(result); 1932 1933 GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper(); 1934 uint32 sync_point = gl_helper ? gl_helper->InsertSyncPoint() : 0; 1935 if (release_callback) { 1936 DCHECK(!subscriber_texture); 1937 release_callback->Run(sync_point, false); 1938 } else { 1939 // If there's no release callback, then the texture is from 1940 // idle_frame_subscriber_textures_ and we can put it back there. 1941 DCHECK(subscriber_texture); 1942 subscriber_texture->UpdateSyncPoint(sync_point); 1943 if (rwhva && rwhva->frame_subscriber_ && subscriber_texture->texture_id()) 1944 rwhva->idle_frame_subscriber_textures_.push_back(subscriber_texture); 1945 subscriber_texture = NULL; 1946 } 1947 } 1948 1949 // static 1950 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResultForVideo( 1951 base::WeakPtr<RenderWidgetHostViewAura> rwhva, 1952 scoped_refptr<OwnedMailbox> subscriber_texture, 1953 scoped_refptr<media::VideoFrame> video_frame, 1954 const base::Callback<void(bool)>& callback, 1955 scoped_ptr<cc::CopyOutputResult> result) { 1956 base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false)); 1957 1958 if (!rwhva) 1959 return; 1960 if (result->IsEmpty()) 1961 return; 1962 if (result->size().IsEmpty()) 1963 return; 1964 1965 // Compute the dest size we want after the letterboxing resize. Make the 1966 // coordinates and sizes even because we letterbox in YUV space 1967 // (see CopyRGBToVideoFrame). They need to be even for the UV samples to 1968 // line up correctly. 1969 // The video frame's coded_size() and the result's size() are both physical 1970 // pixels. 1971 gfx::Rect region_in_frame = 1972 media::ComputeLetterboxRegion(gfx::Rect(video_frame->coded_size()), 1973 result->size()); 1974 region_in_frame = gfx::Rect(region_in_frame.x() & ~1, 1975 region_in_frame.y() & ~1, 1976 region_in_frame.width() & ~1, 1977 region_in_frame.height() & ~1); 1978 if (region_in_frame.IsEmpty()) 1979 return; 1980 1981 // We only handle texture readbacks for now. If the compositor is in software 1982 // mode, we could produce a software-backed VideoFrame here as well. 1983 if (!result->HasTexture()) { 1984 DCHECK(result->HasBitmap()); 1985 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap(); 1986 // Scale the bitmap to the required size, if necessary. 1987 SkBitmap scaled_bitmap; 1988 if (result->size().width() != region_in_frame.width() || 1989 result->size().height() != region_in_frame.height()) { 1990 skia::ImageOperations::ResizeMethod method = 1991 skia::ImageOperations::RESIZE_GOOD; 1992 scaled_bitmap = skia::ImageOperations::Resize(*bitmap.get(), method, 1993 region_in_frame.width(), 1994 region_in_frame.height()); 1995 } else { 1996 scaled_bitmap = *bitmap.get(); 1997 } 1998 1999 { 2000 SkAutoLockPixels scaled_bitmap_locker(scaled_bitmap); 2001 2002 media::CopyRGBToVideoFrame( 2003 reinterpret_cast<uint8*>(scaled_bitmap.getPixels()), 2004 scaled_bitmap.rowBytes(), 2005 region_in_frame, 2006 video_frame.get()); 2007 } 2008 ignore_result(scoped_callback_runner.Release()); 2009 callback.Run(true); 2010 return; 2011 } 2012 2013 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 2014 GLHelper* gl_helper = factory->GetGLHelper(); 2015 if (!gl_helper) 2016 return; 2017 2018 cc::TextureMailbox texture_mailbox; 2019 scoped_ptr<cc::SingleReleaseCallback> release_callback; 2020 result->TakeTexture(&texture_mailbox, &release_callback); 2021 DCHECK(texture_mailbox.IsTexture()); 2022 if (!texture_mailbox.IsTexture()) 2023 return; 2024 2025 gfx::Rect result_rect(result->size()); 2026 2027 content::ReadbackYUVInterface* yuv_readback_pipeline = 2028 rwhva->yuv_readback_pipeline_.get(); 2029 if (yuv_readback_pipeline == NULL || 2030 yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() || 2031 yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect || 2032 yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) { 2033 GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST; 2034 std::string quality_switch = switches::kTabCaptureDownscaleQuality; 2035 // If we're scaling up, we can use the "best" quality. 2036 if (result_rect.size().width() < region_in_frame.size().width() && 2037 result_rect.size().height() < region_in_frame.size().height()) 2038 quality_switch = switches::kTabCaptureUpscaleQuality; 2039 2040 std::string switch_value = 2041 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch); 2042 if (switch_value == "fast") 2043 quality = GLHelper::SCALER_QUALITY_FAST; 2044 else if (switch_value == "good") 2045 quality = GLHelper::SCALER_QUALITY_GOOD; 2046 else if (switch_value == "best") 2047 quality = GLHelper::SCALER_QUALITY_BEST; 2048 2049 rwhva->yuv_readback_pipeline_.reset( 2050 gl_helper->CreateReadbackPipelineYUV(quality, 2051 result_rect.size(), 2052 result_rect, 2053 video_frame->coded_size(), 2054 region_in_frame, 2055 true, 2056 true)); 2057 yuv_readback_pipeline = rwhva->yuv_readback_pipeline_.get(); 2058 } 2059 2060 ignore_result(scoped_callback_runner.Release()); 2061 base::Callback<void(bool result)> finished_callback = base::Bind( 2062 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceFinishedForVideo, 2063 rwhva->AsWeakPtr(), 2064 callback, 2065 subscriber_texture, 2066 base::Passed(&release_callback)); 2067 yuv_readback_pipeline->ReadbackYUV( 2068 texture_mailbox.name(), 2069 texture_mailbox.sync_point(), 2070 video_frame.get(), 2071 finished_callback); 2072 } 2073 2074 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) { 2075 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL); 2076 } 2077 2078 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() { 2079 #if defined(OS_WIN) 2080 // aura::Window::GetBoundsInScreen doesn't take non-client area into 2081 // account. 2082 RECT window_rect = {0}; 2083 2084 aura::Window* top_level = window_->GetToplevelWindow(); 2085 aura::WindowEventDispatcher* dispatcher = top_level->GetDispatcher(); 2086 if (!dispatcher) 2087 return top_level->GetBoundsInScreen(); 2088 HWND hwnd = dispatcher->host()->GetAcceleratedWidget(); 2089 ::GetWindowRect(hwnd, &window_rect); 2090 gfx::Rect rect(window_rect); 2091 2092 // Maximized windows are outdented from the work area by the frame thickness 2093 // even though this "frame" is not painted. This confuses code (and people) 2094 // that think of a maximized window as corresponding exactly to the work area. 2095 // Correct for this by subtracting the frame thickness back off. 2096 if (::IsZoomed(hwnd)) { 2097 rect.Inset(GetSystemMetrics(SM_CXSIZEFRAME), 2098 GetSystemMetrics(SM_CYSIZEFRAME)); 2099 } 2100 2101 return gfx::win::ScreenToDIPRect(rect); 2102 #else 2103 return window_->GetToplevelWindow()->GetBoundsInScreen(); 2104 #endif 2105 } 2106 2107 void RenderWidgetHostViewAura::GestureEventAck(int gesture_event_type, 2108 InputEventAckState ack_result) { 2109 if (touch_editing_client_) 2110 touch_editing_client_->GestureEventAck(gesture_event_type); 2111 } 2112 2113 void RenderWidgetHostViewAura::ProcessAckedTouchEvent( 2114 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { 2115 ScopedVector<ui::TouchEvent> events; 2116 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, 2117 SCREEN_COORDINATES)) 2118 return; 2119 2120 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 2121 // |dispatcher| is NULL during tests. 2122 if (!dispatcher) 2123 return; 2124 2125 ui::EventResult result = (ack_result == 2126 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; 2127 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), 2128 end = events.end(); iter != end; ++iter) { 2129 dispatcher->ProcessedTouchEvent((*iter), window_, result); 2130 } 2131 } 2132 2133 scoped_ptr<SyntheticGestureTarget> 2134 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() { 2135 return scoped_ptr<SyntheticGestureTarget>( 2136 new SyntheticGestureTargetAura(host_)); 2137 } 2138 2139 void RenderWidgetHostViewAura::SetHasHorizontalScrollbar( 2140 bool has_horizontal_scrollbar) { 2141 // Not needed. Mac-only. 2142 } 2143 2144 void RenderWidgetHostViewAura::SetScrollOffsetPinning( 2145 bool is_pinned_to_left, bool is_pinned_to_right) { 2146 // Not needed. Mac-only. 2147 } 2148 2149 void RenderWidgetHostViewAura::OnAccessibilityEvents( 2150 const std::vector<AccessibilityHostMsg_EventParams>& params) { 2151 BrowserAccessibilityManager* manager = 2152 GetOrCreateBrowserAccessibilityManager(); 2153 if (manager) 2154 manager->OnAccessibilityEvents(params); 2155 } 2156 2157 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() { 2158 if (shared_surface_handle_.is_null()) { 2159 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 2160 shared_surface_handle_ = factory->CreateSharedSurfaceHandle(); 2161 if (!shared_surface_handle_.is_null()) 2162 factory->AddObserver(this); 2163 } 2164 return shared_surface_handle_; 2165 } 2166 2167 bool RenderWidgetHostViewAura::LockMouse() { 2168 aura::Window* root_window = window_->GetRootWindow(); 2169 if (!root_window) 2170 return false; 2171 2172 if (mouse_locked_) 2173 return true; 2174 2175 mouse_locked_ = true; 2176 #if !defined(OS_WIN) 2177 window_->SetCapture(); 2178 #endif 2179 aura::client::CursorClient* cursor_client = 2180 aura::client::GetCursorClient(root_window); 2181 if (cursor_client) { 2182 cursor_client->HideCursor(); 2183 cursor_client->LockCursor(); 2184 } 2185 2186 if (ShouldMoveToCenter()) { 2187 synthetic_move_sent_ = true; 2188 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint()); 2189 } 2190 if (aura::client::GetTooltipClient(root_window)) 2191 aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(false); 2192 2193 root_window->GetDispatcher()->host()->ConfineCursorToRootWindow(); 2194 return true; 2195 } 2196 2197 void RenderWidgetHostViewAura::UnlockMouse() { 2198 aura::Window* root_window = window_->GetRootWindow(); 2199 if (!mouse_locked_ || !root_window) 2200 return; 2201 2202 mouse_locked_ = false; 2203 2204 #if !defined(OS_WIN) 2205 window_->ReleaseCapture(); 2206 #endif 2207 window_->MoveCursorTo(unlocked_mouse_position_); 2208 aura::client::CursorClient* cursor_client = 2209 aura::client::GetCursorClient(root_window); 2210 if (cursor_client) { 2211 cursor_client->UnlockCursor(); 2212 cursor_client->ShowCursor(); 2213 } 2214 2215 if (aura::client::GetTooltipClient(root_window)) 2216 aura::client::GetTooltipClient(root_window)->SetTooltipsEnabled(true); 2217 2218 host_->LostMouseLock(); 2219 root_window->GetDispatcher()->host()->UnConfineCursor(); 2220 } 2221 2222 //////////////////////////////////////////////////////////////////////////////// 2223 // RenderWidgetHostViewAura, ui::TextInputClient implementation: 2224 void RenderWidgetHostViewAura::SetCompositionText( 2225 const ui::CompositionText& composition) { 2226 if (!host_) 2227 return; 2228 2229 // ui::CompositionUnderline should be identical to 2230 // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely. 2231 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) == 2232 sizeof(blink::WebCompositionUnderline), 2233 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff); 2234 2235 // TODO(suzhe): convert both renderer_host and renderer to use 2236 // ui::CompositionText. 2237 const std::vector<blink::WebCompositionUnderline>& underlines = 2238 reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>( 2239 composition.underlines); 2240 2241 // TODO(suzhe): due to a bug of webkit, we can't use selection range with 2242 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788 2243 host_->ImeSetComposition(composition.text, underlines, 2244 composition.selection.end(), 2245 composition.selection.end()); 2246 2247 has_composition_text_ = !composition.text.empty(); 2248 } 2249 2250 void RenderWidgetHostViewAura::ConfirmCompositionText() { 2251 if (host_ && has_composition_text_) { 2252 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), 2253 false); 2254 } 2255 has_composition_text_ = false; 2256 } 2257 2258 void RenderWidgetHostViewAura::ClearCompositionText() { 2259 if (host_ && has_composition_text_) 2260 host_->ImeCancelComposition(); 2261 has_composition_text_ = false; 2262 } 2263 2264 void RenderWidgetHostViewAura::InsertText(const base::string16& text) { 2265 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE); 2266 if (host_) 2267 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false); 2268 has_composition_text_ = false; 2269 } 2270 2271 void RenderWidgetHostViewAura::InsertChar(char16 ch, int flags) { 2272 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) { 2273 popup_child_host_view_->InsertChar(ch, flags); 2274 return; 2275 } 2276 2277 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547 2278 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) { 2279 double now = ui::EventTimeForNow().InSecondsF(); 2280 // Send a blink::WebInputEvent::Char event to |host_|. 2281 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED, 2282 true /* is_char */, 2283 ch, 2284 flags, 2285 now); 2286 host_->ForwardKeyboardEvent(webkit_event); 2287 } 2288 } 2289 2290 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const { 2291 return window_; 2292 } 2293 2294 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const { 2295 return text_input_type_; 2296 } 2297 2298 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const { 2299 return text_input_mode_; 2300 } 2301 2302 bool RenderWidgetHostViewAura::CanComposeInline() const { 2303 return can_compose_inline_; 2304 } 2305 2306 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen( 2307 const gfx::Rect& rect) const { 2308 gfx::Point origin = rect.origin(); 2309 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); 2310 2311 aura::Window* root_window = window_->GetRootWindow(); 2312 if (!root_window) 2313 return rect; 2314 aura::client::ScreenPositionClient* screen_position_client = 2315 aura::client::GetScreenPositionClient(root_window); 2316 if (!screen_position_client) 2317 return rect; 2318 screen_position_client->ConvertPointToScreen(window_, &origin); 2319 screen_position_client->ConvertPointToScreen(window_, &end); 2320 return gfx::Rect(origin.x(), 2321 origin.y(), 2322 end.x() - origin.x(), 2323 end.y() - origin.y()); 2324 } 2325 2326 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen( 2327 const gfx::Rect& rect) const { 2328 gfx::Point origin = rect.origin(); 2329 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); 2330 2331 aura::Window* root_window = window_->GetRootWindow(); 2332 if (root_window) { 2333 aura::client::ScreenPositionClient* screen_position_client = 2334 aura::client::GetScreenPositionClient(root_window); 2335 screen_position_client->ConvertPointFromScreen(window_, &origin); 2336 screen_position_client->ConvertPointFromScreen(window_, &end); 2337 return gfx::Rect(origin.x(), 2338 origin.y(), 2339 end.x() - origin.x(), 2340 end.y() - origin.y()); 2341 } 2342 2343 return rect; 2344 } 2345 2346 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const { 2347 const gfx::Rect rect = 2348 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_); 2349 return ConvertRectToScreen(rect); 2350 } 2351 2352 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds( 2353 uint32 index, 2354 gfx::Rect* rect) const { 2355 DCHECK(rect); 2356 if (index >= composition_character_bounds_.size()) 2357 return false; 2358 *rect = ConvertRectToScreen(composition_character_bounds_[index]); 2359 return true; 2360 } 2361 2362 bool RenderWidgetHostViewAura::HasCompositionText() const { 2363 return has_composition_text_; 2364 } 2365 2366 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const { 2367 range->set_start(selection_text_offset_); 2368 range->set_end(selection_text_offset_ + selection_text_.length()); 2369 return true; 2370 } 2371 2372 bool RenderWidgetHostViewAura::GetCompositionTextRange( 2373 gfx::Range* range) const { 2374 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 2375 NOTIMPLEMENTED(); 2376 return false; 2377 } 2378 2379 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const { 2380 range->set_start(selection_range_.start()); 2381 range->set_end(selection_range_.end()); 2382 return true; 2383 } 2384 2385 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) { 2386 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 2387 NOTIMPLEMENTED(); 2388 return false; 2389 } 2390 2391 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) { 2392 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 2393 NOTIMPLEMENTED(); 2394 return false; 2395 } 2396 2397 bool RenderWidgetHostViewAura::GetTextFromRange( 2398 const gfx::Range& range, 2399 base::string16* text) const { 2400 gfx::Range selection_text_range(selection_text_offset_, 2401 selection_text_offset_ + selection_text_.length()); 2402 2403 if (!selection_text_range.Contains(range)) { 2404 text->clear(); 2405 return false; 2406 } 2407 if (selection_text_range.EqualsIgnoringDirection(range)) { 2408 // Avoid calling substr whose performance is low. 2409 *text = selection_text_; 2410 } else { 2411 *text = selection_text_.substr( 2412 range.GetMin() - selection_text_offset_, 2413 range.length()); 2414 } 2415 return true; 2416 } 2417 2418 void RenderWidgetHostViewAura::OnInputMethodChanged() { 2419 if (!host_) 2420 return; 2421 2422 if (GetInputMethod()) 2423 host_->SetInputMethodActive(GetInputMethod()->IsActive()); 2424 2425 // TODO(suzhe): implement the newly added locale property of HTML DOM 2426 // TextEvent. 2427 } 2428 2429 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment( 2430 base::i18n::TextDirection direction) { 2431 if (!host_) 2432 return false; 2433 host_->UpdateTextDirection( 2434 direction == base::i18n::RIGHT_TO_LEFT ? 2435 blink::WebTextDirectionRightToLeft : 2436 blink::WebTextDirectionLeftToRight); 2437 host_->NotifyTextDirection(); 2438 return true; 2439 } 2440 2441 void RenderWidgetHostViewAura::ExtendSelectionAndDelete( 2442 size_t before, size_t after) { 2443 if (host_) 2444 host_->ExtendSelectionAndDelete(before, after); 2445 } 2446 2447 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) { 2448 gfx::Rect intersected_rect( 2449 gfx::IntersectRects(rect, window_->GetBoundsInScreen())); 2450 2451 if (intersected_rect.IsEmpty()) 2452 return; 2453 2454 host_->ScrollFocusedEditableNodeIntoRect( 2455 ConvertRectFromScreen(intersected_rect)); 2456 } 2457 2458 void RenderWidgetHostViewAura::OnCandidateWindowShown() { 2459 host_->CandidateWindowShown(); 2460 } 2461 2462 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() { 2463 host_->CandidateWindowUpdated(); 2464 } 2465 2466 void RenderWidgetHostViewAura::OnCandidateWindowHidden() { 2467 host_->CandidateWindowHidden(); 2468 } 2469 2470 //////////////////////////////////////////////////////////////////////////////// 2471 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation: 2472 2473 void RenderWidgetHostViewAura::OnDisplayBoundsChanged( 2474 const gfx::Display& display) { 2475 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_); 2476 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) { 2477 UpdateScreenInfo(window_); 2478 current_cursor_.SetDisplayInfo(display); 2479 UpdateCursorIfOverSelf(); 2480 } 2481 } 2482 2483 void RenderWidgetHostViewAura::OnDisplayAdded( 2484 const gfx::Display& new_display) { 2485 } 2486 2487 void RenderWidgetHostViewAura::OnDisplayRemoved( 2488 const gfx::Display& old_display) { 2489 } 2490 2491 //////////////////////////////////////////////////////////////////////////////// 2492 // RenderWidgetHostViewAura, aura::WindowDelegate implementation: 2493 2494 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const { 2495 return gfx::Size(); 2496 } 2497 2498 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const { 2499 return gfx::Size(); 2500 } 2501 2502 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, 2503 const gfx::Rect& new_bounds) { 2504 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true); 2505 // We care about this only in fullscreen mode, where there is no 2506 // WebContentsViewAura. We are sized via SetSize() or SetBounds() by 2507 // WebContentsViewAura in other cases. 2508 if (is_fullscreen_) 2509 SetSize(new_bounds.size()); 2510 } 2511 2512 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) { 2513 if (mouse_locked_) 2514 return ui::kCursorNone; 2515 return current_cursor_.GetNativeCursor(); 2516 } 2517 2518 int RenderWidgetHostViewAura::GetNonClientComponent( 2519 const gfx::Point& point) const { 2520 return HTCLIENT; 2521 } 2522 2523 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling( 2524 aura::Window* child, 2525 const gfx::Point& location) { 2526 return true; 2527 } 2528 2529 bool RenderWidgetHostViewAura::CanFocus() { 2530 return popup_type_ == blink::WebPopupTypeNone; 2531 } 2532 2533 void RenderWidgetHostViewAura::OnCaptureLost() { 2534 host_->LostCapture(); 2535 if (touch_editing_client_) 2536 touch_editing_client_->EndTouchEditing(); 2537 } 2538 2539 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) { 2540 bool has_backing_store = !!host_->GetBackingStore(false); 2541 if (has_backing_store) { 2542 paint_canvas_ = canvas; 2543 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>( 2544 host_->GetBackingStore(true)); 2545 paint_canvas_ = NULL; 2546 backing_store->SkiaShowRect(gfx::Point(), canvas); 2547 2548 if (paint_observer_) 2549 paint_observer_->OnPaintComplete(); 2550 ui::Compositor* compositor = GetCompositor(); 2551 if (compositor) { 2552 compositor->SetLatencyInfo(software_latency_info_); 2553 software_latency_info_.Clear(); 2554 } 2555 } else { 2556 // For non-opaque windows, we don't draw anything, since we depend on the 2557 // canvas coming from the compositor to already be initialized as 2558 // transparent. 2559 if (window_->layer()->fills_bounds_opaquely()) 2560 canvas->DrawColor(SK_ColorWHITE); 2561 } 2562 } 2563 2564 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged( 2565 float device_scale_factor) { 2566 if (!host_) 2567 return; 2568 2569 BackingStoreAura* backing_store = static_cast<BackingStoreAura*>( 2570 host_->GetBackingStore(false)); 2571 if (backing_store) // NULL in hardware path. 2572 backing_store->ScaleFactorChanged(device_scale_factor); 2573 2574 UpdateScreenInfo(window_); 2575 2576 const gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 2577 GetDisplayNearestWindow(window_); 2578 DCHECK_EQ(device_scale_factor, display.device_scale_factor()); 2579 current_cursor_.SetDisplayInfo(display); 2580 } 2581 2582 void RenderWidgetHostViewAura::OnWindowDestroying() { 2583 #if defined(OS_WIN) 2584 HWND parent = NULL; 2585 // If the tab was hidden and it's closed, host_->is_hidden would have been 2586 // reset to false in RenderWidgetHostImpl::RendererExited. 2587 if (!window_->GetRootWindow() || host_->is_hidden()) { 2588 parent = ui::GetHiddenWindow(); 2589 } else { 2590 parent = window_->GetDispatcher()->host()->GetAcceleratedWidget(); 2591 } 2592 LPARAM lparam = reinterpret_cast<LPARAM>(this); 2593 EnumChildWindows(parent, WindowDestroyingCallback, lparam); 2594 #endif 2595 2596 // Make sure that the input method no longer references to this object before 2597 // this object is removed from the root window (i.e. this object loses access 2598 // to the input method). 2599 ui::InputMethod* input_method = GetInputMethod(); 2600 if (input_method) 2601 input_method->DetachTextInputClient(this); 2602 } 2603 2604 void RenderWidgetHostViewAura::OnWindowDestroyed() { 2605 host_->ViewDestroyed(); 2606 delete this; 2607 } 2608 2609 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) { 2610 } 2611 2612 bool RenderWidgetHostViewAura::HasHitTestMask() const { 2613 return false; 2614 } 2615 2616 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const { 2617 } 2618 2619 void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer, 2620 ui::Layer *new_layer) { 2621 float mailbox_scale_factor; 2622 cc::TextureMailbox old_mailbox = 2623 old_layer->GetTextureMailbox(&mailbox_scale_factor); 2624 scoped_refptr<ui::Texture> old_texture = old_layer->external_texture(); 2625 // The new_layer is the one that will be used by our Window, so that's the one 2626 // that should keep our texture. old_layer will be returned to the 2627 // RecreateLayer caller, and should have a copy. 2628 if (old_texture.get()) { 2629 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 2630 GLHelper* gl_helper = factory->GetGLHelper(); 2631 scoped_refptr<ui::Texture> new_texture; 2632 if (host_->is_accelerated_compositing_active() && 2633 gl_helper && current_surface_.get()) { 2634 blink::WebGLId texture_id = 2635 gl_helper->CopyTexture(current_surface_->PrepareTexture(), 2636 current_surface_->size()); 2637 if (texture_id) { 2638 new_texture = factory->CreateOwnedTexture( 2639 current_surface_->size(), 2640 current_surface_->device_scale_factor(), texture_id); 2641 } 2642 } 2643 if (new_texture.get()) 2644 old_layer->SetExternalTexture(new_texture.get()); 2645 else 2646 old_layer->SetShowPaintedContent(); 2647 new_layer->SetExternalTexture(old_texture.get()); 2648 } else if (old_mailbox.IsSharedMemory()) { 2649 base::SharedMemory* old_buffer = old_mailbox.shared_memory(); 2650 const size_t size = old_mailbox.shared_memory_size_in_bytes(); 2651 2652 scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory); 2653 new_buffer->CreateAndMapAnonymous(size); 2654 2655 if (old_buffer->memory() && new_buffer->memory()) { 2656 memcpy(new_buffer->memory(), old_buffer->memory(), size); 2657 base::SharedMemory* new_buffer_raw_ptr = new_buffer.get(); 2658 scoped_ptr<cc::SingleReleaseCallback> callback = 2659 cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback, 2660 Passed(&new_buffer))); 2661 cc::TextureMailbox new_mailbox(new_buffer_raw_ptr, 2662 old_mailbox.shared_memory_size()); 2663 new_layer->SetTextureMailbox(new_mailbox, 2664 callback.Pass(), 2665 mailbox_scale_factor); 2666 } 2667 } else if (frame_provider_.get()) { 2668 new_layer->SetShowDelegatedContent(frame_provider_.get(), 2669 current_frame_size_); 2670 } 2671 } 2672 2673 //////////////////////////////////////////////////////////////////////////////// 2674 // RenderWidgetHostViewAura, ui::EventHandler implementation: 2675 2676 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) { 2677 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent"); 2678 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 2679 return; 2680 2681 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) { 2682 popup_child_host_view_->OnKeyEvent(event); 2683 if (event->handled()) 2684 return; 2685 } 2686 2687 // We need to handle the Escape key for Pepper Flash. 2688 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) { 2689 // Focus the window we were created from. 2690 if (host_tracker_.get() && !host_tracker_->windows().empty()) { 2691 aura::Window* host = *(host_tracker_->windows().begin()); 2692 aura::client::FocusClient* client = aura::client::GetFocusClient(host); 2693 if (client) { 2694 // Calling host->Focus() may delete |this|. We create a local observer 2695 // for that. In that case we exit without further access to any members. 2696 aura::WindowTracker tracker; 2697 aura::Window* window = window_; 2698 tracker.Add(window); 2699 host->Focus(); 2700 if (!tracker.Contains(window)) { 2701 event->SetHandled(); 2702 return; 2703 } 2704 } 2705 } 2706 if (!in_shutdown_) { 2707 in_shutdown_ = true; 2708 host_->Shutdown(); 2709 } 2710 } else { 2711 if (event->key_code() == ui::VKEY_RETURN) { 2712 // Do not forward return key release events if no press event was handled. 2713 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_) 2714 return; 2715 // Accept return key character events between press and release events. 2716 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED; 2717 } 2718 2719 // We don't have to communicate with an input method here. 2720 if (!event->HasNativeEvent()) { 2721 NativeWebKeyboardEvent webkit_event( 2722 event->type(), 2723 event->is_char(), 2724 event->is_char() ? event->GetCharacter() : event->key_code(), 2725 event->flags(), 2726 ui::EventTimeForNow().InSecondsF()); 2727 host_->ForwardKeyboardEvent(webkit_event); 2728 } else { 2729 NativeWebKeyboardEvent webkit_event(event); 2730 host_->ForwardKeyboardEvent(webkit_event); 2731 } 2732 } 2733 event->SetHandled(); 2734 } 2735 2736 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) { 2737 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent"); 2738 2739 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 2740 return; 2741 2742 if (mouse_locked_) { 2743 aura::client::CursorClient* cursor_client = 2744 aura::client::GetCursorClient(window_->GetRootWindow()); 2745 DCHECK(!cursor_client || !cursor_client->IsCursorVisible()); 2746 2747 if (event->type() == ui::ET_MOUSEWHEEL) { 2748 blink::WebMouseWheelEvent mouse_wheel_event = 2749 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event)); 2750 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) 2751 host_->ForwardWheelEvent(mouse_wheel_event); 2752 return; 2753 } 2754 2755 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint()); 2756 2757 // If we receive non client mouse messages while we are in the locked state 2758 // it probably means that the mouse left the borders of our window and 2759 // needs to be moved back to the center. 2760 if (event->flags() & ui::EF_IS_NON_CLIENT) { 2761 synthetic_move_sent_ = true; 2762 window_->MoveCursorTo(center); 2763 return; 2764 } 2765 2766 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event); 2767 2768 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED || 2769 event->type() == ui::ET_MOUSE_DRAGGED) && 2770 mouse_event.x == center.x() && mouse_event.y == center.y(); 2771 2772 ModifyEventMovementAndCoords(&mouse_event); 2773 2774 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_; 2775 if (should_not_forward) { 2776 synthetic_move_sent_ = false; 2777 } else { 2778 // Check if the mouse has reached the border and needs to be centered. 2779 if (ShouldMoveToCenter()) { 2780 synthetic_move_sent_ = true; 2781 window_->MoveCursorTo(center); 2782 } 2783 // Forward event to renderer. 2784 if (CanRendererHandleEvent(event) && 2785 !(event->flags() & ui::EF_FROM_TOUCH)) { 2786 host_->ForwardMouseEvent(mouse_event); 2787 // Ensure that we get keyboard focus on mouse down as a plugin window 2788 // may have grabbed keyboard focus. 2789 if (event->type() == ui::ET_MOUSE_PRESSED) 2790 SetKeyboardFocus(); 2791 } 2792 } 2793 return; 2794 } 2795 2796 // As the overscroll is handled during scroll events from the trackpad, the 2797 // RWHVA window is transformed by the overscroll controller. This transform 2798 // triggers a synthetic mouse-move event to be generated (by the aura 2799 // RootWindow). But this event interferes with the overscroll gesture. So, 2800 // ignore such synthetic mouse-move events if an overscroll gesture is in 2801 // progress. 2802 if (host_->overscroll_controller() && 2803 host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE && 2804 event->flags() & ui::EF_IS_SYNTHESIZED && 2805 (event->type() == ui::ET_MOUSE_ENTERED || 2806 event->type() == ui::ET_MOUSE_EXITED || 2807 event->type() == ui::ET_MOUSE_MOVED)) { 2808 event->StopPropagation(); 2809 return; 2810 } 2811 2812 if (event->type() == ui::ET_MOUSEWHEEL) { 2813 #if defined(OS_WIN) 2814 // We get mouse wheel/scroll messages even if we are not in the foreground. 2815 // So here we check if we have any owned popup windows in the foreground and 2816 // dismiss them. 2817 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 2818 if (dispatcher) { 2819 HWND parent = dispatcher->host()->GetAcceleratedWidget(); 2820 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT); 2821 EnumThreadWindows(GetCurrentThreadId(), 2822 DismissOwnedPopups, 2823 reinterpret_cast<LPARAM>(toplevel_hwnd)); 2824 } 2825 #endif 2826 blink::WebMouseWheelEvent mouse_wheel_event = 2827 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event)); 2828 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) 2829 host_->ForwardWheelEvent(mouse_wheel_event); 2830 } else if (CanRendererHandleEvent(event) && 2831 !(event->flags() & ui::EF_FROM_TOUCH)) { 2832 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event); 2833 ModifyEventMovementAndCoords(&mouse_event); 2834 host_->ForwardMouseEvent(mouse_event); 2835 // Ensure that we get keyboard focus on mouse down as a plugin window may 2836 // have grabbed keyboard focus. 2837 if (event->type() == ui::ET_MOUSE_PRESSED) 2838 SetKeyboardFocus(); 2839 } 2840 2841 switch (event->type()) { 2842 case ui::ET_MOUSE_PRESSED: 2843 window_->SetCapture(); 2844 // Confirm existing composition text on mouse click events, to make sure 2845 // the input caret won't be moved with an ongoing composition text. 2846 FinishImeCompositionSession(); 2847 break; 2848 case ui::ET_MOUSE_RELEASED: 2849 window_->ReleaseCapture(); 2850 break; 2851 default: 2852 break; 2853 } 2854 2855 // Needed to propagate mouse event to native_tab_contents_view_aura. 2856 // TODO(pkotwicz): Find a better way of doing this. 2857 // In fullscreen mode which is typically used by flash, don't forward 2858 // the mouse events to the parent. The renderer and the plugin process 2859 // handle these events. 2860 if (!is_fullscreen_ && window_->parent()->delegate() && 2861 !(event->flags() & ui::EF_FROM_TOUCH)) 2862 window_->parent()->delegate()->OnMouseEvent(event); 2863 2864 if (!IsXButtonUpEvent(event)) 2865 event->SetHandled(); 2866 } 2867 2868 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) { 2869 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent"); 2870 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 2871 return; 2872 2873 if (event->type() == ui::ET_SCROLL) { 2874 #if !defined(OS_WIN) 2875 // TODO(ananta) 2876 // Investigate if this is true for Windows 8 Metro ASH as well. 2877 if (event->finger_count() != 2) 2878 return; 2879 #endif 2880 blink::WebGestureEvent gesture_event = 2881 MakeWebGestureEventFlingCancel(); 2882 host_->ForwardGestureEvent(gesture_event); 2883 blink::WebMouseWheelEvent mouse_wheel_event = 2884 MakeWebMouseWheelEvent(event); 2885 host_->ForwardWheelEvent(mouse_wheel_event); 2886 RecordAction(UserMetricsAction("TrackpadScroll")); 2887 } else if (event->type() == ui::ET_SCROLL_FLING_START || 2888 event->type() == ui::ET_SCROLL_FLING_CANCEL) { 2889 blink::WebGestureEvent gesture_event = 2890 MakeWebGestureEvent(event); 2891 host_->ForwardGestureEvent(gesture_event); 2892 if (event->type() == ui::ET_SCROLL_FLING_START) 2893 RecordAction(UserMetricsAction("TrackpadScrollFling")); 2894 } 2895 2896 event->SetHandled(); 2897 } 2898 2899 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) { 2900 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent"); 2901 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 2902 return; 2903 2904 // Update the touch event first. 2905 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event, 2906 &touch_event_); 2907 2908 // Forward the touch event only if a touch point was updated, and there's a 2909 // touch-event handler in the page, and no other touch-event is in the queue. 2910 // It is important to always consume the event if there is a touch-event 2911 // handler in the page, or some touch-event is already in the queue, even if 2912 // no point has been updated, to make sure that this event does not get 2913 // processed by the gesture recognizer before the events in the queue. 2914 if (host_->ShouldForwardTouchEvent()) 2915 event->StopPropagation(); 2916 2917 if (point) { 2918 if (host_->ShouldForwardTouchEvent()) 2919 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency()); 2920 UpdateWebTouchEventAfterDispatch(&touch_event_, point); 2921 } 2922 } 2923 2924 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) { 2925 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent"); 2926 // Pinch gestures are currently disabled by default. See crbug.com/128477. 2927 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN || 2928 event->type() == ui::ET_GESTURE_PINCH_UPDATE || 2929 event->type() == ui::ET_GESTURE_PINCH_END) && !ShouldSendPinchGesture()) { 2930 event->SetHandled(); 2931 return; 2932 } 2933 2934 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 2935 return; 2936 2937 RenderViewHostDelegate* delegate = NULL; 2938 if (popup_type_ == blink::WebPopupTypeNone && !is_fullscreen_) 2939 delegate = RenderViewHost::From(host_)->GetDelegate(); 2940 2941 if (delegate && event->type() == ui::ET_GESTURE_BEGIN && 2942 event->details().touch_points() == 1) { 2943 delegate->HandleGestureBegin(); 2944 } 2945 2946 blink::WebGestureEvent gesture = MakeWebGestureEvent(event); 2947 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { 2948 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an 2949 // event to stop any in-progress flings. 2950 blink::WebGestureEvent fling_cancel = gesture; 2951 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel; 2952 fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen; 2953 host_->ForwardGestureEvent(fling_cancel); 2954 } 2955 2956 if (gesture.type != blink::WebInputEvent::Undefined) { 2957 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency()); 2958 2959 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || 2960 event->type() == ui::ET_GESTURE_SCROLL_UPDATE || 2961 event->type() == ui::ET_GESTURE_SCROLL_END) { 2962 RecordAction(UserMetricsAction("TouchscreenScroll")); 2963 } else if (event->type() == ui::ET_SCROLL_FLING_START) { 2964 RecordAction(UserMetricsAction("TouchscreenScrollFling")); 2965 } 2966 } 2967 2968 if (delegate && event->type() == ui::ET_GESTURE_END && 2969 event->details().touch_points() == 1) { 2970 delegate->HandleGestureEnd(); 2971 } 2972 2973 // If a gesture is not processed by the webpage, then WebKit processes it 2974 // (e.g. generates synthetic mouse events). 2975 event->SetHandled(); 2976 } 2977 2978 //////////////////////////////////////////////////////////////////////////////// 2979 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation: 2980 2981 bool RenderWidgetHostViewAura::ShouldActivate() const { 2982 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 2983 if (!dispatcher) 2984 return true; 2985 const ui::Event* event = dispatcher->current_event(); 2986 if (!event) 2987 return true; 2988 return is_fullscreen_; 2989 } 2990 2991 //////////////////////////////////////////////////////////////////////////////// 2992 // RenderWidgetHostViewAura, 2993 // aura::client::ActivationChangeObserver implementation: 2994 2995 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active, 2996 aura::Window* lost_active) { 2997 DCHECK(window_ == gained_active || window_ == lost_active); 2998 if (window_ == gained_active) { 2999 const ui::Event* event = window_->GetDispatcher()->current_event(); 3000 if (event && PointerEventActivates(*event)) 3001 host_->OnPointerEventActivate(); 3002 } 3003 } 3004 3005 //////////////////////////////////////////////////////////////////////////////// 3006 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation: 3007 3008 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) { 3009 NotifyRendererOfCursorVisibilityState(is_visible); 3010 } 3011 3012 //////////////////////////////////////////////////////////////////////////////// 3013 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation: 3014 3015 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus, 3016 aura::Window* lost_focus) { 3017 DCHECK(window_ == gained_focus || window_ == lost_focus); 3018 if (window_ == gained_focus) { 3019 // We need to honor input bypass if the associated tab is does not want 3020 // input. This gives the current focused window a chance to be the text 3021 // input client and handle events. 3022 if (host_->ignore_input_events()) 3023 return; 3024 3025 host_->GotFocus(); 3026 host_->SetActive(true); 3027 3028 ui::InputMethod* input_method = GetInputMethod(); 3029 if (input_method) { 3030 // Ask the system-wide IME to send all TextInputClient messages to |this| 3031 // object. 3032 input_method->SetFocusedTextInputClient(this); 3033 host_->SetInputMethodActive(input_method->IsActive()); 3034 3035 // Often the application can set focus to the view in response to a key 3036 // down. However the following char event shouldn't be sent to the web 3037 // page. 3038 host_->SuppressNextCharEvents(); 3039 } else { 3040 host_->SetInputMethodActive(false); 3041 } 3042 } else if (window_ == lost_focus) { 3043 host_->SetActive(false); 3044 host_->Blur(); 3045 3046 DetachFromInputMethod(); 3047 host_->SetInputMethodActive(false); 3048 3049 if (touch_editing_client_) 3050 touch_editing_client_->EndTouchEditing(); 3051 3052 // If we lose the focus while fullscreen, close the window; Pepper Flash 3053 // won't do it for us (unlike NPAPI Flash). However, we do not close the 3054 // window if we lose the focus to a window on another display. 3055 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_); 3056 bool focusing_other_display = 3057 gained_focus && screen->GetNumDisplays() > 1 && 3058 (screen->GetDisplayNearestWindow(window_).id() != 3059 screen->GetDisplayNearestWindow(gained_focus).id()); 3060 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) { 3061 #if defined(OS_WIN) 3062 // On Windows, if we are switching to a non Aura Window on a different 3063 // screen we should not close the fullscreen window. 3064 if (!gained_focus) { 3065 POINT point = {0}; 3066 ::GetCursorPos(&point); 3067 if (screen->GetDisplayNearestWindow(window_).id() != 3068 screen->GetDisplayNearestPoint(gfx::Point(point)).id()) 3069 return; 3070 } 3071 #endif 3072 in_shutdown_ = true; 3073 host_->Shutdown(); 3074 } 3075 } 3076 } 3077 3078 //////////////////////////////////////////////////////////////////////////////// 3079 // RenderWidgetHostViewAura, aura::RootWindowObserver implementation: 3080 3081 void RenderWidgetHostViewAura::OnRootWindowHostMoved( 3082 const aura::RootWindow* root, 3083 const gfx::Point& new_origin) { 3084 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnRootWindowHostMoved", 3085 "new_origin", new_origin.ToString()); 3086 3087 UpdateScreenInfo(window_); 3088 } 3089 3090 //////////////////////////////////////////////////////////////////////////////// 3091 // RenderWidgetHostViewAura, SoftwareFrameManagerClient implementation: 3092 3093 void RenderWidgetHostViewAura::SoftwareFrameWasFreed( 3094 uint32 output_surface_id, unsigned frame_id) { 3095 ReleaseSoftwareFrame(output_surface_id, frame_id); 3096 } 3097 3098 void RenderWidgetHostViewAura::ReleaseReferencesToSoftwareFrame() { 3099 ui::Compositor* compositor = GetCompositor(); 3100 if (compositor) { 3101 AddOnCommitCallbackAndDisableLocks(base::Bind( 3102 &RenderWidgetHostViewAura::SendReclaimSoftwareFrames, AsWeakPtr())); 3103 } 3104 UpdateExternalTexture(); 3105 } 3106 3107 //////////////////////////////////////////////////////////////////////////////// 3108 // RenderWidgetHostViewAura, ui::CompositorObserver implementation: 3109 3110 void RenderWidgetHostViewAura::OnCompositingDidCommit( 3111 ui::Compositor* compositor) { 3112 if (can_lock_compositor_ == NO_PENDING_COMMIT) { 3113 can_lock_compositor_ = YES; 3114 if (resize_lock_.get() && resize_lock_->GrabDeferredLock()) 3115 can_lock_compositor_ = YES_DID_LOCK; 3116 } 3117 RunOnCommitCallbacks(); 3118 if (resize_lock_ && resize_lock_->expected_size() == current_frame_size_) { 3119 resize_lock_.reset(); 3120 host_->WasResized(); 3121 // We may have had a resize while we had the lock (e.g. if the lock expired, 3122 // or if the UI still gave us some resizes), so make sure we grab a new lock 3123 // if necessary. 3124 MaybeCreateResizeLock(); 3125 } 3126 } 3127 3128 void RenderWidgetHostViewAura::OnCompositingStarted( 3129 ui::Compositor* compositor, base::TimeTicks start_time) { 3130 last_draw_ended_ = start_time; 3131 } 3132 3133 void RenderWidgetHostViewAura::OnCompositingEnded( 3134 ui::Compositor* compositor) { 3135 if (paint_observer_) 3136 paint_observer_->OnCompositingComplete(); 3137 } 3138 3139 void RenderWidgetHostViewAura::OnCompositingAborted( 3140 ui::Compositor* compositor) { 3141 } 3142 3143 void RenderWidgetHostViewAura::OnCompositingLockStateChanged( 3144 ui::Compositor* compositor) { 3145 // A compositor lock that is part of a resize lock timed out. We 3146 // should display a renderer frame. 3147 if (!compositor->IsLocked() && can_lock_compositor_ == YES_DID_LOCK) { 3148 can_lock_compositor_ = NO_PENDING_RENDERER_FRAME; 3149 } 3150 } 3151 3152 void RenderWidgetHostViewAura::OnUpdateVSyncParameters( 3153 ui::Compositor* compositor, 3154 base::TimeTicks timebase, 3155 base::TimeDelta interval) { 3156 if (IsShowing()) { 3157 if (IsDeadlineSchedulingEnabled()) { 3158 // The deadline scheduler has logic to stagger the draws of the 3159 // Renderer and Browser built-in, so send it an accurate timebase. 3160 host_->UpdateVSyncParameters(timebase, interval); 3161 } else if (!last_draw_ended_.is_null()) { 3162 // For the non-deadline scheduler, we send the Renderer an offset 3163 // vsync timebase to avoid its draws racing the Browser's draws. 3164 host_->UpdateVSyncParameters(last_draw_ended_, interval); 3165 } 3166 } 3167 } 3168 3169 //////////////////////////////////////////////////////////////////////////////// 3170 // RenderWidgetHostViewAura, BrowserAccessibilityDelegate implementation: 3171 3172 void RenderWidgetHostViewAura::SetAccessibilityFocus(int acc_obj_id) { 3173 if (!host_) 3174 return; 3175 3176 host_->AccessibilitySetFocus(acc_obj_id); 3177 } 3178 3179 void RenderWidgetHostViewAura::AccessibilityDoDefaultAction(int acc_obj_id) { 3180 if (!host_) 3181 return; 3182 3183 host_->AccessibilityDoDefaultAction(acc_obj_id); 3184 } 3185 3186 void RenderWidgetHostViewAura::AccessibilityScrollToMakeVisible( 3187 int acc_obj_id, gfx::Rect subfocus) { 3188 if (!host_) 3189 return; 3190 3191 host_->AccessibilityScrollToMakeVisible(acc_obj_id, subfocus); 3192 } 3193 3194 void RenderWidgetHostViewAura::AccessibilityScrollToPoint( 3195 int acc_obj_id, gfx::Point point) { 3196 if (!host_) 3197 return; 3198 3199 host_->AccessibilityScrollToPoint(acc_obj_id, point); 3200 } 3201 3202 void RenderWidgetHostViewAura::AccessibilitySetTextSelection( 3203 int acc_obj_id, int start_offset, int end_offset) { 3204 if (!host_) 3205 return; 3206 3207 host_->AccessibilitySetTextSelection( 3208 acc_obj_id, start_offset, end_offset); 3209 } 3210 3211 gfx::Point RenderWidgetHostViewAura::GetLastTouchEventLocation() const { 3212 // Only needed for Win 8 non-aura. 3213 return gfx::Point(); 3214 } 3215 3216 void RenderWidgetHostViewAura::FatalAccessibilityTreeError() { 3217 host_->FatalAccessibilityTreeError(); 3218 SetBrowserAccessibilityManager(NULL); 3219 } 3220 3221 //////////////////////////////////////////////////////////////////////////////// 3222 // RenderWidgetHostViewAura, ImageTransportFactoryObserver implementation: 3223 3224 void RenderWidgetHostViewAura::OnLostResources() { 3225 current_surface_ = NULL; 3226 UpdateExternalTexture(); 3227 3228 idle_frame_subscriber_textures_.clear(); 3229 3230 // Make sure all ImageTransportClients are deleted now that the context those 3231 // are using is becoming invalid. This sends pending ACKs and needs to happen 3232 // after calling UpdateExternalTexture() which syncs with the impl thread. 3233 RunOnCommitCallbacks(); 3234 3235 DCHECK(!shared_surface_handle_.is_null()); 3236 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 3237 factory->DestroySharedSurfaceHandle(shared_surface_handle_); 3238 shared_surface_handle_ = factory->CreateSharedSurfaceHandle(); 3239 host_->CompositingSurfaceUpdated(); 3240 host_->ScheduleComposite(); 3241 } 3242 3243 //////////////////////////////////////////////////////////////////////////////// 3244 // RenderWidgetHostViewAura, private: 3245 3246 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() { 3247 if (paint_observer_) 3248 paint_observer_->OnViewDestroyed(); 3249 if (touch_editing_client_) 3250 touch_editing_client_->OnViewDestroyed(); 3251 if (!shared_surface_handle_.is_null()) { 3252 ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); 3253 factory->DestroySharedSurfaceHandle(shared_surface_handle_); 3254 factory->RemoveObserver(this); 3255 } 3256 window_observer_.reset(); 3257 if (window_->GetDispatcher()) 3258 window_->GetDispatcher()->RemoveRootWindowObserver(this); 3259 UnlockMouse(); 3260 if (popup_parent_host_view_) { 3261 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL || 3262 popup_parent_host_view_->popup_child_host_view_ == this); 3263 popup_parent_host_view_->popup_child_host_view_ = NULL; 3264 } 3265 if (popup_child_host_view_) { 3266 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL || 3267 popup_child_host_view_->popup_parent_host_view_ == this); 3268 popup_child_host_view_->popup_parent_host_view_ = NULL; 3269 } 3270 aura::client::SetTooltipText(window_, NULL); 3271 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this); 3272 3273 // This call is usually no-op since |this| object is already removed from the 3274 // Aura root window and we don't have a way to get an input method object 3275 // associated with the window, but just in case. 3276 DetachFromInputMethod(); 3277 3278 if (resource_collection_.get()) 3279 resource_collection_->SetClient(NULL); 3280 3281 #if defined(OS_WIN) 3282 if (::IsWindow(plugin_parent_window_)) 3283 ::DestroyWindow(plugin_parent_window_); 3284 #endif 3285 } 3286 3287 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() { 3288 const gfx::Point screen_point = 3289 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 3290 aura::Window* root_window = window_->GetRootWindow(); 3291 if (!root_window) 3292 return; 3293 3294 gfx::Rect screen_rect = GetViewBounds(); 3295 gfx::Point local_point = screen_point; 3296 local_point.Offset(-screen_rect.x(), -screen_rect.y()); 3297 3298 #if defined(OS_WIN) 3299 // If there's another toplevel window above us at this point (for example a 3300 // menu), we don't want to update the cursor. 3301 POINT windows_point = { screen_point.x(), screen_point.y() }; 3302 aura::WindowEventDispatcher* dispatcher = root_window->GetDispatcher(); 3303 if (dispatcher->host()->GetAcceleratedWidget() != 3304 ::WindowFromPoint(windows_point)) 3305 return; 3306 #endif 3307 if (root_window->GetEventHandlerForPoint(local_point) != window_) 3308 return; 3309 3310 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor(); 3311 // Do not show loading cursor when the cursor is currently hidden. 3312 if (is_loading_ && cursor != ui::kCursorNone) 3313 cursor = ui::kCursorPointer; 3314 3315 aura::client::CursorClient* cursor_client = 3316 aura::client::GetCursorClient(root_window); 3317 if (cursor_client) { 3318 cursor_client->SetCursor(cursor); 3319 } 3320 } 3321 3322 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const { 3323 aura::Window* root_window = window_->GetRootWindow(); 3324 if (!root_window) 3325 return NULL; 3326 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey); 3327 } 3328 3329 bool RenderWidgetHostViewAura::NeedsInputGrab() { 3330 return popup_type_ == blink::WebPopupTypeSelect; 3331 } 3332 3333 void RenderWidgetHostViewAura::FinishImeCompositionSession() { 3334 if (!has_composition_text_) 3335 return; 3336 if (host_) { 3337 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), 3338 false); 3339 } 3340 ImeCancelComposition(); 3341 } 3342 3343 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords( 3344 blink::WebMouseEvent* event) { 3345 // If the mouse has just entered, we must report zero movementX/Y. Hence we 3346 // reset any global_mouse_position set previously. 3347 if (event->type == blink::WebInputEvent::MouseEnter || 3348 event->type == blink::WebInputEvent::MouseLeave) 3349 global_mouse_position_.SetPoint(event->globalX, event->globalY); 3350 3351 // Movement is computed by taking the difference of the new cursor position 3352 // and the previous. Under mouse lock the cursor will be warped back to the 3353 // center so that we are not limited by clipping boundaries. 3354 // We do not measure movement as the delta from cursor to center because 3355 // we may receive more mouse movement events before our warp has taken 3356 // effect. 3357 event->movementX = event->globalX - global_mouse_position_.x(); 3358 event->movementY = event->globalY - global_mouse_position_.y(); 3359 3360 global_mouse_position_.SetPoint(event->globalX, event->globalY); 3361 3362 // Under mouse lock, coordinates of mouse are locked to what they were when 3363 // mouse lock was entered. 3364 if (mouse_locked_) { 3365 event->x = unlocked_mouse_position_.x(); 3366 event->y = unlocked_mouse_position_.y(); 3367 event->windowX = unlocked_mouse_position_.x(); 3368 event->windowY = unlocked_mouse_position_.y(); 3369 event->globalX = unlocked_global_mouse_position_.x(); 3370 event->globalY = unlocked_global_mouse_position_.y(); 3371 } else { 3372 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY); 3373 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY); 3374 } 3375 } 3376 3377 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState( 3378 bool is_visible) { 3379 if (host_->is_hidden() || 3380 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) || 3381 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible)) 3382 return; 3383 3384 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE; 3385 host_->SendCursorVisibilityState(is_visible); 3386 } 3387 3388 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip( 3389 const gfx::Rect& rect, 3390 const gfx::Rect& clip) { 3391 if (!clip.IsEmpty()) { 3392 gfx::Rect to_paint = gfx::SubtractRects(rect, clip); 3393 if (!to_paint.IsEmpty()) 3394 window_->SchedulePaintInRect(to_paint); 3395 } else { 3396 window_->SchedulePaintInRect(rect); 3397 } 3398 } 3399 3400 bool RenderWidgetHostViewAura::ShouldMoveToCenter() { 3401 gfx::Rect rect = window_->bounds(); 3402 rect = ConvertRectToScreen(rect); 3403 int border_x = rect.width() * kMouseLockBorderPercentage / 100; 3404 int border_y = rect.height() * kMouseLockBorderPercentage / 100; 3405 3406 return global_mouse_position_.x() < rect.x() + border_x || 3407 global_mouse_position_.x() > rect.right() - border_x || 3408 global_mouse_position_.y() < rect.y() + border_y || 3409 global_mouse_position_.y() > rect.bottom() - border_y; 3410 } 3411 3412 void RenderWidgetHostViewAura::RunOnCommitCallbacks() { 3413 for (std::vector<base::Closure>::const_iterator 3414 it = on_compositing_did_commit_callbacks_.begin(); 3415 it != on_compositing_did_commit_callbacks_.end(); ++it) { 3416 it->Run(); 3417 } 3418 on_compositing_did_commit_callbacks_.clear(); 3419 } 3420 3421 void RenderWidgetHostViewAura::AddOnCommitCallbackAndDisableLocks( 3422 const base::Closure& callback) { 3423 ui::Compositor* compositor = GetCompositor(); 3424 DCHECK(compositor); 3425 3426 if (!compositor->HasObserver(this)) 3427 compositor->AddObserver(this); 3428 3429 can_lock_compositor_ = NO_PENDING_COMMIT; 3430 on_compositing_did_commit_callbacks_.push_back(callback); 3431 } 3432 3433 void RenderWidgetHostViewAura::AddedToRootWindow() { 3434 window_->GetDispatcher()->AddRootWindowObserver(this); 3435 host_->ParentChanged(GetNativeViewId()); 3436 UpdateScreenInfo(window_); 3437 if (popup_type_ != blink::WebPopupTypeNone) 3438 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this)); 3439 3440 aura::client::CursorClient* cursor_client = 3441 aura::client::GetCursorClient(window_->GetRootWindow()); 3442 if (cursor_client) { 3443 cursor_client->AddObserver(this); 3444 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible()); 3445 } 3446 if (current_surface_.get()) 3447 UpdateExternalTexture(); 3448 if (HasFocus()) { 3449 ui::InputMethod* input_method = GetInputMethod(); 3450 if (input_method) 3451 input_method->SetFocusedTextInputClient(this); 3452 } 3453 } 3454 3455 void RenderWidgetHostViewAura::RemovingFromRootWindow() { 3456 aura::client::CursorClient* cursor_client = 3457 aura::client::GetCursorClient(window_->GetRootWindow()); 3458 if (cursor_client) 3459 cursor_client->RemoveObserver(this); 3460 3461 DetachFromInputMethod(); 3462 3463 event_filter_for_popup_exit_.reset(); 3464 window_->GetDispatcher()->RemoveRootWindowObserver(this); 3465 host_->ParentChanged(0); 3466 ui::Compositor* compositor = GetCompositor(); 3467 if (current_surface_.get()) { 3468 // We can't get notification for commits after this point, which would 3469 // guarantee that the compositor isn't using an old texture any more, so 3470 // instead we force the layer to stop using any external resources which 3471 // synchronizes with the compositor thread, and makes it safe to run the 3472 // callback. 3473 window_->layer()->SetShowPaintedContent(); 3474 } 3475 RunOnCommitCallbacks(); 3476 resize_lock_.reset(); 3477 host_->WasResized(); 3478 if (compositor && compositor->HasObserver(this)) 3479 compositor->RemoveObserver(this); 3480 } 3481 3482 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const { 3483 aura::WindowEventDispatcher* dispatcher = window_->GetDispatcher(); 3484 return dispatcher ? dispatcher->compositor() : NULL; 3485 } 3486 3487 void RenderWidgetHostViewAura::DetachFromInputMethod() { 3488 ui::InputMethod* input_method = GetInputMethod(); 3489 if (input_method && input_method->GetTextInputClient() == this) 3490 input_method->SetFocusedTextInputClient(NULL); 3491 } 3492 3493 //////////////////////////////////////////////////////////////////////////////// 3494 // RenderWidgetHostView, public: 3495 3496 // static 3497 RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( 3498 RenderWidgetHost* widget) { 3499 return new RenderWidgetHostViewAura(widget); 3500 } 3501 3502 // static 3503 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) { 3504 GetScreenInfoForWindow(results, NULL); 3505 } 3506 3507 } // namespace content 3508