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/layer.h" 17 #include "cc/output/copy_output_request.h" 18 #include "cc/output/copy_output_result.h" 19 #include "cc/resources/texture_mailbox.h" 20 #include "cc/trees/layer_tree_settings.h" 21 #include "content/browser/accessibility/browser_accessibility_manager.h" 22 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 23 #include "content/browser/frame_host/frame_tree.h" 24 #include "content/browser/frame_host/frame_tree_node.h" 25 #include "content/browser/frame_host/render_frame_host_impl.h" 26 #include "content/browser/gpu/compositor_util.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_view_host_impl.h" 33 #include "content/browser/renderer_host/render_widget_host_impl.h" 34 #include "content/browser/renderer_host/ui_events_helper.h" 35 #include "content/browser/renderer_host/web_input_event_aura.h" 36 #include "content/common/gpu/client/gl_helper.h" 37 #include "content/common/gpu/gpu_messages.h" 38 #include "content/common/view_messages.h" 39 #include "content/public/browser/content_browser_client.h" 40 #include "content/public/browser/overscroll_configuration.h" 41 #include "content/public/browser/render_view_host.h" 42 #include "content/public/browser/render_widget_host_view_frame_subscriber.h" 43 #include "content/public/browser/user_metrics.h" 44 #include "content/public/common/content_switches.h" 45 #include "third_party/WebKit/public/platform/WebScreenInfo.h" 46 #include "third_party/WebKit/public/web/WebCompositionUnderline.h" 47 #include "third_party/WebKit/public/web/WebInputEvent.h" 48 #include "ui/aura/client/aura_constants.h" 49 #include "ui/aura/client/cursor_client.h" 50 #include "ui/aura/client/cursor_client_observer.h" 51 #include "ui/aura/client/focus_client.h" 52 #include "ui/aura/client/screen_position_client.h" 53 #include "ui/aura/client/window_tree_client.h" 54 #include "ui/aura/env.h" 55 #include "ui/aura/window.h" 56 #include "ui/aura/window_event_dispatcher.h" 57 #include "ui/aura/window_observer.h" 58 #include "ui/aura/window_tracker.h" 59 #include "ui/aura/window_tree_host.h" 60 #include "ui/base/clipboard/scoped_clipboard_writer.h" 61 #include "ui/base/hit_test.h" 62 #include "ui/base/ime/input_method.h" 63 #include "ui/base/ui_base_types.h" 64 #include "ui/compositor/compositor_vsync_manager.h" 65 #include "ui/events/event.h" 66 #include "ui/events/event_utils.h" 67 #include "ui/events/gestures/gesture_recognizer.h" 68 #include "ui/gfx/canvas.h" 69 #include "ui/gfx/display.h" 70 #include "ui/gfx/rect_conversions.h" 71 #include "ui/gfx/screen.h" 72 #include "ui/gfx/size_conversions.h" 73 #include "ui/gfx/skia_util.h" 74 #include "ui/wm/public/activation_client.h" 75 #include "ui/wm/public/scoped_tooltip_disabler.h" 76 #include "ui/wm/public/tooltip_client.h" 77 #include "ui/wm/public/transient_window_client.h" 78 #include "ui/wm/public/window_types.h" 79 80 #if defined(OS_WIN) 81 #include "content/browser/accessibility/browser_accessibility_manager_win.h" 82 #include "content/browser/accessibility/browser_accessibility_win.h" 83 #include "content/browser/renderer_host/legacy_render_widget_host_win.h" 84 #include "content/common/plugin_constants_win.h" 85 #include "ui/base/win/hidden_window.h" 86 #include "ui/gfx/gdi_util.h" 87 #include "ui/gfx/win/dpi.h" 88 #endif 89 90 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 91 #include "content/common/input_messages.h" 92 #include "ui/events/linux/text_edit_command_auralinux.h" 93 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h" 94 #endif 95 96 using gfx::RectToSkIRect; 97 using gfx::SkIRectToRect; 98 99 using blink::WebScreenInfo; 100 using blink::WebInputEvent; 101 using blink::WebGestureEvent; 102 using blink::WebTouchEvent; 103 104 namespace content { 105 106 namespace { 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. 115 const 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. 121 const int kResizeLockTimeoutMs = 67; 122 123 #if defined(OS_WIN) 124 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance. 125 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner"; 126 127 BOOL 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 138 BOOL 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 146 BOOL 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 158 struct 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. 168 BOOL 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. 217 BOOL 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 231 void 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 244 bool 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 #elif defined(USE_X11) 273 // Renderer only supports standard mouse buttons, so ignore programmable 274 // buttons. 275 switch (event->type()) { 276 case ui::ET_MOUSE_PRESSED: 277 case ui::ET_MOUSE_RELEASED: 278 return event->IsAnyButton(); 279 default: 280 break; 281 } 282 #endif 283 return true; 284 } 285 286 // We don't mark these as handled so that they're sent back to the 287 // DefWindowProc so it can generate WM_APPCOMMAND as necessary. 288 bool IsXButtonUpEvent(const ui::MouseEvent* event) { 289 #if defined(OS_WIN) 290 switch (event->native_event().message) { 291 case WM_XBUTTONUP: 292 case WM_NCXBUTTONUP: 293 return true; 294 } 295 #endif 296 return false; 297 } 298 299 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) { 300 const gfx::Display display = window ? 301 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) : 302 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay(); 303 results->rect = display.bounds(); 304 results->availableRect = display.work_area(); 305 // TODO(derat|oshima): Don't hardcode this. Get this from display object. 306 results->depth = 24; 307 results->depthPerComponent = 8; 308 results->deviceScaleFactor = display.device_scale_factor(); 309 310 // The Display rotation and the WebScreenInfo orientation are not the same 311 // angle. The former is the physical display rotation while the later is the 312 // rotation required by the content to be shown properly on the screen, in 313 // other words, relative to the physical display. 314 results->orientationAngle = display.RotationAsDegree(); 315 if (results->orientationAngle == 90) 316 results->orientationAngle = 270; 317 else if (results->orientationAngle == 270) 318 results->orientationAngle = 90; 319 } 320 321 bool PointerEventActivates(const ui::Event& event) { 322 if (event.type() == ui::ET_MOUSE_PRESSED) 323 return true; 324 325 if (event.type() == ui::ET_GESTURE_BEGIN) { 326 const ui::GestureEvent& gesture = 327 static_cast<const ui::GestureEvent&>(event); 328 return gesture.details().touch_points() == 1; 329 } 330 331 return false; 332 } 333 334 } // namespace 335 336 // We need to watch for mouse events outside a Web Popup or its parent 337 // and dismiss the popup for certain events. 338 class RenderWidgetHostViewAura::EventFilterForPopupExit 339 : public ui::EventHandler { 340 public: 341 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva) 342 : rwhva_(rwhva) { 343 DCHECK(rwhva_); 344 aura::Env::GetInstance()->AddPreTargetHandler(this); 345 } 346 347 virtual ~EventFilterForPopupExit() { 348 aura::Env::GetInstance()->RemovePreTargetHandler(this); 349 } 350 351 // Overridden from ui::EventHandler 352 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { 353 rwhva_->ApplyEventFilterForPopupExit(event); 354 } 355 356 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { 357 rwhva_->ApplyEventFilterForPopupExit(event); 358 } 359 360 private: 361 RenderWidgetHostViewAura* rwhva_; 362 363 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit); 364 }; 365 366 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit( 367 ui::LocatedEvent* event) { 368 if (in_shutdown_ || is_fullscreen_ || !event->target()) 369 return; 370 371 if (event->type() != ui::ET_MOUSE_PRESSED && 372 event->type() != ui::ET_TOUCH_PRESSED) { 373 return; 374 } 375 376 aura::Window* target = static_cast<aura::Window*>(event->target()); 377 if (target != window_ && 378 (!popup_parent_host_view_ || 379 target != popup_parent_host_view_->window_)) { 380 // Note: popup_parent_host_view_ may be NULL when there are multiple 381 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup(). 382 in_shutdown_ = true; 383 host_->Shutdown(); 384 } 385 } 386 387 // We have to implement the WindowObserver interface on a separate object 388 // because clang doesn't like implementing multiple interfaces that have 389 // methods with the same name. This object is owned by the 390 // RenderWidgetHostViewAura. 391 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver { 392 public: 393 explicit WindowObserver(RenderWidgetHostViewAura* view) 394 : view_(view) { 395 view_->window_->AddObserver(this); 396 } 397 398 virtual ~WindowObserver() { 399 view_->window_->RemoveObserver(this); 400 } 401 402 // Overridden from aura::WindowObserver: 403 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE { 404 if (window == view_->window_) 405 view_->AddedToRootWindow(); 406 } 407 408 virtual void OnWindowRemovingFromRootWindow(aura::Window* window, 409 aura::Window* new_root) OVERRIDE { 410 if (window == view_->window_) 411 view_->RemovingFromRootWindow(); 412 } 413 414 private: 415 RenderWidgetHostViewAura* view_; 416 417 DISALLOW_COPY_AND_ASSIGN(WindowObserver); 418 }; 419 420 //////////////////////////////////////////////////////////////////////////////// 421 // RenderWidgetHostViewAura, public: 422 423 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host) 424 : host_(RenderWidgetHostImpl::From(host)), 425 window_(new aura::Window(this)), 426 delegated_frame_host_(new DelegatedFrameHost(this)), 427 in_shutdown_(false), 428 in_bounds_changed_(false), 429 is_fullscreen_(false), 430 popup_parent_host_view_(NULL), 431 popup_child_host_view_(NULL), 432 is_loading_(false), 433 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), 434 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), 435 can_compose_inline_(true), 436 has_composition_text_(false), 437 accept_return_character_(false), 438 last_swapped_software_frame_scale_factor_(1.f), 439 paint_canvas_(NULL), 440 synthetic_move_sent_(false), 441 cursor_visibility_state_in_renderer_(UNKNOWN), 442 touch_editing_client_(NULL), 443 weak_ptr_factory_(this) { 444 host_->SetView(this); 445 window_observer_.reset(new WindowObserver(this)); 446 aura::client::SetTooltipText(window_, &tooltip_); 447 aura::client::SetActivationDelegate(window_, this); 448 aura::client::SetActivationChangeObserver(window_, this); 449 aura::client::SetFocusChangeObserver(window_, this); 450 window_->set_layer_owner_delegate(delegated_frame_host_.get()); 451 gfx::Screen::GetScreenFor(window_)->AddObserver(this); 452 453 bool overscroll_enabled = CommandLine::ForCurrentProcess()-> 454 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0"; 455 SetOverscrollControllerEnabled(overscroll_enabled); 456 } 457 458 //////////////////////////////////////////////////////////////////////////////// 459 // RenderWidgetHostViewAura, RenderWidgetHostView implementation: 460 461 void RenderWidgetHostViewAura::InitAsChild( 462 gfx::NativeView parent_view) { 463 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL); 464 window_->Init(aura::WINDOW_LAYER_TEXTURED); 465 window_->SetName("RenderWidgetHostViewAura"); 466 } 467 468 void RenderWidgetHostViewAura::InitAsPopup( 469 RenderWidgetHostView* parent_host_view, 470 const gfx::Rect& bounds_in_screen) { 471 popup_parent_host_view_ = 472 static_cast<RenderWidgetHostViewAura*>(parent_host_view); 473 474 // TransientWindowClient may be NULL during tests. 475 aura::client::TransientWindowClient* transient_window_client = 476 aura::client::GetTransientWindowClient(); 477 RenderWidgetHostViewAura* old_child = 478 popup_parent_host_view_->popup_child_host_view_; 479 if (old_child) { 480 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or 481 // similar mechanism to ensure a second popup doesn't cause the first one 482 // to never get a chance to filter events. See crbug.com/160589. 483 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_); 484 if (transient_window_client) { 485 transient_window_client->RemoveTransientChild( 486 popup_parent_host_view_->window_, old_child->window_); 487 } 488 old_child->popup_parent_host_view_ = NULL; 489 } 490 popup_parent_host_view_->popup_child_host_view_ = this; 491 window_->SetType(ui::wm::WINDOW_TYPE_MENU); 492 window_->Init(aura::WINDOW_LAYER_TEXTURED); 493 window_->SetName("RenderWidgetHostViewAura"); 494 495 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow(); 496 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen); 497 // Setting the transient child allows for the popup to get mouse events when 498 // in a system modal dialog. 499 // This fixes crbug.com/328593. 500 if (transient_window_client) { 501 transient_window_client->AddTransientChild( 502 popup_parent_host_view_->window_, window_); 503 } 504 505 SetBounds(bounds_in_screen); 506 Show(); 507 #if !defined(OS_WIN) && !defined(OS_CHROMEOS) 508 if (NeedsInputGrab()) 509 window_->SetCapture(); 510 #endif 511 512 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this)); 513 } 514 515 void RenderWidgetHostViewAura::InitAsFullscreen( 516 RenderWidgetHostView* reference_host_view) { 517 is_fullscreen_ = true; 518 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL); 519 window_->Init(aura::WINDOW_LAYER_TEXTURED); 520 window_->SetName("RenderWidgetHostViewAura"); 521 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 522 523 aura::Window* parent = NULL; 524 gfx::Rect bounds; 525 if (reference_host_view) { 526 aura::Window* reference_window = 527 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_; 528 if (reference_window) { 529 host_tracker_.reset(new aura::WindowTracker); 530 host_tracker_->Add(reference_window); 531 } 532 gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 533 GetDisplayNearestWindow(reference_window); 534 parent = reference_window->GetRootWindow(); 535 bounds = display.bounds(); 536 } 537 aura::client::ParentWindowWithContext(window_, parent, bounds); 538 Show(); 539 Focus(); 540 } 541 542 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const { 543 return host_; 544 } 545 546 void RenderWidgetHostViewAura::WasShown() { 547 DCHECK(host_); 548 if (!host_->is_hidden()) 549 return; 550 host_->WasShown(); 551 552 aura::Window* root = window_->GetRootWindow(); 553 if (root) { 554 aura::client::CursorClient* cursor_client = 555 aura::client::GetCursorClient(root); 556 if (cursor_client) 557 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible()); 558 } 559 560 delegated_frame_host_->WasShown(); 561 562 #if defined(OS_WIN) 563 if (legacy_render_widget_host_HWND_) { 564 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent 565 // window before reparenting any plugins. This ensures that the plugin 566 // windows stay on top of the child Zorder in the parent and receive 567 // mouse events, etc. 568 legacy_render_widget_host_HWND_->UpdateParent( 569 GetNativeView()->GetHost()->GetAcceleratedWidget()); 570 legacy_render_widget_host_HWND_->SetBounds( 571 window_->GetBoundsInRootWindow()); 572 } 573 LPARAM lparam = reinterpret_cast<LPARAM>(this); 574 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam); 575 #endif 576 } 577 578 void RenderWidgetHostViewAura::WasHidden() { 579 if (!host_ || host_->is_hidden()) 580 return; 581 host_->WasHidden(); 582 delegated_frame_host_->WasHidden(); 583 584 #if defined(OS_WIN) 585 constrained_rects_.clear(); 586 aura::WindowTreeHost* host = window_->GetHost(); 587 if (host) { 588 HWND parent = host->GetAcceleratedWidget(); 589 LPARAM lparam = reinterpret_cast<LPARAM>(this); 590 EnumChildWindows(parent, HideWindowsCallback, lparam); 591 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global 592 // hidden window on the same lines as Windowed plugin windows. 593 if (legacy_render_widget_host_HWND_) 594 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow()); 595 } 596 #endif 597 } 598 599 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) { 600 // For a SetSize operation, we don't care what coordinate system the origin 601 // of the window is in, it's only important to make sure that the origin 602 // remains constant after the operation. 603 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size)); 604 } 605 606 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) { 607 gfx::Point relative_origin(rect.origin()); 608 609 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but 610 // Window::SetBounds() takes parent coordinates, so do the conversion here. 611 aura::Window* root = window_->GetRootWindow(); 612 if (root) { 613 aura::client::ScreenPositionClient* screen_position_client = 614 aura::client::GetScreenPositionClient(root); 615 if (screen_position_client) { 616 screen_position_client->ConvertPointFromScreen( 617 window_->parent(), &relative_origin); 618 } 619 } 620 621 InternalSetBounds(gfx::Rect(relative_origin, rect.size())); 622 } 623 624 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const { 625 return window_; 626 } 627 628 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const { 629 #if defined(OS_WIN) 630 aura::WindowTreeHost* host = window_->GetHost(); 631 if (host) 632 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget()); 633 #endif 634 return static_cast<gfx::NativeViewId>(NULL); 635 } 636 637 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() { 638 #if defined(OS_WIN) 639 aura::WindowTreeHost* host = window_->GetHost(); 640 if (!host) 641 return static_cast<gfx::NativeViewAccessible>(NULL); 642 HWND hwnd = host->GetAcceleratedWidget(); 643 644 CreateBrowserAccessibilityManagerIfNeeded(); 645 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager(); 646 if (manager) 647 return manager->GetRoot()->ToBrowserAccessibilityWin(); 648 #endif 649 650 NOTIMPLEMENTED(); 651 return static_cast<gfx::NativeViewAccessible>(NULL); 652 } 653 654 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() { 655 return this; 656 } 657 658 void RenderWidgetHostViewAura::SetKeyboardFocus() { 659 #if defined(OS_WIN) 660 if (CanFocus()) { 661 aura::WindowTreeHost* host = window_->GetHost(); 662 if (host) 663 ::SetFocus(host->GetAcceleratedWidget()); 664 } 665 #endif 666 } 667 668 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() { 669 if (!host_->IsRenderView()) 670 return NULL; 671 RenderViewHost* rvh = RenderViewHost::From(host_); 672 FrameTreeNode* focused_frame = 673 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame(); 674 if (!focused_frame) 675 return NULL; 676 677 return focused_frame->current_frame_host(); 678 } 679 680 void RenderWidgetHostViewAura::MovePluginWindows( 681 const std::vector<WebPluginGeometry>& plugin_window_moves) { 682 #if defined(OS_WIN) 683 // We need to clip the rectangle to the tab's viewport, otherwise we will draw 684 // over the browser UI. 685 if (!window_->GetRootWindow()) { 686 DCHECK(plugin_window_moves.empty()); 687 return; 688 } 689 HWND parent = window_->GetHost()->GetAcceleratedWidget(); 690 gfx::Rect view_bounds = window_->GetBoundsInRootWindow(); 691 std::vector<WebPluginGeometry> moves = plugin_window_moves; 692 693 gfx::Rect view_port(view_bounds.size()); 694 695 for (size_t i = 0; i < moves.size(); ++i) { 696 gfx::Rect clip(moves[i].clip_rect); 697 gfx::Vector2d view_port_offset( 698 moves[i].window_rect.OffsetFromOrigin()); 699 clip.Offset(view_port_offset); 700 clip.Intersect(view_port); 701 clip.Offset(-view_port_offset); 702 moves[i].clip_rect = clip; 703 704 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin()); 705 706 plugin_window_moves_[moves[i].window] = moves[i]; 707 708 // constrained_rects_ are relative to the root window. We want to convert 709 // them to be relative to the plugin window. 710 for (size_t j = 0; j < constrained_rects_.size(); ++j) { 711 gfx::Rect offset_cutout = constrained_rects_[j]; 712 offset_cutout -= moves[i].window_rect.OffsetFromOrigin(); 713 moves[i].cutout_rects.push_back(offset_cutout); 714 } 715 } 716 717 MovePluginWindowsHelper(parent, moves); 718 719 // Make sure each plugin window (or its wrapper if it exists) has a pointer to 720 // |this|. 721 for (size_t i = 0; i < moves.size(); ++i) { 722 HWND window = moves[i].window; 723 if (GetParent(window) != parent) { 724 window = GetParent(window); 725 } 726 if (!GetProp(window, kWidgetOwnerProperty)) 727 SetProp(window, kWidgetOwnerProperty, this); 728 } 729 #endif // defined(OS_WIN) 730 } 731 732 void RenderWidgetHostViewAura::Focus() { 733 // Make sure we have a FocusClient before attempting to Focus(). In some 734 // situations we may not yet be in a valid Window hierarchy (such as reloading 735 // after out of memory discarded the tab). 736 aura::client::FocusClient* client = aura::client::GetFocusClient(window_); 737 if (client) 738 window_->Focus(); 739 } 740 741 void RenderWidgetHostViewAura::Blur() { 742 window_->Blur(); 743 } 744 745 bool RenderWidgetHostViewAura::HasFocus() const { 746 return window_->HasFocus(); 747 } 748 749 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const { 750 return delegated_frame_host_->CanCopyToBitmap(); 751 } 752 753 void RenderWidgetHostViewAura::Show() { 754 window_->Show(); 755 WasShown(); 756 #if defined(OS_WIN) 757 if (legacy_render_widget_host_HWND_) 758 legacy_render_widget_host_HWND_->Show(); 759 #endif 760 } 761 762 void RenderWidgetHostViewAura::Hide() { 763 window_->Hide(); 764 WasHidden(); 765 #if defined(OS_WIN) 766 if (legacy_render_widget_host_HWND_) 767 legacy_render_widget_host_HWND_->Hide(); 768 #endif 769 } 770 771 bool RenderWidgetHostViewAura::IsShowing() { 772 return window_->IsVisible(); 773 } 774 775 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const { 776 return window_->GetBoundsInScreen(); 777 } 778 779 void RenderWidgetHostViewAura::SetBackgroundOpaque(bool opaque) { 780 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque); 781 host_->SetBackgroundOpaque(opaque); 782 window_->layer()->SetFillsBoundsOpaquely(opaque); 783 } 784 785 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const { 786 gfx::Rect requested_rect(GetRequestedRendererSize()); 787 requested_rect.Inset(insets_); 788 return requested_rect.size(); 789 } 790 791 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) { 792 if (insets != insets_) { 793 insets_ = insets; 794 host_->WasResized(); 795 } 796 } 797 798 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) { 799 current_cursor_ = cursor; 800 const gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 801 GetDisplayNearestWindow(window_); 802 current_cursor_.SetDisplayInfo(display); 803 UpdateCursorIfOverSelf(); 804 } 805 806 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) { 807 is_loading_ = is_loading; 808 UpdateCursorIfOverSelf(); 809 } 810 811 void RenderWidgetHostViewAura::TextInputStateChanged( 812 const ViewHostMsg_TextInputState_Params& params) { 813 if (text_input_type_ != params.type || 814 text_input_mode_ != params.mode || 815 can_compose_inline_ != params.can_compose_inline) { 816 text_input_type_ = params.type; 817 text_input_mode_ = params.mode; 818 can_compose_inline_ = params.can_compose_inline; 819 if (GetInputMethod()) 820 GetInputMethod()->OnTextInputTypeChanged(this); 821 if (touch_editing_client_) 822 touch_editing_client_->OnTextInputTypeChanged(text_input_type_); 823 } 824 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) { 825 if (GetInputMethod()) 826 GetInputMethod()->ShowImeIfNeeded(); 827 } 828 } 829 830 void RenderWidgetHostViewAura::ImeCancelComposition() { 831 if (GetInputMethod()) 832 GetInputMethod()->CancelComposition(this); 833 has_composition_text_ = false; 834 } 835 836 void RenderWidgetHostViewAura::ImeCompositionRangeChanged( 837 const gfx::Range& range, 838 const std::vector<gfx::Rect>& character_bounds) { 839 composition_character_bounds_ = character_bounds; 840 } 841 842 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status, 843 int error_code) { 844 UpdateCursorIfOverSelf(); 845 Destroy(); 846 } 847 848 void RenderWidgetHostViewAura::Destroy() { 849 // Beware, this function is not called on all destruction paths. It will 850 // implicitly end up calling ~RenderWidgetHostViewAura though, so all 851 // destruction/cleanup code should happen there, not here. 852 in_shutdown_ = true; 853 delete window_; 854 } 855 856 void RenderWidgetHostViewAura::SetTooltipText( 857 const base::string16& tooltip_text) { 858 tooltip_ = tooltip_text; 859 aura::Window* root_window = window_->GetRootWindow(); 860 aura::client::TooltipClient* tooltip_client = 861 aura::client::GetTooltipClient(root_window); 862 if (tooltip_client) { 863 tooltip_client->UpdateTooltip(window_); 864 // Content tooltips should be visible indefinitely. 865 tooltip_client->SetTooltipShownTimeout(window_, 0); 866 } 867 } 868 869 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text, 870 size_t offset, 871 const gfx::Range& range) { 872 RenderWidgetHostViewBase::SelectionChanged(text, offset, range); 873 874 #if defined(USE_X11) && !defined(OS_CHROMEOS) 875 if (text.empty() || range.is_empty()) 876 return; 877 size_t pos = range.GetMin() - offset; 878 size_t n = range.length(); 879 880 DCHECK(pos + n <= text.length()) << "The text can not fully cover range."; 881 if (pos >= text.length()) { 882 NOTREACHED() << "The text can not cover range."; 883 return; 884 } 885 886 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. 887 ui::ScopedClipboardWriter clipboard_writer( 888 ui::Clipboard::GetForCurrentThread(), 889 ui::CLIPBOARD_TYPE_SELECTION); 890 clipboard_writer.WriteText(text.substr(pos, n)); 891 #endif // defined(USE_X11) && !defined(OS_CHROMEOS) 892 } 893 894 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const { 895 return delegated_frame_host_->GetRequestedRendererSize(); 896 } 897 898 void RenderWidgetHostViewAura::SelectionBoundsChanged( 899 const ViewHostMsg_SelectionBounds_Params& params) { 900 if (selection_anchor_rect_ == params.anchor_rect && 901 selection_focus_rect_ == params.focus_rect) 902 return; 903 904 selection_anchor_rect_ = params.anchor_rect; 905 selection_focus_rect_ = params.focus_rect; 906 907 if (GetInputMethod()) 908 GetInputMethod()->OnCaretBoundsChanged(this); 909 910 if (touch_editing_client_) { 911 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_, 912 selection_focus_rect_); 913 } 914 } 915 916 void RenderWidgetHostViewAura::ScrollOffsetChanged() { 917 aura::Window* root = window_->GetRootWindow(); 918 if (!root) 919 return; 920 aura::client::CursorClient* cursor_client = 921 aura::client::GetCursorClient(root); 922 if (cursor_client && !cursor_client->IsCursorVisible()) 923 cursor_client->DisableMouseEvents(); 924 } 925 926 void RenderWidgetHostViewAura::CopyFromCompositingSurface( 927 const gfx::Rect& src_subrect, 928 const gfx::Size& dst_size, 929 const base::Callback<void(bool, const SkBitmap&)>& callback, 930 const SkBitmap::Config config) { 931 delegated_frame_host_->CopyFromCompositingSurface( 932 src_subrect, dst_size, callback, config); 933 } 934 935 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame( 936 const gfx::Rect& src_subrect, 937 const scoped_refptr<media::VideoFrame>& target, 938 const base::Callback<void(bool)>& callback) { 939 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame( 940 src_subrect, target, callback); 941 } 942 943 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const { 944 return delegated_frame_host_->CanCopyToVideoFrame(); 945 } 946 947 bool RenderWidgetHostViewAura::CanSubscribeFrame() const { 948 return delegated_frame_host_->CanSubscribeFrame(); 949 } 950 951 void RenderWidgetHostViewAura::BeginFrameSubscription( 952 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) { 953 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass()); 954 } 955 956 void RenderWidgetHostViewAura::EndFrameSubscription() { 957 delegated_frame_host_->EndFrameSubscription(); 958 } 959 960 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id, 961 int route_id) { 962 } 963 964 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() { 965 // The top left corner of our view in window coordinates might not land on a 966 // device pixel boundary if we have a non-integer device scale. In that case, 967 // to avoid the web contents area looking blurry we translate the web contents 968 // in the +x, +y direction to land on the nearest pixel boundary. This may 969 // cause the bottom and right edges to be clipped slightly, but that's ok. 970 gfx::Point view_offset_dips = window_->GetBoundsInRootWindow().origin(); 971 gfx::PointF view_offset = view_offset_dips; 972 view_offset.Scale(current_device_scale_factor_); 973 gfx::PointF view_offset_snapped(std::ceil(view_offset.x()), 974 std::ceil(view_offset.y())); 975 976 gfx::Vector2dF fudge = view_offset_snapped - view_offset; 977 fudge.Scale(1.0 / current_device_scale_factor_); 978 GetLayer()->SetSubpixelPositionOffset(fudge); 979 } 980 981 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) { 982 if (HasDisplayPropertyChanged(window_)) 983 host_->InvalidateScreenInfo(); 984 985 SnapToPhysicalPixelBoundary(); 986 // Don't recursively call SetBounds if this bounds update is the result of 987 // a Window::SetBoundsInternal call. 988 if (!in_bounds_changed_) 989 window_->SetBounds(rect); 990 host_->WasResized(); 991 delegated_frame_host_->WasResized(); 992 if (touch_editing_client_) { 993 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_, 994 selection_focus_rect_); 995 } 996 #if defined(OS_WIN) 997 // Create the legacy dummy window which corresponds to the bounds of the 998 // webcontents. This will be passed as the container window for windowless 999 // plugins. 1000 // Plugins like Flash assume the container window which is returned via the 1001 // NPNVnetscapeWindow property corresponds to the bounds of the webpage. 1002 // This is not true in Aura where we have only HWND which is the main Aura 1003 // window. If we return this window to plugins like Flash then it causes the 1004 // coordinate translations done by these plugins to break. 1005 // Additonally the legacy dummy window is needed for accessibility and for 1006 // scrolling to work in legacy drivers for trackpoints/trackpads, etc. 1007 if (GetNativeViewId()) { 1008 if (!legacy_render_widget_host_HWND_) { 1009 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create( 1010 reinterpret_cast<HWND>(GetNativeViewId())); 1011 BrowserAccessibilityManagerWin* manager = 1012 static_cast<BrowserAccessibilityManagerWin*>( 1013 GetBrowserAccessibilityManager()); 1014 if (manager) 1015 manager->SetAccessibleHWND(legacy_render_widget_host_HWND_.get()); 1016 } 1017 if (legacy_render_widget_host_HWND_) { 1018 legacy_render_widget_host_HWND_->SetBounds( 1019 window_->GetBoundsInRootWindow()); 1020 } 1021 } 1022 1023 if (mouse_locked_) 1024 UpdateMouseLockRegion(); 1025 #endif 1026 } 1027 1028 #if defined(OS_WIN) 1029 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const { 1030 return (legacy_render_widget_host_HWND_ != NULL); 1031 } 1032 1033 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects( 1034 const std::vector<gfx::Rect>& rects) { 1035 // Check this before setting constrained_rects_, so that next time they're set 1036 // and we have a root window we don't early return. 1037 if (!window_->GetHost()) 1038 return; 1039 1040 if (rects == constrained_rects_) 1041 return; 1042 1043 constrained_rects_ = rects; 1044 1045 HWND parent = window_->GetHost()->GetAcceleratedWidget(); 1046 CutoutRectsParams params; 1047 params.widget = this; 1048 params.cutout_rects = constrained_rects_; 1049 params.geometry = &plugin_window_moves_; 1050 LPARAM lparam = reinterpret_cast<LPARAM>(¶ms); 1051 EnumChildWindows(parent, SetCutoutRectsCallback, lparam); 1052 } 1053 1054 void RenderWidgetHostViewAura::UpdateMouseLockRegion() { 1055 // Clip the cursor if chrome is running on regular desktop. 1056 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) { 1057 RECT window_rect = window_->GetBoundsInScreen().ToRECT(); 1058 ::ClipCursor(&window_rect); 1059 } 1060 } 1061 #endif 1062 1063 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped( 1064 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel, 1065 int gpu_host_id) { 1066 // Oldschool composited mode is no longer supported. 1067 } 1068 1069 void RenderWidgetHostViewAura::OnSwapCompositorFrame( 1070 uint32 output_surface_id, 1071 scoped_ptr<cc::CompositorFrame> frame) { 1072 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame"); 1073 if (frame->delegated_frame_data) { 1074 delegated_frame_host_->SwapDelegatedFrame( 1075 output_surface_id, 1076 frame->delegated_frame_data.Pass(), 1077 frame->metadata.device_scale_factor, 1078 frame->metadata.latency_info); 1079 return; 1080 } 1081 1082 if (frame->software_frame_data) { 1083 DLOG(ERROR) << "Unable to use software frame in aura"; 1084 RecordAction( 1085 base::UserMetricsAction("BadMessageTerminate_SharedMemoryAura")); 1086 host_->GetProcess()->ReceivedBadMessage(); 1087 return; 1088 } 1089 } 1090 1091 #if defined(OS_WIN) 1092 void RenderWidgetHostViewAura::SetParentNativeViewAccessible( 1093 gfx::NativeViewAccessible accessible_parent) { 1094 if (GetBrowserAccessibilityManager()) { 1095 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin() 1096 ->set_parent_iaccessible(accessible_parent); 1097 } 1098 } 1099 1100 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin() 1101 const { 1102 if (legacy_render_widget_host_HWND_) { 1103 return reinterpret_cast<gfx::NativeViewId>( 1104 legacy_render_widget_host_HWND_->hwnd()); 1105 } 1106 return NULL; 1107 } 1108 #endif 1109 1110 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer( 1111 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel, 1112 int gpu_host_id) { 1113 // Oldschool composited mode is no longer supported. 1114 } 1115 1116 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() { 1117 } 1118 1119 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() { 1120 } 1121 1122 bool RenderWidgetHostViewAura::HasAcceleratedSurface( 1123 const gfx::Size& desired_size) { 1124 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't 1125 // matter what is returned here as GetBackingStore is the only caller of this 1126 // method. TODO(jbates) implement this if other Aura code needs it. 1127 return false; 1128 } 1129 1130 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) { 1131 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL); 1132 } 1133 1134 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() { 1135 aura::Window* top_level = window_->GetToplevelWindow(); 1136 gfx::Rect bounds(top_level->GetBoundsInScreen()); 1137 1138 #if defined(OS_WIN) 1139 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and 1140 // remove the legacy hwnd, so a better fix will need to be decided when that 1141 // happens. 1142 if (UsesNativeWindowFrame()) { 1143 // aura::Window doesn't take into account non-client area of native windows 1144 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are. 1145 aura::WindowTreeHost* host = top_level->GetHost(); 1146 if (!host) 1147 return top_level->GetBoundsInScreen(); 1148 RECT window_rect = {0}; 1149 HWND hwnd = host->GetAcceleratedWidget(); 1150 ::GetWindowRect(hwnd, &window_rect); 1151 bounds = gfx::Rect(window_rect); 1152 1153 // Maximized windows are outdented from the work area by the frame thickness 1154 // even though this "frame" is not painted. This confuses code (and people) 1155 // that think of a maximized window as corresponding exactly to the work 1156 // area. Correct for this by subtracting the frame thickness back off. 1157 if (::IsZoomed(hwnd)) { 1158 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME), 1159 GetSystemMetrics(SM_CYSIZEFRAME)); 1160 1161 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER), 1162 GetSystemMetrics(SM_CXPADDEDBORDER)); 1163 } 1164 } 1165 1166 bounds = gfx::win::ScreenToDIPRect(bounds); 1167 #endif 1168 1169 return bounds; 1170 } 1171 1172 void RenderWidgetHostViewAura::WheelEventAck( 1173 const blink::WebMouseWheelEvent& event, 1174 InputEventAckState ack_result) { 1175 if (overscroll_controller_) { 1176 overscroll_controller_->ReceivedEventACK( 1177 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); 1178 } 1179 } 1180 1181 void RenderWidgetHostViewAura::GestureEventAck( 1182 const blink::WebGestureEvent& event, 1183 InputEventAckState ack_result) { 1184 if (touch_editing_client_) 1185 touch_editing_client_->GestureEventAck(event.type); 1186 1187 if (overscroll_controller_) { 1188 overscroll_controller_->ReceivedEventACK( 1189 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result)); 1190 } 1191 } 1192 1193 void RenderWidgetHostViewAura::ProcessAckedTouchEvent( 1194 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) { 1195 ScopedVector<ui::TouchEvent> events; 1196 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events, 1197 SCREEN_COORDINATES)) 1198 return; 1199 1200 aura::WindowTreeHost* host = window_->GetHost(); 1201 // |host| is NULL during tests. 1202 if (!host) 1203 return; 1204 1205 ui::EventResult result = (ack_result == 1206 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED; 1207 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(), 1208 end = events.end(); iter != end; ++iter) { 1209 host->dispatcher()->ProcessedTouchEvent((*iter), window_, result); 1210 } 1211 } 1212 1213 scoped_ptr<SyntheticGestureTarget> 1214 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() { 1215 return scoped_ptr<SyntheticGestureTarget>( 1216 new SyntheticGestureTargetAura(host_)); 1217 } 1218 1219 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent( 1220 const blink::WebInputEvent& input_event) { 1221 bool consumed = false; 1222 if (input_event.type == WebInputEvent::GestureFlingStart) { 1223 const WebGestureEvent& gesture_event = 1224 static_cast<const WebGestureEvent&>(input_event); 1225 // Zero-velocity touchpad flings are an Aura-specific signal that the 1226 // touchpad scroll has ended, and should not be forwarded to the renderer. 1227 if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad && 1228 !gesture_event.data.flingStart.velocityX && 1229 !gesture_event.data.flingStart.velocityY) { 1230 consumed = true; 1231 } 1232 } 1233 1234 if (overscroll_controller_) 1235 consumed |= overscroll_controller_->WillHandleEvent(input_event); 1236 1237 return consumed && !WebTouchEvent::isTouchEventType(input_event.type) 1238 ? INPUT_EVENT_ACK_STATE_CONSUMED 1239 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 1240 } 1241 1242 void RenderWidgetHostViewAura::CreateBrowserAccessibilityManagerIfNeeded() { 1243 #if defined(OS_WIN) 1244 if (!GetBrowserAccessibilityManager()) { 1245 gfx::NativeViewAccessible accessible_parent = 1246 host_->GetParentNativeViewAccessible(); 1247 LegacyRenderWidgetHostHWND* parent_hwnd = 1248 legacy_render_widget_host_HWND_.get(); 1249 SetBrowserAccessibilityManager(new BrowserAccessibilityManagerWin( 1250 legacy_render_widget_host_HWND_.get(), accessible_parent, 1251 BrowserAccessibilityManagerWin::GetEmptyDocument(), host_)); 1252 } 1253 #else 1254 if (!GetBrowserAccessibilityManager()) { 1255 SetBrowserAccessibilityManager( 1256 BrowserAccessibilityManager::Create( 1257 BrowserAccessibilityManager::GetEmptyDocument(), host_)); 1258 } 1259 #endif 1260 } 1261 1262 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() { 1263 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle(); 1264 } 1265 1266 bool RenderWidgetHostViewAura::LockMouse() { 1267 aura::Window* root_window = window_->GetRootWindow(); 1268 if (!root_window) 1269 return false; 1270 1271 if (mouse_locked_) 1272 return true; 1273 1274 mouse_locked_ = true; 1275 #if !defined(OS_WIN) 1276 window_->SetCapture(); 1277 #else 1278 UpdateMouseLockRegion(); 1279 #endif 1280 aura::client::CursorClient* cursor_client = 1281 aura::client::GetCursorClient(root_window); 1282 if (cursor_client) { 1283 cursor_client->HideCursor(); 1284 cursor_client->LockCursor(); 1285 } 1286 1287 if (ShouldMoveToCenter()) { 1288 synthetic_move_sent_ = true; 1289 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint()); 1290 } 1291 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window)); 1292 return true; 1293 } 1294 1295 void RenderWidgetHostViewAura::UnlockMouse() { 1296 tooltip_disabler_.reset(); 1297 1298 aura::Window* root_window = window_->GetRootWindow(); 1299 if (!mouse_locked_ || !root_window) 1300 return; 1301 1302 mouse_locked_ = false; 1303 1304 #if !defined(OS_WIN) 1305 window_->ReleaseCapture(); 1306 #else 1307 ::ClipCursor(NULL); 1308 #endif 1309 window_->MoveCursorTo(unlocked_mouse_position_); 1310 aura::client::CursorClient* cursor_client = 1311 aura::client::GetCursorClient(root_window); 1312 if (cursor_client) { 1313 cursor_client->UnlockCursor(); 1314 cursor_client->ShowCursor(); 1315 } 1316 1317 host_->LostMouseLock(); 1318 } 1319 1320 //////////////////////////////////////////////////////////////////////////////// 1321 // RenderWidgetHostViewAura, ui::TextInputClient implementation: 1322 void RenderWidgetHostViewAura::SetCompositionText( 1323 const ui::CompositionText& composition) { 1324 if (!host_) 1325 return; 1326 1327 // TODO(suzhe): convert both renderer_host and renderer to use 1328 // ui::CompositionText. 1329 std::vector<blink::WebCompositionUnderline> underlines; 1330 underlines.reserve(composition.underlines.size()); 1331 for (std::vector<ui::CompositionUnderline>::const_iterator it = 1332 composition.underlines.begin(); 1333 it != composition.underlines.end(); ++it) { 1334 underlines.push_back( 1335 blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset), 1336 static_cast<unsigned>(it->end_offset), 1337 it->color, 1338 it->thick, 1339 it->background_color)); 1340 } 1341 1342 // TODO(suzhe): due to a bug of webkit, we can't use selection range with 1343 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788 1344 host_->ImeSetComposition(composition.text, underlines, 1345 composition.selection.end(), 1346 composition.selection.end()); 1347 1348 has_composition_text_ = !composition.text.empty(); 1349 } 1350 1351 void RenderWidgetHostViewAura::ConfirmCompositionText() { 1352 if (host_ && has_composition_text_) { 1353 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), 1354 false); 1355 } 1356 has_composition_text_ = false; 1357 } 1358 1359 void RenderWidgetHostViewAura::ClearCompositionText() { 1360 if (host_ && has_composition_text_) 1361 host_->ImeCancelComposition(); 1362 has_composition_text_ = false; 1363 } 1364 1365 void RenderWidgetHostViewAura::InsertText(const base::string16& text) { 1366 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE); 1367 if (host_) 1368 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false); 1369 has_composition_text_ = false; 1370 } 1371 1372 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) { 1373 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) { 1374 popup_child_host_view_->InsertChar(ch, flags); 1375 return; 1376 } 1377 1378 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547 1379 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) { 1380 double now = ui::EventTimeForNow().InSecondsF(); 1381 // Send a blink::WebInputEvent::Char event to |host_|. 1382 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED, 1383 true /* is_char */, 1384 ch, 1385 flags, 1386 now); 1387 ForwardKeyboardEvent(webkit_event); 1388 } 1389 } 1390 1391 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const { 1392 return window_; 1393 } 1394 1395 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const { 1396 return text_input_type_; 1397 } 1398 1399 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const { 1400 return text_input_mode_; 1401 } 1402 1403 bool RenderWidgetHostViewAura::CanComposeInline() const { 1404 return can_compose_inline_; 1405 } 1406 1407 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen( 1408 const gfx::Rect& rect) const { 1409 gfx::Point origin = rect.origin(); 1410 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); 1411 1412 aura::Window* root_window = window_->GetRootWindow(); 1413 if (!root_window) 1414 return rect; 1415 aura::client::ScreenPositionClient* screen_position_client = 1416 aura::client::GetScreenPositionClient(root_window); 1417 if (!screen_position_client) 1418 return rect; 1419 screen_position_client->ConvertPointToScreen(window_, &origin); 1420 screen_position_client->ConvertPointToScreen(window_, &end); 1421 return gfx::Rect(origin.x(), 1422 origin.y(), 1423 end.x() - origin.x(), 1424 end.y() - origin.y()); 1425 } 1426 1427 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen( 1428 const gfx::Rect& rect) const { 1429 gfx::Point origin = rect.origin(); 1430 gfx::Point end = gfx::Point(rect.right(), rect.bottom()); 1431 1432 aura::Window* root_window = window_->GetRootWindow(); 1433 if (root_window) { 1434 aura::client::ScreenPositionClient* screen_position_client = 1435 aura::client::GetScreenPositionClient(root_window); 1436 screen_position_client->ConvertPointFromScreen(window_, &origin); 1437 screen_position_client->ConvertPointFromScreen(window_, &end); 1438 return gfx::Rect(origin.x(), 1439 origin.y(), 1440 end.x() - origin.x(), 1441 end.y() - origin.y()); 1442 } 1443 1444 return rect; 1445 } 1446 1447 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const { 1448 const gfx::Rect rect = 1449 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_); 1450 return ConvertRectToScreen(rect); 1451 } 1452 1453 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds( 1454 uint32 index, 1455 gfx::Rect* rect) const { 1456 DCHECK(rect); 1457 if (index >= composition_character_bounds_.size()) 1458 return false; 1459 *rect = ConvertRectToScreen(composition_character_bounds_[index]); 1460 return true; 1461 } 1462 1463 bool RenderWidgetHostViewAura::HasCompositionText() const { 1464 return has_composition_text_; 1465 } 1466 1467 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const { 1468 range->set_start(selection_text_offset_); 1469 range->set_end(selection_text_offset_ + selection_text_.length()); 1470 return true; 1471 } 1472 1473 bool RenderWidgetHostViewAura::GetCompositionTextRange( 1474 gfx::Range* range) const { 1475 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 1476 NOTIMPLEMENTED(); 1477 return false; 1478 } 1479 1480 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const { 1481 range->set_start(selection_range_.start()); 1482 range->set_end(selection_range_.end()); 1483 return true; 1484 } 1485 1486 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) { 1487 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 1488 NOTIMPLEMENTED(); 1489 return false; 1490 } 1491 1492 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) { 1493 // TODO(suzhe): implement this method when fixing http://crbug.com/55130. 1494 NOTIMPLEMENTED(); 1495 return false; 1496 } 1497 1498 bool RenderWidgetHostViewAura::GetTextFromRange( 1499 const gfx::Range& range, 1500 base::string16* text) const { 1501 gfx::Range selection_text_range(selection_text_offset_, 1502 selection_text_offset_ + selection_text_.length()); 1503 1504 if (!selection_text_range.Contains(range)) { 1505 text->clear(); 1506 return false; 1507 } 1508 if (selection_text_range.EqualsIgnoringDirection(range)) { 1509 // Avoid calling substr whose performance is low. 1510 *text = selection_text_; 1511 } else { 1512 *text = selection_text_.substr( 1513 range.GetMin() - selection_text_offset_, 1514 range.length()); 1515 } 1516 return true; 1517 } 1518 1519 void RenderWidgetHostViewAura::OnInputMethodChanged() { 1520 if (!host_) 1521 return; 1522 1523 if (GetInputMethod()) 1524 host_->SetInputMethodActive(GetInputMethod()->IsActive()); 1525 1526 // TODO(suzhe): implement the newly added locale property of HTML DOM 1527 // TextEvent. 1528 } 1529 1530 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment( 1531 base::i18n::TextDirection direction) { 1532 if (!host_) 1533 return false; 1534 host_->UpdateTextDirection( 1535 direction == base::i18n::RIGHT_TO_LEFT ? 1536 blink::WebTextDirectionRightToLeft : 1537 blink::WebTextDirectionLeftToRight); 1538 host_->NotifyTextDirection(); 1539 return true; 1540 } 1541 1542 void RenderWidgetHostViewAura::ExtendSelectionAndDelete( 1543 size_t before, size_t after) { 1544 RenderFrameHostImpl* rfh = GetFocusedFrame(); 1545 if (rfh) 1546 rfh->ExtendSelectionAndDelete(before, after); 1547 } 1548 1549 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) { 1550 gfx::Rect intersected_rect( 1551 gfx::IntersectRects(rect, window_->GetBoundsInScreen())); 1552 1553 if (intersected_rect.IsEmpty()) 1554 return; 1555 1556 host_->ScrollFocusedEditableNodeIntoRect( 1557 ConvertRectFromScreen(intersected_rect)); 1558 } 1559 1560 void RenderWidgetHostViewAura::OnCandidateWindowShown() { 1561 host_->CandidateWindowShown(); 1562 } 1563 1564 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() { 1565 host_->CandidateWindowUpdated(); 1566 } 1567 1568 void RenderWidgetHostViewAura::OnCandidateWindowHidden() { 1569 host_->CandidateWindowHidden(); 1570 } 1571 1572 bool RenderWidgetHostViewAura::IsEditingCommandEnabled(int command_id) { 1573 return false; 1574 } 1575 1576 void RenderWidgetHostViewAura::ExecuteEditingCommand(int command_id) { 1577 } 1578 1579 //////////////////////////////////////////////////////////////////////////////// 1580 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation: 1581 1582 void RenderWidgetHostViewAura::OnDisplayAdded( 1583 const gfx::Display& new_display) { 1584 } 1585 1586 void RenderWidgetHostViewAura::OnDisplayRemoved( 1587 const gfx::Display& old_display) { 1588 } 1589 1590 void RenderWidgetHostViewAura::OnDisplayMetricsChanged( 1591 const gfx::Display& display, uint32_t metrics) { 1592 // The screen info should be updated regardless of the metric change. 1593 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_); 1594 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) { 1595 UpdateScreenInfo(window_); 1596 current_cursor_.SetDisplayInfo(display); 1597 UpdateCursorIfOverSelf(); 1598 } 1599 } 1600 1601 //////////////////////////////////////////////////////////////////////////////// 1602 // RenderWidgetHostViewAura, aura::WindowDelegate implementation: 1603 1604 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const { 1605 return gfx::Size(); 1606 } 1607 1608 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const { 1609 return gfx::Size(); 1610 } 1611 1612 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds, 1613 const gfx::Rect& new_bounds) { 1614 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true); 1615 // We care about this whenever RenderWidgetHostViewAura is not owned by a 1616 // WebContentsViewAura since changes to the Window's bounds need to be 1617 // messaged to the renderer. WebContentsViewAura invokes SetSize() or 1618 // SetBounds() itself. No matter how we got here, any redundant calls are 1619 // harmless. 1620 SetSize(new_bounds.size()); 1621 1622 if (GetInputMethod()) 1623 GetInputMethod()->OnCaretBoundsChanged(this); 1624 } 1625 1626 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) { 1627 if (mouse_locked_) 1628 return ui::kCursorNone; 1629 return current_cursor_.GetNativeCursor(); 1630 } 1631 1632 int RenderWidgetHostViewAura::GetNonClientComponent( 1633 const gfx::Point& point) const { 1634 return HTCLIENT; 1635 } 1636 1637 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling( 1638 aura::Window* child, 1639 const gfx::Point& location) { 1640 return true; 1641 } 1642 1643 bool RenderWidgetHostViewAura::CanFocus() { 1644 return popup_type_ == blink::WebPopupTypeNone; 1645 } 1646 1647 void RenderWidgetHostViewAura::OnCaptureLost() { 1648 host_->LostCapture(); 1649 if (touch_editing_client_) 1650 touch_editing_client_->EndTouchEditing(false); 1651 } 1652 1653 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) { 1654 // For non-opaque windows, we don't draw anything, since we depend on the 1655 // canvas coming from the compositor to already be initialized as 1656 // transparent. 1657 if (window_->layer()->fills_bounds_opaquely()) 1658 canvas->DrawColor(SK_ColorWHITE); 1659 } 1660 1661 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged( 1662 float device_scale_factor) { 1663 if (!host_) 1664 return; 1665 1666 UpdateScreenInfo(window_); 1667 1668 const gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 1669 GetDisplayNearestWindow(window_); 1670 DCHECK_EQ(device_scale_factor, display.device_scale_factor()); 1671 current_cursor_.SetDisplayInfo(display); 1672 } 1673 1674 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) { 1675 #if defined(OS_WIN) 1676 HWND parent = NULL; 1677 // If the tab was hidden and it's closed, host_->is_hidden would have been 1678 // reset to false in RenderWidgetHostImpl::RendererExited. 1679 if (!window_->GetRootWindow() || host_->is_hidden()) { 1680 parent = ui::GetHiddenWindow(); 1681 } else { 1682 parent = window_->GetHost()->GetAcceleratedWidget(); 1683 } 1684 LPARAM lparam = reinterpret_cast<LPARAM>(this); 1685 EnumChildWindows(parent, WindowDestroyingCallback, lparam); 1686 #endif 1687 1688 // Make sure that the input method no longer references to this object before 1689 // this object is removed from the root window (i.e. this object loses access 1690 // to the input method). 1691 ui::InputMethod* input_method = GetInputMethod(); 1692 if (input_method) 1693 input_method->DetachTextInputClient(this); 1694 1695 if (overscroll_controller_) 1696 overscroll_controller_->Reset(); 1697 } 1698 1699 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) { 1700 host_->ViewDestroyed(); 1701 delete this; 1702 } 1703 1704 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) { 1705 } 1706 1707 bool RenderWidgetHostViewAura::HasHitTestMask() const { 1708 return false; 1709 } 1710 1711 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const { 1712 } 1713 1714 //////////////////////////////////////////////////////////////////////////////// 1715 // RenderWidgetHostViewAura, ui::EventHandler implementation: 1716 1717 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) { 1718 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent"); 1719 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 1720 return; 1721 1722 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) { 1723 popup_child_host_view_->OnKeyEvent(event); 1724 if (event->handled()) 1725 return; 1726 } 1727 1728 // We need to handle the Escape key for Pepper Flash. 1729 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) { 1730 // Focus the window we were created from. 1731 if (host_tracker_.get() && !host_tracker_->windows().empty()) { 1732 aura::Window* host = *(host_tracker_->windows().begin()); 1733 aura::client::FocusClient* client = aura::client::GetFocusClient(host); 1734 if (client) { 1735 // Calling host->Focus() may delete |this|. We create a local observer 1736 // for that. In that case we exit without further access to any members. 1737 aura::WindowTracker tracker; 1738 aura::Window* window = window_; 1739 tracker.Add(window); 1740 host->Focus(); 1741 if (!tracker.Contains(window)) { 1742 event->SetHandled(); 1743 return; 1744 } 1745 } 1746 } 1747 if (!in_shutdown_) { 1748 in_shutdown_ = true; 1749 host_->Shutdown(); 1750 } 1751 } else { 1752 if (event->key_code() == ui::VKEY_RETURN) { 1753 // Do not forward return key release events if no press event was handled. 1754 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_) 1755 return; 1756 // Accept return key character events between press and release events. 1757 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED; 1758 } 1759 1760 // We don't have to communicate with an input method here. 1761 if (!event->HasNativeEvent()) { 1762 NativeWebKeyboardEvent webkit_event( 1763 event->type(), 1764 event->is_char(), 1765 event->is_char() ? event->GetCharacter() : event->key_code(), 1766 event->flags(), 1767 ui::EventTimeForNow().InSecondsF()); 1768 ForwardKeyboardEvent(webkit_event); 1769 } else { 1770 NativeWebKeyboardEvent webkit_event(event); 1771 ForwardKeyboardEvent(webkit_event); 1772 } 1773 } 1774 event->SetHandled(); 1775 } 1776 1777 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) { 1778 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent"); 1779 1780 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 1781 return; 1782 1783 if (mouse_locked_) { 1784 aura::client::CursorClient* cursor_client = 1785 aura::client::GetCursorClient(window_->GetRootWindow()); 1786 DCHECK(!cursor_client || !cursor_client->IsCursorVisible()); 1787 1788 if (event->type() == ui::ET_MOUSEWHEEL) { 1789 blink::WebMouseWheelEvent mouse_wheel_event = 1790 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event)); 1791 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) 1792 host_->ForwardWheelEvent(mouse_wheel_event); 1793 return; 1794 } 1795 1796 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint()); 1797 1798 // If we receive non client mouse messages while we are in the locked state 1799 // it probably means that the mouse left the borders of our window and 1800 // needs to be moved back to the center. 1801 if (event->flags() & ui::EF_IS_NON_CLIENT) { 1802 synthetic_move_sent_ = true; 1803 window_->MoveCursorTo(center); 1804 return; 1805 } 1806 1807 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event); 1808 1809 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED || 1810 event->type() == ui::ET_MOUSE_DRAGGED) && 1811 mouse_event.x == center.x() && mouse_event.y == center.y(); 1812 1813 ModifyEventMovementAndCoords(&mouse_event); 1814 1815 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_; 1816 if (should_not_forward) { 1817 synthetic_move_sent_ = false; 1818 } else { 1819 // Check if the mouse has reached the border and needs to be centered. 1820 if (ShouldMoveToCenter()) { 1821 synthetic_move_sent_ = true; 1822 window_->MoveCursorTo(center); 1823 } 1824 // Forward event to renderer. 1825 if (CanRendererHandleEvent(event) && 1826 !(event->flags() & ui::EF_FROM_TOUCH)) { 1827 host_->ForwardMouseEvent(mouse_event); 1828 // Ensure that we get keyboard focus on mouse down as a plugin window 1829 // may have grabbed keyboard focus. 1830 if (event->type() == ui::ET_MOUSE_PRESSED) 1831 SetKeyboardFocus(); 1832 } 1833 } 1834 return; 1835 } 1836 1837 // As the overscroll is handled during scroll events from the trackpad, the 1838 // RWHVA window is transformed by the overscroll controller. This transform 1839 // triggers a synthetic mouse-move event to be generated (by the aura 1840 // RootWindow). But this event interferes with the overscroll gesture. So, 1841 // ignore such synthetic mouse-move events if an overscroll gesture is in 1842 // progress. 1843 if (overscroll_controller_ && 1844 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE && 1845 event->flags() & ui::EF_IS_SYNTHESIZED && 1846 (event->type() == ui::ET_MOUSE_ENTERED || 1847 event->type() == ui::ET_MOUSE_EXITED || 1848 event->type() == ui::ET_MOUSE_MOVED)) { 1849 event->StopPropagation(); 1850 return; 1851 } 1852 1853 if (event->type() == ui::ET_MOUSEWHEEL) { 1854 #if defined(OS_WIN) 1855 // We get mouse wheel/scroll messages even if we are not in the foreground. 1856 // So here we check if we have any owned popup windows in the foreground and 1857 // dismiss them. 1858 aura::WindowTreeHost* host = window_->GetHost(); 1859 if (host) { 1860 HWND parent = host->GetAcceleratedWidget(); 1861 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT); 1862 EnumThreadWindows(GetCurrentThreadId(), 1863 DismissOwnedPopups, 1864 reinterpret_cast<LPARAM>(toplevel_hwnd)); 1865 } 1866 #endif 1867 blink::WebMouseWheelEvent mouse_wheel_event = 1868 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event)); 1869 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) 1870 host_->ForwardWheelEvent(mouse_wheel_event); 1871 } else if (CanRendererHandleEvent(event) && 1872 !(event->flags() & ui::EF_FROM_TOUCH)) { 1873 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event); 1874 ModifyEventMovementAndCoords(&mouse_event); 1875 host_->ForwardMouseEvent(mouse_event); 1876 // Ensure that we get keyboard focus on mouse down as a plugin window may 1877 // have grabbed keyboard focus. 1878 if (event->type() == ui::ET_MOUSE_PRESSED) 1879 SetKeyboardFocus(); 1880 } 1881 1882 switch (event->type()) { 1883 case ui::ET_MOUSE_PRESSED: 1884 window_->SetCapture(); 1885 // Confirm existing composition text on mouse click events, to make sure 1886 // the input caret won't be moved with an ongoing composition text. 1887 FinishImeCompositionSession(); 1888 break; 1889 case ui::ET_MOUSE_RELEASED: 1890 window_->ReleaseCapture(); 1891 break; 1892 default: 1893 break; 1894 } 1895 1896 // Needed to propagate mouse event to |window_->parent()->delegate()|, but 1897 // note that it might be something other than a WebContentsViewAura instance. 1898 // TODO(pkotwicz): Find a better way of doing this. 1899 // In fullscreen mode which is typically used by flash, don't forward 1900 // the mouse events to the parent. The renderer and the plugin process 1901 // handle these events. 1902 if (!is_fullscreen_ && window_->parent()->delegate() && 1903 !(event->flags() & ui::EF_FROM_TOUCH)) { 1904 event->ConvertLocationToTarget(window_, window_->parent()); 1905 window_->parent()->delegate()->OnMouseEvent(event); 1906 } 1907 1908 if (!IsXButtonUpEvent(event)) 1909 event->SetHandled(); 1910 } 1911 1912 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) { 1913 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent"); 1914 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 1915 return; 1916 1917 if (event->type() == ui::ET_SCROLL) { 1918 #if !defined(OS_WIN) 1919 // TODO(ananta) 1920 // Investigate if this is true for Windows 8 Metro ASH as well. 1921 if (event->finger_count() != 2) 1922 return; 1923 #endif 1924 blink::WebGestureEvent gesture_event = 1925 MakeWebGestureEventFlingCancel(); 1926 host_->ForwardGestureEvent(gesture_event); 1927 blink::WebMouseWheelEvent mouse_wheel_event = 1928 MakeWebMouseWheelEvent(event); 1929 host_->ForwardWheelEvent(mouse_wheel_event); 1930 RecordAction(base::UserMetricsAction("TrackpadScroll")); 1931 } else if (event->type() == ui::ET_SCROLL_FLING_START || 1932 event->type() == ui::ET_SCROLL_FLING_CANCEL) { 1933 blink::WebGestureEvent gesture_event = 1934 MakeWebGestureEvent(event); 1935 host_->ForwardGestureEvent(gesture_event); 1936 if (event->type() == ui::ET_SCROLL_FLING_START) 1937 RecordAction(base::UserMetricsAction("TrackpadScrollFling")); 1938 } 1939 1940 event->SetHandled(); 1941 } 1942 1943 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) { 1944 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent"); 1945 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 1946 return; 1947 1948 // Update the touch event first. 1949 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event, 1950 &touch_event_); 1951 1952 // Forward the touch event only if a touch point was updated, and there's a 1953 // touch-event handler in the page, and no other touch-event is in the queue. 1954 // It is important to always consume the event if there is a touch-event 1955 // handler in the page, or some touch-event is already in the queue, even if 1956 // no point has been updated, to make sure that this event does not get 1957 // processed by the gesture recognizer before the events in the queue. 1958 if (host_->ShouldForwardTouchEvent()) 1959 event->StopPropagation(); 1960 1961 if (point) { 1962 if (host_->ShouldForwardTouchEvent()) 1963 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency()); 1964 UpdateWebTouchEventAfterDispatch(&touch_event_, point); 1965 } 1966 } 1967 1968 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) { 1969 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent"); 1970 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN || 1971 event->type() == ui::ET_GESTURE_PINCH_UPDATE || 1972 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) { 1973 event->SetHandled(); 1974 return; 1975 } 1976 1977 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event)) 1978 return; 1979 1980 RenderViewHostDelegate* delegate = NULL; 1981 if (host_->IsRenderView()) 1982 delegate = RenderViewHost::From(host_)->GetDelegate(); 1983 1984 if (delegate && event->type() == ui::ET_GESTURE_BEGIN && 1985 event->details().touch_points() == 1) { 1986 delegate->HandleGestureBegin(); 1987 } 1988 1989 blink::WebGestureEvent gesture = MakeWebGestureEvent(event); 1990 if (event->type() == ui::ET_GESTURE_TAP_DOWN) { 1991 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an 1992 // event to stop any in-progress flings. 1993 blink::WebGestureEvent fling_cancel = gesture; 1994 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel; 1995 fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen; 1996 host_->ForwardGestureEvent(fling_cancel); 1997 } 1998 1999 if (gesture.type != blink::WebInputEvent::Undefined) { 2000 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency()); 2001 2002 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || 2003 event->type() == ui::ET_GESTURE_SCROLL_UPDATE || 2004 event->type() == ui::ET_GESTURE_SCROLL_END) { 2005 RecordAction(base::UserMetricsAction("TouchscreenScroll")); 2006 } else if (event->type() == ui::ET_SCROLL_FLING_START) { 2007 RecordAction(base::UserMetricsAction("TouchscreenScrollFling")); 2008 } 2009 } 2010 2011 if (delegate && event->type() == ui::ET_GESTURE_END && 2012 event->details().touch_points() == 1) { 2013 delegate->HandleGestureEnd(); 2014 } 2015 2016 // If a gesture is not processed by the webpage, then WebKit processes it 2017 // (e.g. generates synthetic mouse events). 2018 event->SetHandled(); 2019 } 2020 2021 //////////////////////////////////////////////////////////////////////////////// 2022 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation: 2023 2024 bool RenderWidgetHostViewAura::ShouldActivate() const { 2025 aura::WindowTreeHost* host = window_->GetHost(); 2026 if (!host) 2027 return true; 2028 const ui::Event* event = host->dispatcher()->current_event(); 2029 if (!event) 2030 return true; 2031 return is_fullscreen_; 2032 } 2033 2034 //////////////////////////////////////////////////////////////////////////////// 2035 // RenderWidgetHostViewAura, 2036 // aura::client::ActivationChangeObserver implementation: 2037 2038 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active, 2039 aura::Window* lost_active) { 2040 DCHECK(window_ == gained_active || window_ == lost_active); 2041 if (window_ == gained_active) { 2042 const ui::Event* event = window_->GetHost()->dispatcher()->current_event(); 2043 if (event && PointerEventActivates(*event)) 2044 host_->OnPointerEventActivate(); 2045 } 2046 } 2047 2048 //////////////////////////////////////////////////////////////////////////////// 2049 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation: 2050 2051 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) { 2052 NotifyRendererOfCursorVisibilityState(is_visible); 2053 } 2054 2055 //////////////////////////////////////////////////////////////////////////////// 2056 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation: 2057 2058 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus, 2059 aura::Window* lost_focus) { 2060 DCHECK(window_ == gained_focus || window_ == lost_focus); 2061 if (window_ == gained_focus) { 2062 // We need to honor input bypass if the associated tab is does not want 2063 // input. This gives the current focused window a chance to be the text 2064 // input client and handle events. 2065 if (host_->ignore_input_events()) 2066 return; 2067 2068 host_->GotFocus(); 2069 host_->SetActive(true); 2070 2071 ui::InputMethod* input_method = GetInputMethod(); 2072 if (input_method) { 2073 // Ask the system-wide IME to send all TextInputClient messages to |this| 2074 // object. 2075 input_method->SetFocusedTextInputClient(this); 2076 host_->SetInputMethodActive(input_method->IsActive()); 2077 2078 // Often the application can set focus to the view in response to a key 2079 // down. However the following char event shouldn't be sent to the web 2080 // page. 2081 host_->SuppressNextCharEvents(); 2082 } else { 2083 host_->SetInputMethodActive(false); 2084 } 2085 2086 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager(); 2087 if (manager) 2088 manager->OnWindowFocused(); 2089 } else if (window_ == lost_focus) { 2090 host_->SetActive(false); 2091 host_->Blur(); 2092 2093 DetachFromInputMethod(); 2094 host_->SetInputMethodActive(false); 2095 2096 if (touch_editing_client_) 2097 touch_editing_client_->EndTouchEditing(false); 2098 2099 if (overscroll_controller_) 2100 overscroll_controller_->Cancel(); 2101 2102 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager(); 2103 if (manager) 2104 manager->OnWindowBlurred(); 2105 2106 // If we lose the focus while fullscreen, close the window; Pepper Flash 2107 // won't do it for us (unlike NPAPI Flash). However, we do not close the 2108 // window if we lose the focus to a window on another display. 2109 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_); 2110 bool focusing_other_display = 2111 gained_focus && screen->GetNumDisplays() > 1 && 2112 (screen->GetDisplayNearestWindow(window_).id() != 2113 screen->GetDisplayNearestWindow(gained_focus).id()); 2114 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) { 2115 #if defined(OS_WIN) 2116 // On Windows, if we are switching to a non Aura Window on a different 2117 // screen we should not close the fullscreen window. 2118 if (!gained_focus) { 2119 POINT point = {0}; 2120 ::GetCursorPos(&point); 2121 if (screen->GetDisplayNearestWindow(window_).id() != 2122 screen->GetDisplayNearestPoint(gfx::Point(point)).id()) 2123 return; 2124 } 2125 #endif 2126 in_shutdown_ = true; 2127 host_->Shutdown(); 2128 } 2129 } 2130 } 2131 2132 //////////////////////////////////////////////////////////////////////////////// 2133 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation: 2134 2135 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host, 2136 const gfx::Point& new_origin) { 2137 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved", 2138 "new_origin", new_origin.ToString()); 2139 2140 UpdateScreenInfo(window_); 2141 } 2142 2143 //////////////////////////////////////////////////////////////////////////////// 2144 // RenderWidgetHostViewAura, private: 2145 2146 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() { 2147 if (touch_editing_client_) 2148 touch_editing_client_->OnViewDestroyed(); 2149 2150 delegated_frame_host_.reset(); 2151 window_observer_.reset(); 2152 if (window_->GetHost()) 2153 window_->GetHost()->RemoveObserver(this); 2154 UnlockMouse(); 2155 if (popup_parent_host_view_) { 2156 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL || 2157 popup_parent_host_view_->popup_child_host_view_ == this); 2158 popup_parent_host_view_->popup_child_host_view_ = NULL; 2159 } 2160 if (popup_child_host_view_) { 2161 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL || 2162 popup_child_host_view_->popup_parent_host_view_ == this); 2163 popup_child_host_view_->popup_parent_host_view_ = NULL; 2164 } 2165 event_filter_for_popup_exit_.reset(); 2166 aura::client::SetTooltipText(window_, NULL); 2167 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this); 2168 2169 // This call is usually no-op since |this| object is already removed from the 2170 // Aura root window and we don't have a way to get an input method object 2171 // associated with the window, but just in case. 2172 DetachFromInputMethod(); 2173 2174 #if defined(OS_WIN) 2175 legacy_render_widget_host_HWND_.reset(NULL); 2176 #endif 2177 } 2178 2179 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() { 2180 const gfx::Point screen_point = 2181 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(); 2182 aura::Window* root_window = window_->GetRootWindow(); 2183 if (!root_window) 2184 return; 2185 2186 gfx::Point root_window_point = screen_point; 2187 aura::client::ScreenPositionClient* screen_position_client = 2188 aura::client::GetScreenPositionClient(root_window); 2189 if (screen_position_client) { 2190 screen_position_client->ConvertPointFromScreen( 2191 root_window, &root_window_point); 2192 } 2193 2194 if (root_window->GetEventHandlerForPoint(root_window_point) != window_) 2195 return; 2196 2197 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor(); 2198 // Do not show loading cursor when the cursor is currently hidden. 2199 if (is_loading_ && cursor != ui::kCursorNone) 2200 cursor = ui::kCursorPointer; 2201 2202 aura::client::CursorClient* cursor_client = 2203 aura::client::GetCursorClient(root_window); 2204 if (cursor_client) { 2205 cursor_client->SetCursor(cursor); 2206 } 2207 } 2208 2209 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const { 2210 aura::Window* root_window = window_->GetRootWindow(); 2211 if (!root_window) 2212 return NULL; 2213 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey); 2214 } 2215 2216 bool RenderWidgetHostViewAura::NeedsInputGrab() { 2217 return popup_type_ == blink::WebPopupTypeSelect; 2218 } 2219 2220 void RenderWidgetHostViewAura::FinishImeCompositionSession() { 2221 if (!has_composition_text_) 2222 return; 2223 if (host_) { 2224 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(), 2225 false); 2226 } 2227 ImeCancelComposition(); 2228 } 2229 2230 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords( 2231 blink::WebMouseEvent* event) { 2232 // If the mouse has just entered, we must report zero movementX/Y. Hence we 2233 // reset any global_mouse_position set previously. 2234 if (event->type == blink::WebInputEvent::MouseEnter || 2235 event->type == blink::WebInputEvent::MouseLeave) 2236 global_mouse_position_.SetPoint(event->globalX, event->globalY); 2237 2238 // Movement is computed by taking the difference of the new cursor position 2239 // and the previous. Under mouse lock the cursor will be warped back to the 2240 // center so that we are not limited by clipping boundaries. 2241 // We do not measure movement as the delta from cursor to center because 2242 // we may receive more mouse movement events before our warp has taken 2243 // effect. 2244 event->movementX = event->globalX - global_mouse_position_.x(); 2245 event->movementY = event->globalY - global_mouse_position_.y(); 2246 2247 global_mouse_position_.SetPoint(event->globalX, event->globalY); 2248 2249 // Under mouse lock, coordinates of mouse are locked to what they were when 2250 // mouse lock was entered. 2251 if (mouse_locked_) { 2252 event->x = unlocked_mouse_position_.x(); 2253 event->y = unlocked_mouse_position_.y(); 2254 event->windowX = unlocked_mouse_position_.x(); 2255 event->windowY = unlocked_mouse_position_.y(); 2256 event->globalX = unlocked_global_mouse_position_.x(); 2257 event->globalY = unlocked_global_mouse_position_.y(); 2258 } else { 2259 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY); 2260 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY); 2261 } 2262 } 2263 2264 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState( 2265 bool is_visible) { 2266 if (host_->is_hidden() || 2267 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) || 2268 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible)) 2269 return; 2270 2271 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE; 2272 host_->SendCursorVisibilityState(is_visible); 2273 } 2274 2275 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) { 2276 if (!enabled) 2277 overscroll_controller_.reset(); 2278 else if (!overscroll_controller_) 2279 overscroll_controller_.reset(new OverscrollController()); 2280 } 2281 2282 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip( 2283 const gfx::Rect& rect, 2284 const gfx::Rect& clip) { 2285 if (!clip.IsEmpty()) { 2286 gfx::Rect to_paint = gfx::SubtractRects(rect, clip); 2287 if (!to_paint.IsEmpty()) 2288 window_->SchedulePaintInRect(to_paint); 2289 } else { 2290 window_->SchedulePaintInRect(rect); 2291 } 2292 } 2293 2294 bool RenderWidgetHostViewAura::ShouldMoveToCenter() { 2295 gfx::Rect rect = window_->bounds(); 2296 rect = ConvertRectToScreen(rect); 2297 int border_x = rect.width() * kMouseLockBorderPercentage / 100; 2298 int border_y = rect.height() * kMouseLockBorderPercentage / 100; 2299 2300 return global_mouse_position_.x() < rect.x() + border_x || 2301 global_mouse_position_.x() > rect.right() - border_x || 2302 global_mouse_position_.y() < rect.y() + border_y || 2303 global_mouse_position_.y() > rect.bottom() - border_y; 2304 } 2305 2306 void RenderWidgetHostViewAura::AddedToRootWindow() { 2307 window_->GetHost()->AddObserver(this); 2308 UpdateScreenInfo(window_); 2309 2310 aura::client::CursorClient* cursor_client = 2311 aura::client::GetCursorClient(window_->GetRootWindow()); 2312 if (cursor_client) { 2313 cursor_client->AddObserver(this); 2314 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible()); 2315 } 2316 if (HasFocus()) { 2317 ui::InputMethod* input_method = GetInputMethod(); 2318 if (input_method) 2319 input_method->SetFocusedTextInputClient(this); 2320 } 2321 2322 #if defined(OS_WIN) 2323 // The parent may have changed here. Ensure that the legacy window is 2324 // reparented accordingly. 2325 if (legacy_render_widget_host_HWND_) 2326 legacy_render_widget_host_HWND_->UpdateParent( 2327 reinterpret_cast<HWND>(GetNativeViewId())); 2328 #endif 2329 2330 delegated_frame_host_->AddedToWindow(); 2331 } 2332 2333 void RenderWidgetHostViewAura::RemovingFromRootWindow() { 2334 aura::client::CursorClient* cursor_client = 2335 aura::client::GetCursorClient(window_->GetRootWindow()); 2336 if (cursor_client) 2337 cursor_client->RemoveObserver(this); 2338 2339 DetachFromInputMethod(); 2340 2341 window_->GetHost()->RemoveObserver(this); 2342 delegated_frame_host_->RemovingFromWindow(); 2343 2344 #if defined(OS_WIN) 2345 // Update the legacy window's parent temporarily to the desktop window. It 2346 // will eventually get reparented to the right root. 2347 if (legacy_render_widget_host_HWND_) 2348 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow()); 2349 #endif 2350 } 2351 2352 void RenderWidgetHostViewAura::DetachFromInputMethod() { 2353 ui::InputMethod* input_method = GetInputMethod(); 2354 if (input_method && input_method->GetTextInputClient() == this) 2355 input_method->SetFocusedTextInputClient(NULL); 2356 } 2357 2358 void RenderWidgetHostViewAura::ForwardKeyboardEvent( 2359 const NativeWebKeyboardEvent& event) { 2360 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 2361 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate = 2362 ui::GetTextEditKeyBindingsDelegate(); 2363 std::vector<ui::TextEditCommandAuraLinux> commands; 2364 if (!event.skip_in_browser && 2365 keybinding_delegate && 2366 event.os_event && 2367 keybinding_delegate->MatchEvent(*event.os_event, &commands)) { 2368 // Transform from ui/ types to content/ types. 2369 EditCommands edit_commands; 2370 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it = 2371 commands.begin(); it != commands.end(); ++it) { 2372 edit_commands.push_back(EditCommand(it->GetCommandString(), 2373 it->argument())); 2374 } 2375 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent( 2376 host_->GetRoutingID(), edit_commands)); 2377 NativeWebKeyboardEvent copy_event(event); 2378 copy_event.match_edit_command = true; 2379 host_->ForwardKeyboardEvent(copy_event); 2380 return; 2381 } 2382 #endif 2383 2384 host_->ForwardKeyboardEvent(event); 2385 } 2386 2387 SkBitmap::Config RenderWidgetHostViewAura::PreferredReadbackFormat() { 2388 return SkBitmap::kARGB_8888_Config; 2389 } 2390 2391 //////////////////////////////////////////////////////////////////////////////// 2392 // DelegatedFrameHost, public: 2393 2394 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const { 2395 aura::WindowTreeHost* host = window_->GetHost(); 2396 return host ? host->compositor() : NULL; 2397 } 2398 2399 ui::Layer* RenderWidgetHostViewAura::GetLayer() { 2400 return window_->layer(); 2401 } 2402 2403 RenderWidgetHostImpl* RenderWidgetHostViewAura::GetHost() { 2404 return host_; 2405 } 2406 2407 void RenderWidgetHostViewAura::SchedulePaintInRect( 2408 const gfx::Rect& damage_rect_in_dip) { 2409 window_->SchedulePaintInRect(damage_rect_in_dip); 2410 } 2411 2412 bool RenderWidgetHostViewAura::IsVisible() { 2413 return IsShowing(); 2414 } 2415 2416 gfx::Size RenderWidgetHostViewAura::DesiredFrameSize() { 2417 return window_->bounds().size(); 2418 } 2419 2420 float RenderWidgetHostViewAura::CurrentDeviceScaleFactor() { 2421 return current_device_scale_factor_; 2422 } 2423 2424 gfx::Size RenderWidgetHostViewAura::ConvertViewSizeToPixel( 2425 const gfx::Size& size) { 2426 return content::ConvertViewSizeToPixel(this, size); 2427 } 2428 2429 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock( 2430 bool defer_compositor_lock) { 2431 gfx::Size desired_size = window_->bounds().size(); 2432 return scoped_ptr<ResizeLock>(new CompositorResizeLock( 2433 window_->GetHost(), 2434 desired_size, 2435 defer_compositor_lock, 2436 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs))); 2437 } 2438 2439 DelegatedFrameHost* RenderWidgetHostViewAura::GetDelegatedFrameHost() const { 2440 return delegated_frame_host_.get(); 2441 } 2442 2443 //////////////////////////////////////////////////////////////////////////////// 2444 // RenderWidgetHostViewBase, public: 2445 2446 // static 2447 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) { 2448 GetScreenInfoForWindow(results, NULL); 2449 } 2450 2451 } // namespace content 2452