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