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.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.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"
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"
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"
98 using gfx::RectToSkIRect;
99 using gfx::SkIRectToRect;
101 using blink::WebScreenInfo;
102 using blink::WebInputEvent;
103 using blink::WebGestureEvent;
104 using blink::WebTouchEvent;
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;
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;
126 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
127 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
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);
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());
148 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
149 RenderWidgetHostViewAura* widget =
150 reinterpret_cast<RenderWidgetHostViewAura*>(param);
152 if (GetProp(window, kWidgetOwnerProperty) == widget &&
153 widget->GetNativeView()->GetHost()) {
154 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
155 SetParent(window, parent);
160 struct CutoutRectsParams {
161 RenderWidgetHostViewAura* widget;
162 std::vector<gfx::Rect> cutout_rects;
163 std::map<HWND, WebPluginGeometry>* geometry;
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);
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.
177 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
179 offset.x = offset.y = 0;
180 MapWindowPoints(window, parent, &offset, 1);
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) {
191 if (i == params->geometry->end()) {
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);
208 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
209 // If we don't have any cutout rects then no point in messing with the
211 if (cutout_rects.size())
212 SetWindowRgn(window, hrgn, TRUE);
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);
222 if (::IsWindowVisible(window)) {
223 const HWND owner = ::GetWindow(window, GW_OWNER);
224 if (toplevel_hwnd == owner) {
225 ::PostMessage(window, WM_CANCELMODE, 0, 0);
233 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
234 blink::WebTouchPoint* point) {
235 if (point->state != blink::WebTouchPoint::StateReleased &&
236 point->state != blink::WebTouchPoint::StateCancelled)
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)
244 for (unsigned i = point - event->touches; i < new_length; ++i)
245 event->touches[i] = event->touches[i + 1];
246 event->touchesLength = new_length;
249 bool CanRendererHandleEvent(const ui::MouseEvent* event) {
250 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
254 // Renderer cannot handle WM_XBUTTON or NC events.
255 switch (event->native_event().message) {
258 case WM_XBUTTONDBLCLK:
259 case WM_NCMOUSELEAVE:
261 case WM_NCLBUTTONDOWN:
263 case WM_NCLBUTTONDBLCLK:
264 case WM_NCRBUTTONDOWN:
266 case WM_NCRBUTTONDBLCLK:
267 case WM_NCMBUTTONDOWN:
269 case WM_NCMBUTTONDBLCLK:
270 case WM_NCXBUTTONDOWN:
272 case WM_NCXBUTTONDBLCLK:
277 #elif defined(USE_X11)
278 // Renderer only supports standard mouse buttons, so ignore programmable
280 switch (event->type()) {
281 case ui::ET_MOUSE_PRESSED:
282 case ui::ET_MOUSE_RELEASED:
283 return event->IsAnyButton();
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) {
295 switch (event->native_event().message) {
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.
312 results->depthPerComponent = 8;
313 results->deviceScaleFactor = display.device_scale_factor();
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;
325 results->orientationType =
326 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
329 bool PointerEventActivates(const ui::Event& event) {
330 if (event.type() == ui::ET_MOUSE_PRESSED)
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;
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 {
349 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
352 aura::Env::GetInstance()->AddPreTargetHandler(this);
355 virtual ~EventFilterForPopupExit() {
356 aura::Env::GetInstance()->RemovePreTargetHandler(this);
359 // Overridden from ui::EventHandler
360 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
361 rwhva_->ApplyEventFilterForPopupExit(event);
364 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
365 rwhva_->ApplyEventFilterForPopupExit(event);
369 RenderWidgetHostViewAura* rwhva_;
371 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
374 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
375 ui::LocatedEvent* event) {
376 if (in_shutdown_ || is_fullscreen_ || !event->target())
379 if (event->type() != ui::ET_MOUSE_PRESSED &&
380 event->type() != ui::ET_TOUCH_PRESSED) {
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().
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 {
401 explicit WindowObserver(RenderWidgetHostViewAura* view)
403 view_->window_->AddObserver(this);
406 virtual ~WindowObserver() {
407 view_->window_->RemoveObserver(this);
410 // Overridden from aura::WindowObserver:
411 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
412 if (window == view_->window_)
413 view_->AddedToRootWindow();
416 virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
417 aura::Window* new_root) OVERRIDE {
418 if (window == view_->window_)
419 view_->RemovingFromRootWindow();
423 RenderWidgetHostViewAura* view_;
425 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
428 ////////////////////////////////////////////////////////////////////////////////
429 // RenderWidgetHostViewAura, public:
431 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
432 : host_(RenderWidgetHostImpl::From(host)),
433 window_(new aura::Window(this)),
434 delegated_frame_host_(new DelegatedFrameHost(this)),
436 in_bounds_changed_(false),
437 is_fullscreen_(false),
438 popup_parent_host_view_(NULL),
439 popup_child_host_view_(NULL),
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),
448 synthetic_move_sent_(false),
449 cursor_visibility_state_in_renderer_(UNKNOWN),
451 legacy_render_widget_host_HWND_(NULL),
452 legacy_window_destroyed_(false),
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);
466 bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
467 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
468 SetOverscrollControllerEnabled(overscroll_enabled);
471 ////////////////////////////////////////////////////////////////////////////////
472 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
474 bool RenderWidgetHostViewAura::OnMessageReceived(
475 const IPC::Message& message) {
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()
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");
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);
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_;
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_);
515 old_child->popup_parent_host_view_ = NULL;
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");
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_);
532 SetBounds(bounds_in_screen);
534 #if !defined(OS_WIN) && !defined(OS_CHROMEOS)
535 if (NeedsInputGrab())
536 window_->SetCapture();
539 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
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);
550 aura::Window* parent = NULL;
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);
559 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
560 GetDisplayNearestWindow(reference_window);
561 parent = reference_window->GetRootWindow();
562 bounds = display.bounds();
564 aura::client::ParentWindowWithContext(window_, parent, bounds);
569 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
573 void RenderWidgetHostViewAura::WasShown() {
575 if (!host_->is_hidden())
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);
584 renderer_latency_info.AddLatencyNumber(
585 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
587 host_->WasShown(renderer_latency_info);
589 aura::Window* root = window_->GetRootWindow();
591 aura::client::CursorClient* cursor_client =
592 aura::client::GetCursorClient(root);
594 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
597 delegated_frame_host_->WasShown(browser_latency_info);
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());
610 LPARAM lparam = reinterpret_cast<LPARAM>(this);
611 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
615 void RenderWidgetHostViewAura::WasHidden() {
616 if (!host_ || host_->is_hidden())
619 delegated_frame_host_->WasHidden();
622 constrained_rects_.clear();
623 aura::WindowTreeHost* host = window_->GetHost();
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());
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));
643 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
644 gfx::Point relative_origin(rect.origin());
646 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
647 // Window::SetBounds() takes parent coordinates, so do the conversion here.
648 aura::Window* root = window_->GetRootWindow();
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);
658 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
661 gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
662 return last_scroll_offset_;
665 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
669 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
671 aura::WindowTreeHost* host = window_->GetHost();
673 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
675 return static_cast<gfx::NativeViewId>(NULL);
678 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
680 aura::WindowTreeHost* host = window_->GetHost();
682 return static_cast<gfx::NativeViewAccessible>(NULL);
683 HWND hwnd = host->GetAcceleratedWidget();
684 BrowserAccessibilityManager* manager =
685 host_->GetOrCreateRootBrowserAccessibilityManager();
687 return manager->GetRoot()->ToBrowserAccessibilityWin();
691 return static_cast<gfx::NativeViewAccessible>(NULL);
694 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
698 void RenderWidgetHostViewAura::SetKeyboardFocus() {
701 aura::WindowTreeHost* host = window_->GetHost();
703 ::SetFocus(host->GetAcceleratedWidget());
708 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
709 if (!host_->IsRenderView())
711 RenderViewHost* rvh = RenderViewHost::From(host_);
712 FrameTreeNode* focused_frame =
713 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
717 return focused_frame->current_frame_host();
720 void RenderWidgetHostViewAura::MovePluginWindows(
721 const std::vector<WebPluginGeometry>& plugin_window_moves) {
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());
729 HWND parent = window_->GetHost()->GetAcceleratedWidget();
730 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
731 std::vector<WebPluginGeometry> moves = plugin_window_moves;
733 gfx::Rect view_port(view_bounds.size());
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;
744 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
746 plugin_window_moves_[moves[i].window] = moves[i];
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);
757 MovePluginWindowsHelper(parent, moves);
759 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
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);
766 if (!GetProp(window, kWidgetOwnerProperty))
767 SetProp(window, kWidgetOwnerProperty, this);
769 #endif // defined(OS_WIN)
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_);
781 void RenderWidgetHostViewAura::Blur() {
785 bool RenderWidgetHostViewAura::HasFocus() const {
786 return window_->HasFocus();
789 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
790 return delegated_frame_host_->CanCopyToBitmap();
793 void RenderWidgetHostViewAura::Show() {
797 if (legacy_render_widget_host_HWND_)
798 legacy_render_widget_host_HWND_->Show();
802 void RenderWidgetHostViewAura::Hide() {
806 if (legacy_render_widget_host_HWND_)
807 legacy_render_widget_host_HWND_->Hide();
811 bool RenderWidgetHostViewAura::IsShowing() {
812 return window_->IsVisible();
815 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
816 return window_->GetBoundsInScreen();
819 void RenderWidgetHostViewAura::SetBackgroundOpaque(bool opaque) {
820 RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
821 host_->SetBackgroundOpaque(opaque);
822 window_->layer()->SetFillsBoundsOpaquely(opaque);
825 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
826 gfx::Rect requested_rect(GetRequestedRendererSize());
827 requested_rect.Inset(insets_);
828 return requested_rect.size();
831 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
832 if (insets != insets_) {
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();
846 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
847 is_loading_ = is_loading;
848 UpdateCursorIfOverSelf();
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_);
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();
876 void RenderWidgetHostViewAura::ImeCancelComposition() {
877 if (GetInputMethod())
878 GetInputMethod()->CancelComposition(this);
879 has_composition_text_ = false;
882 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
883 const gfx::Range& range,
884 const std::vector<gfx::Rect>& character_bounds) {
885 composition_character_bounds_ = character_bounds;
888 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
890 UpdateCursorIfOverSelf();
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.
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);
915 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
917 const gfx::Range& range) {
918 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
920 #if defined(USE_X11) && !defined(OS_CHROMEOS)
921 if (text.empty() || range.is_empty())
923 size_t pos = range.GetMin() - offset;
924 size_t n = range.length();
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.";
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)
938 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
939 return delegated_frame_host_->GetRequestedRendererSize();
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)
948 selection_anchor_rect_ = params.anchor_rect;
949 selection_focus_rect_ = params.focus_rect;
951 if (GetInputMethod())
952 GetInputMethod()->OnCaretBoundsChanged(this);
954 if (touch_editing_client_) {
955 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
956 selection_focus_rect_);
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);
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);
977 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
978 return delegated_frame_host_->CanCopyToVideoFrame();
981 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
982 return delegated_frame_host_->CanSubscribeFrame();
985 void RenderWidgetHostViewAura::BeginFrameSubscription(
986 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
987 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
990 void RenderWidgetHostViewAura::EndFrameSubscription() {
991 delegated_frame_host_->EndFrameSubscription();
994 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
999 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1000 return (legacy_render_widget_host_HWND_ != NULL);
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())
1010 if (rects == constrained_rects_)
1013 constrained_rects_ = rects;
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);
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);
1032 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1033 legacy_render_widget_host_HWND_ = NULL;
1034 legacy_window_destroyed_ = true;
1038 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1039 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
1041 // Oldschool composited mode is no longer supported.
1044 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1045 uint32 output_surface_id,
1046 scoped_ptr<cc::CompositorFrame> frame) {
1047 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1049 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1050 if (frame->delegated_frame_data) {
1051 delegated_frame_host_->SwapDelegatedFrame(
1053 frame->delegated_frame_data.Pass(),
1054 frame->metadata.device_scale_factor,
1055 frame->metadata.latency_info);
1059 if (frame->software_frame_data) {
1060 DLOG(ERROR) << "Unable to use software frame in aura";
1062 base::UserMetricsAction("BadMessageTerminate_SharedMemoryAura"));
1063 host_->GetProcess()->ReceivedBadMessage();
1068 void RenderWidgetHostViewAura::DidStopFlinging() {
1069 if (touch_editing_client_)
1070 touch_editing_client_->DidStopFlinging();
1074 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1075 gfx::NativeViewAccessible accessible_parent) {
1078 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1080 if (legacy_render_widget_host_HWND_) {
1081 return reinterpret_cast<gfx::NativeViewId>(
1082 legacy_render_widget_host_HWND_->hwnd());
1088 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
1089 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
1091 // Oldschool composited mode is no longer supported.
1094 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
1097 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
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.
1108 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1109 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1112 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1113 aura::Window* top_level = window_->GetToplevelWindow();
1114 gfx::Rect bounds(top_level->GetBoundsInScreen());
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
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();
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);
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));
1139 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1140 GetSystemMetrics(SM_CXPADDEDBORDER));
1144 bounds = gfx::win::ScreenToDIPRect(bounds);
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));
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);
1165 if (overscroll_controller_) {
1166 overscroll_controller_->ReceivedEventACK(
1167 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1171 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1172 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1173 ScopedVector<ui::TouchEvent> events;
1174 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
1175 SCREEN_COORDINATES))
1178 aura::WindowTreeHost* host = window_->GetHost();
1179 // |host| is NULL during tests.
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);
1191 scoped_ptr<SyntheticGestureTarget>
1192 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1193 return scoped_ptr<SyntheticGestureTarget>(
1194 new SyntheticGestureTargetAura(host_));
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) {
1212 if (overscroll_controller_)
1213 consumed |= overscroll_controller_->WillHandleEvent(input_event);
1215 return consumed && !WebTouchEvent::isTouchEventType(input_event.type)
1216 ? INPUT_EVENT_ACK_STATE_CONSUMED
1217 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1220 BrowserAccessibilityManager*
1221 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1222 BrowserAccessibilityDelegate* delegate) {
1223 BrowserAccessibilityManager* manager = NULL;
1225 manager = new BrowserAccessibilityManagerWin(
1226 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
1228 manager = BrowserAccessibilityManager::Create(
1229 BrowserAccessibilityManager::GetEmptyDocument(), delegate);
1234 gfx::AcceleratedWidget
1235 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1237 if (legacy_render_widget_host_HWND_)
1238 return legacy_render_widget_host_HWND_->hwnd();
1240 return gfx::kNullAcceleratedWidget;
1243 gfx::NativeViewAccessible
1244 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1246 if (legacy_render_widget_host_HWND_)
1247 return legacy_render_widget_host_HWND_->window_accessible();
1253 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1254 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
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())
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);
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)));
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_;
1283 CopyFromCompositingSurface(
1284 disambiguation_target_rect_,
1286 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
1287 base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
1288 <RenderWidgetHostViewAura>(this)),
1292 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1294 const SkBitmap& result) {
1295 if (!success || disambiguation_scroll_offset_ != last_scroll_offset_)
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;
1305 delegate_view = delegate->GetDelegateView();
1306 if (delegate->IsVirtualKeyboardRequested())
1309 if (delegate_view) {
1310 delegate_view->ShowDisambiguationPopup(
1311 disambiguation_target_rect_,
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)));
1322 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1323 RenderViewHostDelegate* delegate = NULL;
1324 if (host_->IsRenderView())
1325 delegate = RenderViewHost::From(host_)->GetDelegate();
1326 RenderViewHostDelegateView* delegate_view = NULL;
1328 delegate_view = delegate->GetDelegateView();
1330 delegate_view->HideDisambiguationPopup();
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)
1342 host_->ForwardGestureEvent(web_gesture);
1345 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1346 ui::MouseEvent* event) {
1347 blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(event);
1348 host_->ForwardMouseEvent(web_mouse);
1351 bool RenderWidgetHostViewAura::LockMouse() {
1352 aura::Window* root_window = window_->GetRootWindow();
1359 mouse_locked_ = true;
1360 #if !defined(OS_WIN)
1361 window_->SetCapture();
1363 UpdateMouseLockRegion();
1365 aura::client::CursorClient* cursor_client =
1366 aura::client::GetCursorClient(root_window);
1367 if (cursor_client) {
1368 cursor_client->HideCursor();
1369 cursor_client->LockCursor();
1372 if (ShouldMoveToCenter()) {
1373 synthetic_move_sent_ = true;
1374 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1376 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1380 void RenderWidgetHostViewAura::UnlockMouse() {
1381 tooltip_disabler_.reset();
1383 aura::Window* root_window = window_->GetRootWindow();
1384 if (!mouse_locked_ || !root_window)
1387 mouse_locked_ = false;
1389 #if !defined(OS_WIN)
1390 window_->ReleaseCapture();
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();
1402 host_->LostMouseLock();
1405 ////////////////////////////////////////////////////////////////////////////////
1406 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1407 void RenderWidgetHostViewAura::SetCompositionText(
1408 const ui::CompositionText& composition) {
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),
1424 it->background_color));
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());
1433 has_composition_text_ = !composition.text.empty();
1436 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1437 if (host_ && has_composition_text_) {
1438 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1441 has_composition_text_ = false;
1444 void RenderWidgetHostViewAura::ClearCompositionText() {
1445 if (host_ && has_composition_text_)
1446 host_->ImeCancelComposition();
1447 has_composition_text_ = false;
1450 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1451 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1453 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1454 has_composition_text_ = false;
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);
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,
1472 ForwardKeyboardEvent(webkit_event);
1476 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
1480 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1481 return text_input_type_;
1484 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1485 return text_input_mode_;
1488 bool RenderWidgetHostViewAura::CanComposeInline() const {
1489 return can_compose_inline_;
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());
1497 aura::Window* root_window = window_->GetRootWindow();
1500 aura::client::ScreenPositionClient* screen_position_client =
1501 aura::client::GetScreenPositionClient(root_window);
1502 if (!screen_position_client)
1504 screen_position_client->ConvertPointToScreen(window_, &origin);
1505 screen_position_client->ConvertPointToScreen(window_, &end);
1506 return gfx::Rect(origin.x(),
1508 end.x() - origin.x(),
1509 end.y() - origin.y());
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());
1517 aura::Window* root_window = window_->GetRootWindow();
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(),
1525 end.x() - origin.x(),
1526 end.y() - origin.y());
1532 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1533 const gfx::Rect rect =
1534 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
1535 return ConvertRectToScreen(rect);
1538 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1540 gfx::Rect* rect) const {
1542 if (index >= composition_character_bounds_.size())
1544 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1548 bool RenderWidgetHostViewAura::HasCompositionText() const {
1549 return has_composition_text_;
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());
1558 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1559 gfx::Range* range) const {
1560 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1565 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1566 range->set_start(selection_range_.start());
1567 range->set_end(selection_range_.end());
1571 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1572 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1577 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1578 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
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());
1589 if (!selection_text_range.Contains(range)) {
1593 if (selection_text_range.EqualsIgnoringDirection(range)) {
1594 // Avoid calling substr whose performance is low.
1595 *text = selection_text_;
1597 *text = selection_text_.substr(
1598 range.GetMin() - selection_text_offset_,
1604 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1608 if (GetInputMethod())
1609 host_->SetInputMethodActive(GetInputMethod()->IsActive());
1611 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1615 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1616 base::i18n::TextDirection direction) {
1619 host_->UpdateTextDirection(
1620 direction == base::i18n::RIGHT_TO_LEFT ?
1621 blink::WebTextDirectionRightToLeft :
1622 blink::WebTextDirectionLeftToRight);
1623 host_->NotifyTextDirection();
1627 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1628 size_t before, size_t after) {
1629 RenderFrameHostImpl* rfh = GetFocusedFrame();
1631 rfh->ExtendSelectionAndDelete(before, after);
1634 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1635 gfx::Rect intersected_rect(
1636 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1638 if (intersected_rect.IsEmpty())
1641 host_->ScrollFocusedEditableNodeIntoRect(
1642 ConvertRectFromScreen(intersected_rect));
1645 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
1646 host_->CandidateWindowShown();
1649 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
1650 host_->CandidateWindowUpdated();
1653 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
1654 host_->CandidateWindowHidden();
1657 bool RenderWidgetHostViewAura::IsEditingCommandEnabled(int command_id) {
1661 void RenderWidgetHostViewAura::ExecuteEditingCommand(int command_id) {
1664 ////////////////////////////////////////////////////////////////////////////////
1665 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1667 void RenderWidgetHostViewAura::OnDisplayAdded(
1668 const gfx::Display& new_display) {
1671 void RenderWidgetHostViewAura::OnDisplayRemoved(
1672 const gfx::Display& old_display) {
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();
1686 ////////////////////////////////////////////////////////////////////////////////
1687 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1689 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1693 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
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
1705 SetSize(new_bounds.size());
1707 if (GetInputMethod())
1708 GetInputMethod()->OnCaretBoundsChanged(this);
1711 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1713 return ui::kCursorNone;
1714 return current_cursor_.GetNativeCursor();
1717 int RenderWidgetHostViewAura::GetNonClientComponent(
1718 const gfx::Point& point) const {
1722 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1723 aura::Window* child,
1724 const gfx::Point& location) {
1728 bool RenderWidgetHostViewAura::CanFocus() {
1729 return popup_type_ == blink::WebPopupTypeNone;
1732 void RenderWidgetHostViewAura::OnCaptureLost() {
1733 host_->LostCapture();
1734 if (touch_editing_client_)
1735 touch_editing_client_->EndTouchEditing(false);
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
1742 if (window_->layer()->fills_bounds_opaquely())
1743 canvas->DrawColor(SK_ColorWHITE);
1746 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1747 float device_scale_factor) {
1748 if (!host_ || !window_->GetRootWindow())
1751 UpdateScreenInfo(window_);
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();
1760 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
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();
1768 parent = window_->GetHost()->GetAcceleratedWidget();
1770 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1771 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
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
1784 legacy_render_widget_host_HWND_ = NULL;
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();
1793 input_method->DetachTextInputClient(this);
1795 if (overscroll_controller_)
1796 overscroll_controller_->Reset();
1799 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1800 host_->ViewDestroyed();
1804 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1807 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1811 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1814 ////////////////////////////////////////////////////////////////////////////////
1815 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1817 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1818 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1819 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1822 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1823 popup_child_host_view_->OnKeyEvent(event);
1824 if (event->handled())
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);
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);
1841 if (!tracker.Contains(window)) {
1842 event->SetHandled();
1847 if (!in_shutdown_) {
1848 in_shutdown_ = true;
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_)
1856 // Accept return key character events between press and release events.
1857 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
1860 // We don't have to communicate with an input method here.
1861 if (!event->HasNativeEvent()) {
1862 NativeWebKeyboardEvent webkit_event(
1865 event->is_char() ? event->GetCharacter() : event->key_code(),
1867 ui::EventTimeForNow().InSecondsF());
1868 ForwardKeyboardEvent(webkit_event);
1870 NativeWebKeyboardEvent webkit_event(event);
1871 ForwardKeyboardEvent(webkit_event);
1874 event->SetHandled();
1877 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
1878 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
1880 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1883 if (mouse_locked_) {
1884 aura::client::CursorClient* cursor_client =
1885 aura::client::GetCursorClient(window_->GetRootWindow());
1886 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
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);
1896 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
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);
1907 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
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();
1913 ModifyEventMovementAndCoords(&mouse_event);
1915 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
1916 if (should_not_forward) {
1917 synthetic_move_sent_ = false;
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);
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)
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
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();
1953 if (event->type() == ui::ET_MOUSEWHEEL) {
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
1958 aura::WindowTreeHost* host = window_->GetHost();
1960 HWND parent = host->GetAcceleratedWidget();
1961 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
1962 EnumThreadWindows(GetCurrentThreadId(),
1964 reinterpret_cast<LPARAM>(toplevel_hwnd));
1967 // The Disambiguation popup does not parent itself from this window, so we
1968 // manually dismiss it.
1969 HideDisambiguationPopup();
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)
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();
1993 case ui::ET_MOUSE_RELEASED:
1994 window_->ReleaseCapture();
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);
2012 if (!IsXButtonUpEvent(event))
2013 event->SetHandled();
2016 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2017 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2018 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2021 if (event->type() == ui::ET_SCROLL) {
2022 #if !defined(OS_WIN)
2024 // Investigate if this is true for Windows 8 Metro ASH as well.
2025 if (event->finger_count() != 2)
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"));
2044 event->SetHandled();
2047 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2048 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2049 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2052 // Update the touch event first.
2053 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
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();
2066 if (host_->ShouldForwardTouchEvent())
2067 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
2068 UpdateWebTouchEventAfterDispatch(&touch_event_, point);
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();
2081 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2084 RenderViewHostDelegate* delegate = NULL;
2085 if (host_->IsRenderView())
2086 delegate = RenderViewHost::From(host_)->GetDelegate();
2088 if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
2089 event->details().touch_points() == 1) {
2090 delegate->HandleGestureBegin();
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);
2103 if (gesture.type != blink::WebInputEvent::Undefined) {
2104 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
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"));
2115 if (delegate && event->type() == ui::ET_GESTURE_END &&
2116 event->details().touch_points() == 1) {
2117 delegate->HandleGestureEnd();
2120 // If a gesture is not processed by the webpage, then WebKit processes it
2121 // (e.g. generates synthetic mouse events).
2122 event->SetHandled();
2125 ////////////////////////////////////////////////////////////////////////////////
2126 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2128 bool RenderWidgetHostViewAura::ShouldActivate() const {
2129 aura::WindowTreeHost* host = window_->GetHost();
2132 const ui::Event* event = host->dispatcher()->current_event();
2135 return is_fullscreen_;
2138 ////////////////////////////////////////////////////////////////////////////////
2139 // RenderWidgetHostViewAura,
2140 // aura::client::ActivationChangeObserver implementation:
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();
2152 ////////////////////////////////////////////////////////////////////////////////
2153 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2155 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2156 NotifyRendererOfCursorVisibilityState(is_visible);
2159 ////////////////////////////////////////////////////////////////////////////////
2160 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
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())
2173 host_->SetActive(true);
2175 ui::InputMethod* input_method = GetInputMethod();
2177 // Ask the system-wide IME to send all TextInputClient messages to |this|
2179 input_method->SetFocusedTextInputClient(this);
2180 host_->SetInputMethodActive(input_method->IsActive());
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
2185 host_->SuppressNextCharEvents();
2187 host_->SetInputMethodActive(false);
2190 BrowserAccessibilityManager* manager =
2191 host_->GetRootBrowserAccessibilityManager();
2193 manager->OnWindowFocused();
2194 } else if (window_ == lost_focus) {
2195 host_->SetActive(false);
2198 DetachFromInputMethod();
2199 host_->SetInputMethodActive(false);
2201 if (touch_editing_client_)
2202 touch_editing_client_->EndTouchEditing(false);
2204 if (overscroll_controller_)
2205 overscroll_controller_->Cancel();
2207 BrowserAccessibilityManager* manager =
2208 host_->GetRootBrowserAccessibilityManager();
2210 manager->OnWindowBlurred();
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) {
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) {
2226 ::GetCursorPos(&point);
2227 if (screen->GetDisplayNearestWindow(window_).id() !=
2228 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2232 in_shutdown_ = true;
2238 ////////////////////////////////////////////////////////////////////////////////
2239 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
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());
2246 UpdateScreenInfo(window_);
2249 ////////////////////////////////////////////////////////////////////////////////
2250 // RenderWidgetHostViewAura, private:
2252 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2253 if (touch_editing_client_)
2254 touch_editing_client_->OnViewDestroyed();
2256 delegated_frame_host_.reset();
2257 window_observer_.reset();
2258 if (window_->GetHost())
2259 window_->GetHost()->RemoveObserver(this);
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;
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;
2271 event_filter_for_popup_exit_.reset();
2272 aura::client::SetTooltipText(window_, NULL);
2273 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
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();
2281 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2282 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2284 DCHECK(!legacy_render_widget_host_HWND_);
2288 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2289 const gfx::Point screen_point =
2290 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2291 aura::Window* root_window = window_->GetRootWindow();
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);
2303 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
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;
2311 aura::client::CursorClient* cursor_client =
2312 aura::client::GetCursorClient(root_window);
2313 if (cursor_client) {
2314 cursor_client->SetCursor(cursor);
2318 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2319 aura::Window* root_window = window_->GetRootWindow();
2322 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
2325 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2326 return popup_type_ == blink::WebPopupTypeSelect;
2329 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2330 if (!has_composition_text_)
2333 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2336 ImeCancelComposition();
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);
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
2353 event->movementX = event->globalX - global_mouse_position_.x();
2354 event->movementY = event->globalY - global_mouse_position_.y();
2356 global_mouse_position_.SetPoint(event->globalX, event->globalY);
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();
2368 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
2369 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2373 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2375 if (host_->is_hidden() ||
2376 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2377 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2380 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2381 host_->SendCursorVisibilityState(is_visible);
2384 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
2386 overscroll_controller_.reset();
2387 else if (!overscroll_controller_)
2388 overscroll_controller_.reset(new OverscrollController());
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();
2404 snapped = window_->GetToplevelWindow();
2406 if (snapped && snapped != window_)
2407 ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
2409 has_snapped_to_boundary_ = true;
2412 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
2413 if (HasDisplayPropertyChanged(window_))
2414 host_->InvalidateScreenInfo();
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_);
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
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()));
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
2451 if (!host_->is_hidden())
2452 legacy_render_widget_host_HWND_->Show();
2457 UpdateMouseLockRegion();
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);
2469 window_->SchedulePaintInRect(rect);
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;
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;
2485 void RenderWidgetHostViewAura::AddedToRootWindow() {
2486 window_->GetHost()->AddObserver(this);
2487 UpdateScreenInfo(window_);
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());
2496 ui::InputMethod* input_method = GetInputMethod();
2498 input_method->SetFocusedTextInputClient(this);
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()));
2509 delegated_frame_host_->AddedToWindow();
2512 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2513 aura::client::CursorClient* cursor_client =
2514 aura::client::GetCursorClient(window_->GetRootWindow());
2516 cursor_client->RemoveObserver(this);
2518 DetachFromInputMethod();
2520 window_->GetHost()->RemoveObserver(this);
2521 delegated_frame_host_->RemovingFromWindow();
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());
2531 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2532 ui::InputMethod* input_method = GetInputMethod();
2533 if (input_method && input_method->GetTextInputClient() == this)
2534 input_method->SetFocusedTextInputClient(NULL);
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 &&
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(),
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);
2563 host_->ForwardKeyboardEvent(event);
2566 SkColorType RenderWidgetHostViewAura::PreferredReadbackFormat() {
2567 return kN32_SkColorType;
2570 ////////////////////////////////////////////////////////////////////////////////
2571 // DelegatedFrameHost, public:
2573 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
2574 aura::WindowTreeHost* host = window_->GetHost();
2575 return host ? host->compositor() : NULL;
2578 ui::Layer* RenderWidgetHostViewAura::GetLayer() {
2579 return window_->layer();
2582 RenderWidgetHostImpl* RenderWidgetHostViewAura::GetHost() {
2586 bool RenderWidgetHostViewAura::IsVisible() {
2590 gfx::Size RenderWidgetHostViewAura::DesiredFrameSize() {
2591 return window_->bounds().size();
2594 float RenderWidgetHostViewAura::CurrentDeviceScaleFactor() {
2595 return current_device_scale_factor_;
2598 gfx::Size RenderWidgetHostViewAura::ConvertViewSizeToPixel(
2599 const gfx::Size& size) {
2600 return content::ConvertViewSizeToPixel(this, size);
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(
2609 defer_compositor_lock,
2610 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2613 DelegatedFrameHost* RenderWidgetHostViewAura::GetDelegatedFrameHost() const {
2614 return delegated_frame_host_.get();
2617 ////////////////////////////////////////////////////////////////////////////////
2618 // RenderWidgetHostViewBase, public:
2621 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2622 GetScreenInfoForWindow(results, NULL);
2625 } // namespace content