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