This sets up API to release OutputSurface from LTHClient.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura.cc
blob4d8e2b73bc90d4b1ae7a709288440fab761451a1
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 <set>
9 #include "base/auto_reset.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/trace_event/trace_event.h"
18 #include "cc/layers/layer.h"
19 #include "cc/output/copy_output_request.h"
20 #include "cc/output/copy_output_result.h"
21 #include "cc/resources/texture_mailbox.h"
22 #include "cc/trees/layer_tree_settings.h"
23 #include "content/browser/accessibility/browser_accessibility_manager.h"
24 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
25 #include "content/browser/bad_message.h"
26 #include "content/browser/frame_host/frame_tree.h"
27 #include "content/browser/frame_host/frame_tree_node.h"
28 #include "content/browser/frame_host/render_frame_host_impl.h"
29 #include "content/browser/gpu/compositor_util.h"
30 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
31 #include "content/browser/renderer_host/dip_util.h"
32 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
33 #include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
34 #include "content/browser/renderer_host/input/ui_touch_selection_helper.h"
35 #include "content/browser/renderer_host/input/web_input_event_util.h"
36 #include "content/browser/renderer_host/overscroll_controller.h"
37 #include "content/browser/renderer_host/render_view_host_delegate.h"
38 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
39 #include "content/browser/renderer_host/render_view_host_impl.h"
40 #include "content/browser/renderer_host/render_widget_host_delegate.h"
41 #include "content/browser/renderer_host/render_widget_host_impl.h"
42 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
43 #include "content/browser/renderer_host/ui_events_helper.h"
44 #include "content/browser/renderer_host/web_input_event_aura.h"
45 #include "content/common/gpu/client/gl_helper.h"
46 #include "content/common/gpu/gpu_messages.h"
47 #include "content/common/view_messages.h"
48 #include "content/public/browser/content_browser_client.h"
49 #include "content/public/browser/overscroll_configuration.h"
50 #include "content/public/browser/render_view_host.h"
51 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
52 #include "content/public/browser/user_metrics.h"
53 #include "content/public/common/content_switches.h"
54 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
55 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
56 #include "third_party/WebKit/public/web/WebInputEvent.h"
57 #include "ui/aura/client/aura_constants.h"
58 #include "ui/aura/client/cursor_client.h"
59 #include "ui/aura/client/cursor_client_observer.h"
60 #include "ui/aura/client/focus_client.h"
61 #include "ui/aura/client/screen_position_client.h"
62 #include "ui/aura/client/window_tree_client.h"
63 #include "ui/aura/env.h"
64 #include "ui/aura/window.h"
65 #include "ui/aura/window_event_dispatcher.h"
66 #include "ui/aura/window_observer.h"
67 #include "ui/aura/window_tracker.h"
68 #include "ui/aura/window_tree_host.h"
69 #include "ui/base/clipboard/scoped_clipboard_writer.h"
70 #include "ui/base/hit_test.h"
71 #include "ui/base/ime/input_method.h"
72 #include "ui/base/ui_base_types.h"
73 #include "ui/compositor/compositor_vsync_manager.h"
74 #include "ui/compositor/dip_util.h"
75 #include "ui/events/blink/blink_event_util.h"
76 #include "ui/events/event.h"
77 #include "ui/events/event_utils.h"
78 #include "ui/events/gesture_detection/gesture_configuration.h"
79 #include "ui/events/gestures/gesture_recognizer.h"
80 #include "ui/gfx/canvas.h"
81 #include "ui/gfx/color_profile.h"
82 #include "ui/gfx/display.h"
83 #include "ui/gfx/geometry/rect_conversions.h"
84 #include "ui/gfx/geometry/size_conversions.h"
85 #include "ui/gfx/screen.h"
86 #include "ui/gfx/skia_util.h"
87 #include "ui/touch_selection/touch_selection_controller.h"
88 #include "ui/wm/public/activation_client.h"
89 #include "ui/wm/public/scoped_tooltip_disabler.h"
90 #include "ui/wm/public/tooltip_client.h"
91 #include "ui/wm/public/transient_window_client.h"
92 #include "ui/wm/public/window_types.h"
94 #if defined(OS_WIN)
95 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
96 #include "content/browser/accessibility/browser_accessibility_win.h"
97 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
98 #include "content/common/plugin_constants_win.h"
99 #include "ui/base/win/hidden_window.h"
100 #include "ui/gfx/gdi_util.h"
101 #include "ui/gfx/win/dpi.h"
102 #endif
104 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
105 #include "content/common/input_messages.h"
106 #include "ui/events/linux/text_edit_command_auralinux.h"
107 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
108 #endif
110 using gfx::RectToSkIRect;
111 using gfx::SkIRectToRect;
113 using blink::WebScreenInfo;
114 using blink::WebInputEvent;
115 using blink::WebGestureEvent;
116 using blink::WebTouchEvent;
118 namespace content {
120 namespace {
122 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
123 // the border of the view, in order to get valid movement information. However,
124 // forcing the cursor back to the center of the view after each mouse move
125 // doesn't work well. It reduces the frequency of useful mouse move messages
126 // significantly. Therefore, we move the cursor to the center of the view only
127 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
128 // of the border area, in percentage of the corresponding dimension.
129 const int kMouseLockBorderPercentage = 15;
131 // When accelerated compositing is enabled and a widget resize is pending,
132 // we delay further resizes of the UI. The following constant is the maximum
133 // length of time that we should delay further UI resizes while waiting for a
134 // resized frame from a renderer.
135 const int kResizeLockTimeoutMs = 67;
137 #if defined(OS_WIN)
138 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
139 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
141 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
142 RenderWidgetHostViewAura* widget =
143 reinterpret_cast<RenderWidgetHostViewAura*>(param);
144 if (GetProp(window, kWidgetOwnerProperty) == widget) {
145 // Properties set on HWNDs must be removed to avoid leaks.
146 RemoveProp(window, kWidgetOwnerProperty);
147 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
149 return TRUE;
152 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
153 RenderWidgetHostViewAura* widget =
154 reinterpret_cast<RenderWidgetHostViewAura*>(param);
155 if (GetProp(window, kWidgetOwnerProperty) == widget)
156 SetParent(window, ui::GetHiddenWindow());
157 return TRUE;
160 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
161 RenderWidgetHostViewAura* widget =
162 reinterpret_cast<RenderWidgetHostViewAura*>(param);
164 if (GetProp(window, kWidgetOwnerProperty) == widget &&
165 widget->GetNativeView()->GetHost()) {
166 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
167 SetParent(window, parent);
169 return TRUE;
172 struct CutoutRectsParams {
173 RenderWidgetHostViewAura* widget;
174 std::vector<gfx::Rect> cutout_rects;
175 std::map<HWND, WebPluginGeometry>* geometry;
178 // Used to update the region for the windowed plugin to draw in. We start with
179 // the clip rect from the renderer, then remove the cutout rects from the
180 // renderer, and then remove the transient windows from the root window and the
181 // constrained windows from the parent window.
182 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
183 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
185 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
186 // First calculate the offset of this plugin from the root window, since
187 // the cutouts are relative to the root window.
188 HWND parent =
189 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
190 POINT offset;
191 offset.x = offset.y = 0;
192 MapWindowPoints(window, parent, &offset, 1);
194 // Now get the cached clip rect and cutouts for this plugin window that came
195 // from the renderer.
196 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
197 while (i != params->geometry->end() &&
198 i->second.window != window &&
199 GetParent(i->second.window) != window) {
200 ++i;
203 if (i == params->geometry->end()) {
204 NOTREACHED();
205 return TRUE;
208 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
209 i->second.clip_rect.y(),
210 i->second.clip_rect.right(),
211 i->second.clip_rect.bottom());
212 // We start with the cutout rects that came from the renderer, then add the
213 // ones that came from transient and constrained windows.
214 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
215 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
216 gfx::Rect offset_cutout = params->cutout_rects[i];
217 offset_cutout.Offset(-offset.x, -offset.y);
218 cutout_rects.push_back(offset_cutout);
220 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
221 // If we don't have any cutout rects then no point in messing with the
222 // window region.
223 if (cutout_rects.size())
224 SetWindowRgn(window, hrgn, TRUE);
226 return TRUE;
229 // A callback function for EnumThreadWindows to enumerate and dismiss
230 // any owned popup windows.
231 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
232 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
234 if (::IsWindowVisible(window)) {
235 const HWND owner = ::GetWindow(window, GW_OWNER);
236 if (toplevel_hwnd == owner) {
237 ::PostMessage(window, WM_CANCELMODE, 0, 0);
241 return TRUE;
243 #endif
245 // We don't mark these as handled so that they're sent back to the
246 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
247 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
248 #if defined(OS_WIN)
249 switch (event->native_event().message) {
250 case WM_XBUTTONUP:
251 case WM_NCXBUTTONUP:
252 return true;
254 #endif
255 return false;
258 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
259 const gfx::Display display = window ?
260 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
261 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
262 results->rect = display.bounds();
263 results->availableRect = display.work_area();
264 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
265 results->depth = 24;
266 results->depthPerComponent = 8;
267 results->deviceScaleFactor = display.device_scale_factor();
269 // The Display rotation and the WebScreenInfo orientation are not the same
270 // angle. The former is the physical display rotation while the later is the
271 // rotation required by the content to be shown properly on the screen, in
272 // other words, relative to the physical display.
273 results->orientationAngle = display.RotationAsDegree();
274 if (results->orientationAngle == 90)
275 results->orientationAngle = 270;
276 else if (results->orientationAngle == 270)
277 results->orientationAngle = 90;
279 results->orientationType =
280 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
283 bool IsFractionalScaleFactor(float scale_factor) {
284 return (scale_factor - static_cast<int>(scale_factor)) > 0;
287 // Reset unchanged touch point to StateStationary for touchmove and
288 // touchcancel.
289 void MarkUnchangedTouchPointsAsStationary(
290 blink::WebTouchEvent* event,
291 int changed_touch_id) {
292 if (event->type == blink::WebInputEvent::TouchMove ||
293 event->type == blink::WebInputEvent::TouchCancel) {
294 for (size_t i = 0; i < event->touchesLength; ++i) {
295 if (event->touches[i].id != changed_touch_id)
296 event->touches[i].state = blink::WebTouchPoint::StateStationary;
301 } // namespace
303 // We need to watch for mouse events outside a Web Popup or its parent
304 // and dismiss the popup for certain events.
305 class RenderWidgetHostViewAura::EventFilterForPopupExit
306 : public ui::EventHandler {
307 public:
308 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
309 : rwhva_(rwhva) {
310 DCHECK(rwhva_);
311 aura::Env::GetInstance()->AddPreTargetHandler(this);
314 ~EventFilterForPopupExit() override {
315 aura::Env::GetInstance()->RemovePreTargetHandler(this);
318 // Overridden from ui::EventHandler
319 void OnMouseEvent(ui::MouseEvent* event) override {
320 rwhva_->ApplyEventFilterForPopupExit(event);
323 void OnTouchEvent(ui::TouchEvent* event) override {
324 rwhva_->ApplyEventFilterForPopupExit(event);
327 private:
328 RenderWidgetHostViewAura* rwhva_;
330 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
333 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
334 ui::LocatedEvent* event) {
335 if (in_shutdown_ || is_fullscreen_ || !event->target())
336 return;
338 if (event->type() != ui::ET_MOUSE_PRESSED &&
339 event->type() != ui::ET_TOUCH_PRESSED) {
340 return;
343 aura::Window* target = static_cast<aura::Window*>(event->target());
344 if (target != window_ &&
345 (!popup_parent_host_view_ ||
346 target != popup_parent_host_view_->window_)) {
347 // If we enter this code path it means that we did not receive any focus
348 // lost notifications for the popup window. Ensure that blink is aware
349 // of the fact that focus was lost for the host window by sending a Blur
350 // notification. We also set a flag in the view indicating that we need
351 // to force a Focus notification on the next mouse down.
352 if (popup_parent_host_view_ && popup_parent_host_view_->host_) {
353 popup_parent_host_view_->set_focus_on_mouse_down_ = true;
354 popup_parent_host_view_->host_->Blur();
356 // Note: popup_parent_host_view_ may be NULL when there are multiple
357 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
358 Shutdown();
362 // We have to implement the WindowObserver interface on a separate object
363 // because clang doesn't like implementing multiple interfaces that have
364 // methods with the same name. This object is owned by the
365 // RenderWidgetHostViewAura.
366 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
367 public:
368 explicit WindowObserver(RenderWidgetHostViewAura* view)
369 : view_(view) {
370 view_->window_->AddObserver(this);
373 ~WindowObserver() override { view_->window_->RemoveObserver(this); }
375 // Overridden from aura::WindowObserver:
376 void OnWindowAddedToRootWindow(aura::Window* window) override {
377 if (window == view_->window_)
378 view_->AddedToRootWindow();
381 void OnWindowRemovingFromRootWindow(aura::Window* window,
382 aura::Window* new_root) override {
383 if (window == view_->window_)
384 view_->RemovingFromRootWindow();
387 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
388 view_->ParentHierarchyChanged();
391 private:
392 RenderWidgetHostViewAura* view_;
394 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
397 // This class provides functionality to observe the ancestors of the RWHVA for
398 // bounds changes. This is done to snap the RWHVA window to a pixel boundary,
399 // which could change when the bounds relative to the root changes.
400 // An example where this happens is below:-
401 // The fast resize code path for bookmarks where in the parent of RWHVA which
402 // is WCV has its bounds changed before the bookmark is hidden. This results in
403 // the traditional bounds change notification for the WCV reporting the old
404 // bounds as the bookmark is still around. Observing all the ancestors of the
405 // RWHVA window enables us to know when the bounds of the window relative to
406 // root changes and allows us to snap accordingly.
407 class RenderWidgetHostViewAura::WindowAncestorObserver
408 : public aura::WindowObserver {
409 public:
410 explicit WindowAncestorObserver(RenderWidgetHostViewAura* view)
411 : view_(view) {
412 aura::Window* parent = view_->window_->parent();
413 while (parent) {
414 parent->AddObserver(this);
415 ancestors_.insert(parent);
416 parent = parent->parent();
420 ~WindowAncestorObserver() override {
421 RemoveAncestorObservers();
424 void OnWindowBoundsChanged(aura::Window* window,
425 const gfx::Rect& old_bounds,
426 const gfx::Rect& new_bounds) override {
427 DCHECK(ancestors_.find(window) != ancestors_.end());
428 if (new_bounds.origin() != old_bounds.origin())
429 view_->HandleParentBoundsChanged();
432 private:
433 void RemoveAncestorObservers() {
434 for (auto ancestor : ancestors_)
435 ancestor->RemoveObserver(this);
436 ancestors_.clear();
439 RenderWidgetHostViewAura* view_;
440 std::set<aura::Window*> ancestors_;
442 DISALLOW_COPY_AND_ASSIGN(WindowAncestorObserver);
445 ////////////////////////////////////////////////////////////////////////////////
446 // RenderWidgetHostViewAura, public:
448 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
449 bool is_guest_view_hack)
450 : host_(RenderWidgetHostImpl::From(host)),
451 window_(new aura::Window(this)),
452 delegated_frame_host_(new DelegatedFrameHost(this)),
453 in_shutdown_(false),
454 in_bounds_changed_(false),
455 is_fullscreen_(false),
456 popup_parent_host_view_(NULL),
457 popup_child_host_view_(NULL),
458 is_loading_(false),
459 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
460 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
461 text_input_flags_(0),
462 can_compose_inline_(true),
463 has_composition_text_(false),
464 accept_return_character_(false),
465 last_swapped_software_frame_scale_factor_(1.f),
466 paint_canvas_(NULL),
467 synthetic_move_sent_(false),
468 cursor_visibility_state_in_renderer_(UNKNOWN),
469 #if defined(OS_WIN)
470 legacy_render_widget_host_HWND_(NULL),
471 legacy_window_destroyed_(false),
472 showing_context_menu_(false),
473 #endif
474 has_snapped_to_boundary_(false),
475 is_guest_view_hack_(is_guest_view_hack),
476 begin_frame_observer_proxy_(this),
477 set_focus_on_mouse_down_(false),
478 weak_ptr_factory_(this) {
479 if (!is_guest_view_hack_)
480 host_->SetView(this);
482 window_observer_.reset(new WindowObserver(this));
484 aura::client::SetTooltipText(window_, &tooltip_);
485 aura::client::SetActivationDelegate(window_, this);
486 aura::client::SetFocusChangeObserver(window_, this);
487 window_->set_layer_owner_delegate(delegated_frame_host_.get());
488 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
490 // Let the page-level input event router know about our surface ID
491 // namespace for surface-based hit testing.
492 if (UseSurfacesEnabled() && host_->delegate() &&
493 host_->delegate()->GetInputEventRouter()) {
494 host_->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner(
495 GetSurfaceIdNamespace(), this);
498 bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
499 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
500 SetOverscrollControllerEnabled(overscroll_enabled);
502 selection_controller_client_.reset(
503 new TouchSelectionControllerClientAura(this));
504 CreateSelectionController();
507 ////////////////////////////////////////////////////////////////////////////////
508 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
510 bool RenderWidgetHostViewAura::OnMessageReceived(
511 const IPC::Message& message) {
512 bool handled = true;
513 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
514 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
515 OnSetNeedsBeginFrames)
516 IPC_MESSAGE_UNHANDLED(handled = false)
517 IPC_END_MESSAGE_MAP()
518 return handled;
521 void RenderWidgetHostViewAura::InitAsChild(
522 gfx::NativeView parent_view) {
523 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
524 window_->Init(ui::LAYER_SOLID_COLOR);
525 window_->SetName("RenderWidgetHostViewAura");
526 window_->layer()->SetColor(background_color_);
529 void RenderWidgetHostViewAura::InitAsPopup(
530 RenderWidgetHostView* parent_host_view,
531 const gfx::Rect& bounds_in_screen) {
532 popup_parent_host_view_ =
533 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
535 // TransientWindowClient may be NULL during tests.
536 aura::client::TransientWindowClient* transient_window_client =
537 aura::client::GetTransientWindowClient();
538 RenderWidgetHostViewAura* old_child =
539 popup_parent_host_view_->popup_child_host_view_;
540 if (old_child) {
541 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
542 // similar mechanism to ensure a second popup doesn't cause the first one
543 // to never get a chance to filter events. See crbug.com/160589.
544 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
545 if (transient_window_client) {
546 transient_window_client->RemoveTransientChild(
547 popup_parent_host_view_->window_, old_child->window_);
549 old_child->popup_parent_host_view_ = NULL;
551 popup_parent_host_view_->popup_child_host_view_ = this;
552 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
553 window_->Init(ui::LAYER_SOLID_COLOR);
554 window_->SetName("RenderWidgetHostViewAura");
555 window_->layer()->SetColor(background_color_);
557 // Setting the transient child allows for the popup to get mouse events when
558 // in a system modal dialog. Do this before calling ParentWindowWithContext
559 // below so that the transient parent is visible to WindowTreeClient.
560 // This fixes crbug.com/328593.
561 if (transient_window_client) {
562 transient_window_client->AddTransientChild(
563 popup_parent_host_view_->window_, window_);
566 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
567 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
569 SetBounds(bounds_in_screen);
570 Show();
571 if (NeedsMouseCapture())
572 window_->SetCapture();
574 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
577 void RenderWidgetHostViewAura::InitAsFullscreen(
578 RenderWidgetHostView* reference_host_view) {
579 is_fullscreen_ = true;
580 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
581 window_->Init(ui::LAYER_SOLID_COLOR);
582 window_->SetName("RenderWidgetHostViewAura");
583 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
584 window_->layer()->SetColor(background_color_);
586 aura::Window* parent = NULL;
587 gfx::Rect bounds;
588 if (reference_host_view) {
589 aura::Window* reference_window =
590 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
591 if (reference_window) {
592 host_tracker_.reset(new aura::WindowTracker);
593 host_tracker_->Add(reference_window);
595 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
596 GetDisplayNearestWindow(reference_window);
597 parent = reference_window->GetRootWindow();
598 bounds = display.bounds();
600 aura::client::ParentWindowWithContext(window_, parent, bounds);
601 Show();
602 Focus();
605 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
606 return host_;
609 void RenderWidgetHostViewAura::Show() {
610 window_->Show();
612 if (!host_->is_hidden())
613 return;
615 bool has_saved_frame = delegated_frame_host_->HasSavedFrame();
616 ui::LatencyInfo renderer_latency_info, browser_latency_info;
617 if (has_saved_frame) {
618 browser_latency_info.AddLatencyNumber(
619 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
620 } else {
621 renderer_latency_info.AddLatencyNumber(
622 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
624 host_->WasShown(renderer_latency_info);
626 aura::Window* root = window_->GetRootWindow();
627 if (root) {
628 aura::client::CursorClient* cursor_client =
629 aura::client::GetCursorClient(root);
630 if (cursor_client)
631 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
634 delegated_frame_host_->WasShown(browser_latency_info);
636 #if defined(OS_WIN)
637 if (legacy_render_widget_host_HWND_) {
638 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
639 // window before reparenting any plugins. This ensures that the plugin
640 // windows stay on top of the child Zorder in the parent and receive
641 // mouse events, etc.
642 legacy_render_widget_host_HWND_->UpdateParent(
643 GetNativeView()->GetHost()->GetAcceleratedWidget());
644 legacy_render_widget_host_HWND_->SetBounds(
645 window_->GetBoundsInRootWindow());
647 LPARAM lparam = reinterpret_cast<LPARAM>(this);
648 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
650 if (legacy_render_widget_host_HWND_)
651 legacy_render_widget_host_HWND_->Show();
652 #endif
655 void RenderWidgetHostViewAura::Hide() {
656 window_->Hide();
658 if (host_ && !host_->is_hidden()) {
659 host_->WasHidden();
660 delegated_frame_host_->WasHidden();
662 #if defined(OS_WIN)
663 constrained_rects_.clear();
664 aura::WindowTreeHost* host = window_->GetHost();
665 if (host) {
666 HWND parent = host->GetAcceleratedWidget();
667 LPARAM lparam = reinterpret_cast<LPARAM>(this);
668 EnumChildWindows(parent, HideWindowsCallback, lparam);
669 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
670 // hidden window on the same lines as Windowed plugin windows.
671 if (legacy_render_widget_host_HWND_)
672 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
674 #endif
677 #if defined(OS_WIN)
678 if (legacy_render_widget_host_HWND_)
679 legacy_render_widget_host_HWND_->Hide();
680 #endif
683 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
684 // For a SetSize operation, we don't care what coordinate system the origin
685 // of the window is in, it's only important to make sure that the origin
686 // remains constant after the operation.
687 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
690 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
691 gfx::Point relative_origin(rect.origin());
693 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
694 // Window::SetBounds() takes parent coordinates, so do the conversion here.
695 aura::Window* root = window_->GetRootWindow();
696 if (root) {
697 aura::client::ScreenPositionClient* screen_position_client =
698 aura::client::GetScreenPositionClient(root);
699 if (screen_position_client) {
700 screen_position_client->ConvertPointFromScreen(
701 window_->parent(), &relative_origin);
705 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
708 gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
709 return last_scroll_offset_;
712 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
713 return window_;
716 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
717 #if defined(OS_WIN)
718 aura::WindowTreeHost* host = window_->GetHost();
719 if (host)
720 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
721 #endif
722 return static_cast<gfx::NativeViewId>(NULL);
725 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
726 #if defined(OS_WIN)
727 aura::WindowTreeHost* host = window_->GetHost();
728 if (!host)
729 return static_cast<gfx::NativeViewAccessible>(NULL);
730 BrowserAccessibilityManager* manager =
731 host_->GetOrCreateRootBrowserAccessibilityManager();
732 if (manager)
733 return manager->GetRoot()->ToBrowserAccessibilityWin();
734 #endif
736 NOTIMPLEMENTED();
737 return static_cast<gfx::NativeViewAccessible>(NULL);
740 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
741 return this;
744 void RenderWidgetHostViewAura::OnSetNeedsBeginFrames(bool needs_begin_frames) {
745 begin_frame_observer_proxy_.SetNeedsBeginFrames(needs_begin_frames);
748 void RenderWidgetHostViewAura::SendBeginFrame(const cc::BeginFrameArgs& args) {
749 delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval);
750 host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
753 void RenderWidgetHostViewAura::SetKeyboardFocus() {
754 #if defined(OS_WIN)
755 if (CanFocus()) {
756 aura::WindowTreeHost* host = window_->GetHost();
757 if (host)
758 ::SetFocus(host->GetAcceleratedWidget());
760 #endif
761 if (host_ && set_focus_on_mouse_down_) {
762 set_focus_on_mouse_down_ = false;
763 host_->Focus();
767 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
768 if (!host_->IsRenderView())
769 return NULL;
770 RenderViewHost* rvh = RenderViewHost::From(host_);
771 FrameTreeNode* focused_frame =
772 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
773 if (!focused_frame)
774 return NULL;
776 return focused_frame->current_frame_host();
779 bool RenderWidgetHostViewAura::CanRendererHandleEvent(
780 const ui::MouseEvent* event,
781 bool mouse_locked,
782 bool selection_popup) {
783 #if defined(OS_WIN)
784 bool showing_context_menu = showing_context_menu_;
785 showing_context_menu_ = false;
786 #endif
788 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
789 return false;
791 if ((mouse_locked || selection_popup) &&
792 (event->type() == ui::ET_MOUSE_EXITED))
793 return false;
795 #if defined(OS_WIN)
796 // Don't forward the mouse leave message which is received when the context
797 // menu is displayed by the page. This confuses the page and causes state
798 // changes.
799 if (showing_context_menu) {
800 if (event->type() == ui::ET_MOUSE_EXITED)
801 return false;
803 // Renderer cannot handle WM_XBUTTON or NC events.
804 switch (event->native_event().message) {
805 case WM_XBUTTONDOWN:
806 case WM_XBUTTONUP:
807 case WM_XBUTTONDBLCLK:
808 case WM_NCMOUSELEAVE:
809 case WM_NCMOUSEMOVE:
810 case WM_NCLBUTTONDOWN:
811 case WM_NCLBUTTONUP:
812 case WM_NCLBUTTONDBLCLK:
813 case WM_NCRBUTTONDOWN:
814 case WM_NCRBUTTONUP:
815 case WM_NCRBUTTONDBLCLK:
816 case WM_NCMBUTTONDOWN:
817 case WM_NCMBUTTONUP:
818 case WM_NCMBUTTONDBLCLK:
819 case WM_NCXBUTTONDOWN:
820 case WM_NCXBUTTONUP:
821 case WM_NCXBUTTONDBLCLK:
822 return false;
823 default:
824 break;
826 #elif defined(USE_X11)
827 // Renderer only supports standard mouse buttons, so ignore programmable
828 // buttons.
829 switch (event->type()) {
830 case ui::ET_MOUSE_PRESSED:
831 case ui::ET_MOUSE_RELEASED: {
832 const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
833 ui::EF_MIDDLE_MOUSE_BUTTON |
834 ui::EF_RIGHT_MOUSE_BUTTON;
835 return (event->flags() & kAllowedButtons) != 0;
837 default:
838 break;
840 #endif
841 return true;
844 void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
845 SnapToPhysicalPixelBoundary();
846 #if defined(OS_WIN)
847 if (legacy_render_widget_host_HWND_) {
848 legacy_render_widget_host_HWND_->SetBounds(
849 window_->GetBoundsInRootWindow());
851 #endif
852 if (!in_shutdown_)
853 host_->SendScreenRects();
856 void RenderWidgetHostViewAura::ParentHierarchyChanged() {
857 ancestor_window_observer_.reset(new WindowAncestorObserver(this));
858 // Snap when we receive a hierarchy changed. http://crbug.com/388908.
859 HandleParentBoundsChanged();
862 void RenderWidgetHostViewAura::MovePluginWindows(
863 const std::vector<WebPluginGeometry>& plugin_window_moves) {
864 #if defined(OS_WIN)
865 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
866 // over the browser UI.
867 if (!window_->GetRootWindow()) {
868 DCHECK(plugin_window_moves.empty());
869 return;
871 HWND parent = window_->GetHost()->GetAcceleratedWidget();
872 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
873 std::vector<WebPluginGeometry> moves = plugin_window_moves;
875 gfx::Rect view_port(view_bounds.size());
877 for (size_t i = 0; i < moves.size(); ++i) {
878 gfx::Rect clip(moves[i].clip_rect);
879 gfx::Vector2d view_port_offset(
880 moves[i].window_rect.OffsetFromOrigin());
881 clip.Offset(view_port_offset);
882 clip.Intersect(view_port);
883 clip.Offset(-view_port_offset);
884 moves[i].clip_rect = clip;
886 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
888 plugin_window_moves_[moves[i].window] = moves[i];
890 // constrained_rects_ are relative to the root window. We want to convert
891 // them to be relative to the plugin window.
892 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
893 gfx::Rect offset_cutout = constrained_rects_[j];
894 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
895 moves[i].cutout_rects.push_back(offset_cutout);
899 MovePluginWindowsHelper(parent, moves);
901 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
902 // |this|.
903 for (size_t i = 0; i < moves.size(); ++i) {
904 HWND window = moves[i].window;
905 if (GetParent(window) != parent) {
906 window = GetParent(window);
908 if (!GetProp(window, kWidgetOwnerProperty))
909 SetProp(window, kWidgetOwnerProperty, this);
911 #endif // defined(OS_WIN)
914 void RenderWidgetHostViewAura::Focus() {
915 // Make sure we have a FocusClient before attempting to Focus(). In some
916 // situations we may not yet be in a valid Window hierarchy (such as reloading
917 // after out of memory discarded the tab).
918 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
919 if (client)
920 window_->Focus();
923 bool RenderWidgetHostViewAura::HasFocus() const {
924 return window_->HasFocus();
927 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
928 return delegated_frame_host_->CanCopyToBitmap();
931 bool RenderWidgetHostViewAura::IsShowing() {
932 return window_->IsVisible();
935 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
936 return window_->GetBoundsInScreen();
939 void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
940 RenderWidgetHostViewBase::SetBackgroundColor(color);
941 bool opaque = GetBackgroundOpaque();
942 host_->SetBackgroundOpaque(opaque);
943 window_->layer()->SetFillsBoundsOpaquely(opaque);
944 window_->layer()->SetColor(color);
947 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
948 gfx::Rect requested_rect(GetRequestedRendererSize());
949 requested_rect.Inset(insets_);
950 return requested_rect.size();
953 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
954 if (insets != insets_) {
955 insets_ = insets;
956 host_->WasResized();
960 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
961 current_cursor_ = cursor;
962 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
963 GetDisplayNearestWindow(window_);
964 current_cursor_.SetDisplayInfo(display);
965 UpdateCursorIfOverSelf();
968 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
969 is_loading_ = is_loading;
970 UpdateCursorIfOverSelf();
973 void RenderWidgetHostViewAura::TextInputStateChanged(
974 const ViewHostMsg_TextInputState_Params& params) {
975 if (text_input_type_ != params.type ||
976 text_input_mode_ != params.mode ||
977 can_compose_inline_ != params.can_compose_inline ||
978 text_input_flags_ != params.flags) {
979 text_input_type_ = params.type;
980 text_input_mode_ = params.mode;
981 can_compose_inline_ = params.can_compose_inline;
982 text_input_flags_ = params.flags;
983 if (GetInputMethod())
984 GetInputMethod()->OnTextInputTypeChanged(this);
986 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
987 if (GetInputMethod())
988 GetInputMethod()->ShowImeIfNeeded();
992 void RenderWidgetHostViewAura::ImeCancelComposition() {
993 if (GetInputMethod())
994 GetInputMethod()->CancelComposition(this);
995 has_composition_text_ = false;
998 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
999 const gfx::Range& range,
1000 const std::vector<gfx::Rect>& character_bounds) {
1001 composition_character_bounds_ = character_bounds;
1004 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
1005 int error_code) {
1006 UpdateCursorIfOverSelf();
1007 Destroy();
1010 void RenderWidgetHostViewAura::Destroy() {
1011 // Beware, this function is not called on all destruction paths. It will
1012 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1013 // destruction/cleanup code should happen there, not here.
1014 in_shutdown_ = true;
1015 delete window_;
1018 void RenderWidgetHostViewAura::SetTooltipText(
1019 const base::string16& tooltip_text) {
1020 tooltip_ = tooltip_text;
1021 aura::Window* root_window = window_->GetRootWindow();
1022 aura::client::TooltipClient* tooltip_client =
1023 aura::client::GetTooltipClient(root_window);
1024 if (tooltip_client) {
1025 tooltip_client->UpdateTooltip(window_);
1026 // Content tooltips should be visible indefinitely.
1027 tooltip_client->SetTooltipShownTimeout(window_, 0);
1031 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1032 size_t offset,
1033 const gfx::Range& range) {
1034 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1036 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1037 if (text.empty() || range.is_empty())
1038 return;
1039 size_t pos = range.GetMin() - offset;
1040 size_t n = range.length();
1042 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
1043 if (pos >= text.length()) {
1044 NOTREACHED() << "The text can not cover range.";
1045 return;
1048 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1049 ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
1050 clipboard_writer.WriteText(text.substr(pos, n));
1051 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1054 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
1055 return delegated_frame_host_->GetRequestedRendererSize();
1058 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1059 const ViewHostMsg_SelectionBounds_Params& params) {
1060 ui::SelectionBound anchor_bound, focus_bound;
1061 anchor_bound.SetEdge(params.anchor_rect.origin(),
1062 params.anchor_rect.bottom_left());
1063 focus_bound.SetEdge(params.focus_rect.origin(),
1064 params.focus_rect.bottom_left());
1066 if (params.anchor_rect == params.focus_rect) {
1067 anchor_bound.set_type(ui::SelectionBound::CENTER);
1068 focus_bound.set_type(ui::SelectionBound::CENTER);
1069 } else {
1070 // Whether text is LTR at the anchor handle.
1071 bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight;
1072 // Whether text is LTR at the focus handle.
1073 bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight;
1075 if ((params.is_anchor_first && anchor_LTR) ||
1076 (!params.is_anchor_first && !anchor_LTR)) {
1077 anchor_bound.set_type(ui::SelectionBound::LEFT);
1078 } else {
1079 anchor_bound.set_type(ui::SelectionBound::RIGHT);
1081 if ((params.is_anchor_first && focus_LTR) ||
1082 (!params.is_anchor_first && !focus_LTR)) {
1083 focus_bound.set_type(ui::SelectionBound::RIGHT);
1084 } else {
1085 focus_bound.set_type(ui::SelectionBound::LEFT);
1089 if (anchor_bound == selection_anchor_ && focus_bound == selection_focus_)
1090 return;
1092 selection_anchor_ = anchor_bound;
1093 selection_focus_ = focus_bound;
1094 if (GetInputMethod())
1095 GetInputMethod()->OnCaretBoundsChanged(this);
1098 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1099 const gfx::Rect& src_subrect,
1100 const gfx::Size& dst_size,
1101 ReadbackRequestCallback& callback,
1102 const SkColorType preferred_color_type) {
1103 delegated_frame_host_->CopyFromCompositingSurface(
1104 src_subrect, dst_size, callback, preferred_color_type);
1107 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1108 const gfx::Rect& src_subrect,
1109 const scoped_refptr<media::VideoFrame>& target,
1110 const base::Callback<void(bool)>& callback) {
1111 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
1112 src_subrect, target, callback);
1115 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1116 return delegated_frame_host_->CanCopyToVideoFrame();
1119 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1120 return delegated_frame_host_->CanSubscribeFrame();
1123 void RenderWidgetHostViewAura::BeginFrameSubscription(
1124 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1125 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
1128 void RenderWidgetHostViewAura::EndFrameSubscription() {
1129 delegated_frame_host_->EndFrameSubscription();
1132 #if defined(OS_WIN)
1133 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1134 return (legacy_render_widget_host_HWND_ != NULL);
1137 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1138 const std::vector<gfx::Rect>& rects) {
1139 // Check this before setting constrained_rects_, so that next time they're set
1140 // and we have a root window we don't early return.
1141 if (!window_->GetHost())
1142 return;
1144 if (rects == constrained_rects_)
1145 return;
1147 constrained_rects_ = rects;
1149 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1150 CutoutRectsParams params;
1151 params.widget = this;
1152 params.cutout_rects = constrained_rects_;
1153 params.geometry = &plugin_window_moves_;
1154 LPARAM lparam = reinterpret_cast<LPARAM>(&params);
1155 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1158 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1159 // Clip the cursor if chrome is running on regular desktop.
1160 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1161 RECT window_rect =
1162 gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
1163 ::ClipCursor(&window_rect);
1167 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1168 legacy_render_widget_host_HWND_ = NULL;
1169 legacy_window_destroyed_ = true;
1171 #endif
1173 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1174 uint32 output_surface_id,
1175 scoped_ptr<cc::CompositorFrame> frame) {
1176 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1178 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1179 if (!frame->delegated_frame_data)
1180 return;
1181 delegated_frame_host_->SwapDelegatedFrame(
1182 output_surface_id, frame->delegated_frame_data.Pass(),
1183 frame->metadata.device_scale_factor, frame->metadata.latency_info,
1184 &frame->metadata.satisfies_sequences);
1185 SelectionUpdated(frame->metadata.selection.is_editable,
1186 frame->metadata.selection.is_empty_text_form_control,
1187 ConvertSelectionBound(frame->metadata.selection.start),
1188 ConvertSelectionBound(frame->metadata.selection.end));
1191 void RenderWidgetHostViewAura::ClearCompositorFrame() {
1192 delegated_frame_host_->ClearDelegatedFrame();
1195 void RenderWidgetHostViewAura::DidStopFlinging() {
1196 selection_controller_client_->OnScrollCompleted();
1199 #if defined(OS_WIN)
1200 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1201 gfx::NativeViewAccessible accessible_parent) {
1204 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1205 const {
1206 if (legacy_render_widget_host_HWND_) {
1207 return reinterpret_cast<gfx::NativeViewId>(
1208 legacy_render_widget_host_HWND_->hwnd());
1210 return NULL;
1212 #endif
1214 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1215 const gfx::Size& desired_size) {
1216 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1217 // matter what is returned here as GetBackingStore is the only caller of this
1218 // method. TODO(jbates) implement this if other Aura code needs it.
1219 return false;
1222 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1223 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1226 bool RenderWidgetHostViewAura::GetScreenColorProfile(
1227 std::vector<char>* color_profile) {
1228 DCHECK(color_profile->empty());
1229 gfx::Rect bounds(window_->GetToplevelWindow()->GetBoundsInScreen());
1230 return gfx::GetDisplayColorProfile(bounds, color_profile);
1233 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1234 aura::Window* top_level = window_->GetToplevelWindow();
1235 gfx::Rect bounds(top_level->GetBoundsInScreen());
1237 #if defined(OS_WIN)
1238 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1239 // remove the legacy hwnd, so a better fix will need to be decided when that
1240 // happens.
1241 if (UsesNativeWindowFrame()) {
1242 // aura::Window doesn't take into account non-client area of native windows
1243 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1244 aura::WindowTreeHost* host = top_level->GetHost();
1245 if (!host)
1246 return top_level->GetBoundsInScreen();
1247 RECT window_rect = {0};
1248 HWND hwnd = host->GetAcceleratedWidget();
1249 ::GetWindowRect(hwnd, &window_rect);
1250 bounds = gfx::Rect(window_rect);
1252 // Maximized windows are outdented from the work area by the frame thickness
1253 // even though this "frame" is not painted. This confuses code (and people)
1254 // that think of a maximized window as corresponding exactly to the work
1255 // area. Correct for this by subtracting the frame thickness back off.
1256 if (::IsZoomed(hwnd)) {
1257 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
1258 GetSystemMetrics(SM_CYSIZEFRAME));
1260 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1261 GetSystemMetrics(SM_CXPADDEDBORDER));
1265 bounds = gfx::win::ScreenToDIPRect(bounds);
1266 #endif
1268 return bounds;
1271 void RenderWidgetHostViewAura::WheelEventAck(
1272 const blink::WebMouseWheelEvent& event,
1273 InputEventAckState ack_result) {
1274 if (overscroll_controller_) {
1275 overscroll_controller_->ReceivedEventACK(
1276 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1280 void RenderWidgetHostViewAura::GestureEventAck(
1281 const blink::WebGestureEvent& event,
1282 InputEventAckState ack_result) {
1283 if (overscroll_controller_) {
1284 overscroll_controller_->ReceivedEventACK(
1285 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1289 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1290 const TouchEventWithLatencyInfo& touch,
1291 InputEventAckState ack_result) {
1292 ScopedVector<ui::TouchEvent> events;
1293 aura::WindowTreeHost* host = window_->GetHost();
1294 // |host| is NULL during tests.
1295 if (!host)
1296 return;
1298 ui::EventResult result = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
1299 ? ui::ER_HANDLED
1300 : ui::ER_UNHANDLED;
1302 blink::WebTouchPoint::State required_state;
1303 switch (touch.event.type) {
1304 case blink::WebInputEvent::TouchStart:
1305 required_state = blink::WebTouchPoint::StatePressed;
1306 break;
1307 case blink::WebInputEvent::TouchEnd:
1308 required_state = blink::WebTouchPoint::StateReleased;
1309 break;
1310 case blink::WebInputEvent::TouchMove:
1311 required_state = blink::WebTouchPoint::StateMoved;
1312 break;
1313 case blink::WebInputEvent::TouchCancel:
1314 required_state = blink::WebTouchPoint::StateCancelled;
1315 break;
1316 default:
1317 required_state = blink::WebTouchPoint::StateUndefined;
1318 NOTREACHED();
1319 break;
1322 // Only send acks for one changed touch point.
1323 bool sent_ack = false;
1324 for (size_t i = 0; i < touch.event.touchesLength; ++i) {
1325 if (touch.event.touches[i].state == required_state) {
1326 DCHECK(!sent_ack);
1327 host->dispatcher()->ProcessedTouchEvent(touch.event.uniqueTouchEventId,
1328 window_, result);
1329 sent_ack = true;
1334 scoped_ptr<SyntheticGestureTarget>
1335 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1336 return scoped_ptr<SyntheticGestureTarget>(
1337 new SyntheticGestureTargetAura(host_));
1340 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
1341 const blink::WebInputEvent& input_event) {
1342 bool consumed = false;
1343 if (input_event.type == WebInputEvent::GestureFlingStart) {
1344 const WebGestureEvent& gesture_event =
1345 static_cast<const WebGestureEvent&>(input_event);
1346 // Zero-velocity touchpad flings are an Aura-specific signal that the
1347 // touchpad scroll has ended, and should not be forwarded to the renderer.
1348 if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
1349 !gesture_event.data.flingStart.velocityX &&
1350 !gesture_event.data.flingStart.velocityY) {
1351 consumed = true;
1355 if (overscroll_controller_)
1356 consumed |= overscroll_controller_->WillHandleEvent(input_event);
1358 // Touch events should always propagate to the renderer.
1359 if (WebTouchEvent::isTouchEventType(input_event.type))
1360 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1362 // Reporting consumed for a fling suggests that there's now an *active* fling
1363 // that requires both animation and a fling-end notification. However, the
1364 // OverscrollController consumes a fling to stop its propagation; it doesn't
1365 // actually tick a fling animation. Report no consumer to convey this.
1366 if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart)
1367 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
1369 return consumed ? INPUT_EVENT_ACK_STATE_CONSUMED
1370 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1373 BrowserAccessibilityManager*
1374 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1375 BrowserAccessibilityDelegate* delegate) {
1376 BrowserAccessibilityManager* manager = NULL;
1377 #if defined(OS_WIN)
1378 manager = new BrowserAccessibilityManagerWin(
1379 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
1380 #else
1381 manager = BrowserAccessibilityManager::Create(
1382 BrowserAccessibilityManager::GetEmptyDocument(), delegate);
1383 #endif
1384 return manager;
1387 gfx::AcceleratedWidget
1388 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1389 #if defined(OS_WIN)
1390 if (legacy_render_widget_host_HWND_)
1391 return legacy_render_widget_host_HWND_->hwnd();
1392 #endif
1393 return gfx::kNullAcceleratedWidget;
1396 gfx::NativeViewAccessible
1397 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1398 #if defined(OS_WIN)
1399 if (legacy_render_widget_host_HWND_)
1400 return legacy_render_widget_host_HWND_->window_accessible();
1401 #endif
1402 return NULL;
1405 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1406 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1409 void RenderWidgetHostViewAura::ShowDisambiguationPopup(
1410 const gfx::Rect& rect_pixels,
1411 const SkBitmap& zoomed_bitmap) {
1412 RenderViewHostDelegate* delegate = NULL;
1413 if (host_->IsRenderView())
1414 delegate = RenderViewHost::From(host_)->GetDelegate();
1415 // Suppress the link disambiguation popup if the virtual keyboard is currently
1416 // requested, as it doesn't interact well with the keyboard.
1417 if (delegate && delegate->IsVirtualKeyboardRequested())
1418 return;
1420 // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
1421 // by scaling it by the inverse of the device scale factor.
1422 gfx::RectF screen_target_rect_f(rect_pixels);
1423 screen_target_rect_f.Scale(1.0f / current_device_scale_factor_);
1424 disambiguation_target_rect_ = gfx::ToEnclosingRect(screen_target_rect_f);
1426 float scale = static_cast<float>(zoomed_bitmap.width()) /
1427 static_cast<float>(rect_pixels.width());
1428 gfx::Size zoomed_size(gfx::ToCeiledSize(
1429 gfx::ScaleSize(disambiguation_target_rect_.size(), scale)));
1431 // Save of a copy of the |last_scroll_offset_| for comparison when the copy
1432 // callback fires, to ensure that we haven't scrolled.
1433 disambiguation_scroll_offset_ = last_scroll_offset_;
1435 CopyFromCompositingSurface(
1436 disambiguation_target_rect_,
1437 zoomed_size,
1438 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
1439 weak_ptr_factory_.GetWeakPtr()),
1440 kN32_SkColorType);
1443 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1444 const SkBitmap& result,
1445 ReadbackResponse response) {
1446 if ((response != READBACK_SUCCESS) ||
1447 disambiguation_scroll_offset_ != last_scroll_offset_)
1448 return;
1450 // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
1451 // actually show the disambiguation popup.
1452 RenderViewHostDelegate* delegate = NULL;
1453 if (host_->IsRenderView())
1454 delegate = RenderViewHost::From(host_)->GetDelegate();
1455 RenderViewHostDelegateView* delegate_view = NULL;
1456 if (delegate) {
1457 delegate_view = delegate->GetDelegateView();
1458 if (delegate->IsVirtualKeyboardRequested())
1459 return;
1461 if (delegate_view) {
1462 delegate_view->ShowDisambiguationPopup(
1463 disambiguation_target_rect_,
1464 result,
1465 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture,
1466 weak_ptr_factory_.GetWeakPtr()),
1467 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse,
1468 weak_ptr_factory_.GetWeakPtr()));
1472 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1473 RenderViewHostDelegate* delegate = NULL;
1474 if (host_->IsRenderView())
1475 delegate = RenderViewHost::From(host_)->GetDelegate();
1476 RenderViewHostDelegateView* delegate_view = NULL;
1477 if (delegate)
1478 delegate_view = delegate->GetDelegateView();
1479 if (delegate_view)
1480 delegate_view->HideDisambiguationPopup();
1483 void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
1484 ui::GestureEvent* event) {
1485 blink::WebGestureEvent web_gesture = content::MakeWebGestureEvent(*event);
1486 // If we fail to make a WebGestureEvent that is a Tap from the provided event,
1487 // don't forward it to Blink.
1488 if (web_gesture.type < blink::WebInputEvent::Type::GestureTap ||
1489 web_gesture.type > blink::WebInputEvent::Type::GestureTapCancel)
1490 return;
1492 host_->ForwardGestureEvent(web_gesture);
1495 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1496 ui::MouseEvent* event) {
1497 blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(*event);
1498 host_->ForwardMouseEvent(web_mouse);
1501 bool RenderWidgetHostViewAura::LockMouse() {
1502 aura::Window* root_window = window_->GetRootWindow();
1503 if (!root_window)
1504 return false;
1506 if (mouse_locked_)
1507 return true;
1509 mouse_locked_ = true;
1510 #if !defined(OS_WIN)
1511 window_->SetCapture();
1512 #else
1513 UpdateMouseLockRegion();
1514 #endif
1515 aura::client::CursorClient* cursor_client =
1516 aura::client::GetCursorClient(root_window);
1517 if (cursor_client) {
1518 cursor_client->HideCursor();
1519 cursor_client->LockCursor();
1522 if (ShouldMoveToCenter()) {
1523 synthetic_move_sent_ = true;
1524 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1526 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1527 return true;
1530 void RenderWidgetHostViewAura::UnlockMouse() {
1531 tooltip_disabler_.reset();
1533 aura::Window* root_window = window_->GetRootWindow();
1534 if (!mouse_locked_ || !root_window)
1535 return;
1537 mouse_locked_ = false;
1539 if (window_->HasCapture())
1540 window_->ReleaseCapture();
1542 #if defined(OS_WIN)
1543 ::ClipCursor(NULL);
1544 #endif
1546 window_->MoveCursorTo(unlocked_mouse_position_);
1547 aura::client::CursorClient* cursor_client =
1548 aura::client::GetCursorClient(root_window);
1549 if (cursor_client) {
1550 cursor_client->UnlockCursor();
1551 cursor_client->ShowCursor();
1554 host_->LostMouseLock();
1557 ////////////////////////////////////////////////////////////////////////////////
1558 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1559 void RenderWidgetHostViewAura::SetCompositionText(
1560 const ui::CompositionText& composition) {
1561 if (!host_)
1562 return;
1564 // TODO(suzhe): convert both renderer_host and renderer to use
1565 // ui::CompositionText.
1566 std::vector<blink::WebCompositionUnderline> underlines;
1567 underlines.reserve(composition.underlines.size());
1568 for (std::vector<ui::CompositionUnderline>::const_iterator it =
1569 composition.underlines.begin();
1570 it != composition.underlines.end(); ++it) {
1571 underlines.push_back(
1572 blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset),
1573 static_cast<unsigned>(it->end_offset),
1574 it->color,
1575 it->thick,
1576 it->background_color));
1579 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1580 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1581 host_->ImeSetComposition(composition.text, underlines,
1582 composition.selection.end(),
1583 composition.selection.end());
1585 has_composition_text_ = !composition.text.empty();
1588 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1589 if (host_ && has_composition_text_) {
1590 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1591 false);
1593 has_composition_text_ = false;
1596 void RenderWidgetHostViewAura::ClearCompositionText() {
1597 if (host_ && has_composition_text_)
1598 host_->ImeCancelComposition();
1599 has_composition_text_ = false;
1602 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1603 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1604 if (host_)
1605 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1606 has_composition_text_ = false;
1609 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
1610 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1611 popup_child_host_view_->InsertChar(ch, flags);
1612 return;
1615 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1616 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
1617 double now = ui::EventTimeForNow().InSecondsF();
1618 // Send a blink::WebInputEvent::Char event to |host_|.
1619 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
1620 true /* is_char */,
1622 flags,
1623 now);
1624 ForwardKeyboardEvent(webkit_event);
1628 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1629 return text_input_type_;
1632 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1633 return text_input_mode_;
1636 int RenderWidgetHostViewAura::GetTextInputFlags() const {
1637 return text_input_flags_;
1640 bool RenderWidgetHostViewAura::CanComposeInline() const {
1641 return can_compose_inline_;
1644 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
1645 const gfx::Rect& rect) const {
1646 gfx::Point origin = rect.origin();
1647 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1649 aura::Window* root_window = window_->GetRootWindow();
1650 if (!root_window)
1651 return rect;
1652 aura::client::ScreenPositionClient* screen_position_client =
1653 aura::client::GetScreenPositionClient(root_window);
1654 if (!screen_position_client)
1655 return rect;
1656 screen_position_client->ConvertPointToScreen(window_, &origin);
1657 screen_position_client->ConvertPointToScreen(window_, &end);
1658 return gfx::Rect(origin.x(),
1659 origin.y(),
1660 end.x() - origin.x(),
1661 end.y() - origin.y());
1664 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
1665 const gfx::Rect& rect) const {
1666 gfx::Point origin = rect.origin();
1667 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1669 aura::Window* root_window = window_->GetRootWindow();
1670 if (root_window) {
1671 aura::client::ScreenPositionClient* screen_position_client =
1672 aura::client::GetScreenPositionClient(root_window);
1673 screen_position_client->ConvertPointFromScreen(window_, &origin);
1674 screen_position_client->ConvertPointFromScreen(window_, &end);
1675 return gfx::Rect(origin.x(),
1676 origin.y(),
1677 end.x() - origin.x(),
1678 end.y() - origin.y());
1681 return rect;
1684 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1685 return ConvertRectToScreen(
1686 ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_));
1689 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1690 uint32 index,
1691 gfx::Rect* rect) const {
1692 DCHECK(rect);
1693 if (index >= composition_character_bounds_.size())
1694 return false;
1695 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1696 return true;
1699 bool RenderWidgetHostViewAura::HasCompositionText() const {
1700 return has_composition_text_;
1703 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
1704 range->set_start(selection_text_offset_);
1705 range->set_end(selection_text_offset_ + selection_text_.length());
1706 return true;
1709 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1710 gfx::Range* range) const {
1711 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1712 NOTIMPLEMENTED();
1713 return false;
1716 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1717 range->set_start(selection_range_.start());
1718 range->set_end(selection_range_.end());
1719 return true;
1722 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1723 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1724 NOTIMPLEMENTED();
1725 return false;
1728 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1729 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1730 NOTIMPLEMENTED();
1731 return false;
1734 bool RenderWidgetHostViewAura::GetTextFromRange(
1735 const gfx::Range& range,
1736 base::string16* text) const {
1737 gfx::Range selection_text_range(selection_text_offset_,
1738 selection_text_offset_ + selection_text_.length());
1740 if (!selection_text_range.Contains(range)) {
1741 text->clear();
1742 return false;
1744 if (selection_text_range.EqualsIgnoringDirection(range)) {
1745 // Avoid calling substr whose performance is low.
1746 *text = selection_text_;
1747 } else {
1748 *text = selection_text_.substr(
1749 range.GetMin() - selection_text_offset_,
1750 range.length());
1752 return true;
1755 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1756 if (!host_)
1757 return;
1759 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1760 // TextEvent.
1763 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1764 base::i18n::TextDirection direction) {
1765 if (!host_)
1766 return false;
1767 host_->UpdateTextDirection(
1768 direction == base::i18n::RIGHT_TO_LEFT ?
1769 blink::WebTextDirectionRightToLeft :
1770 blink::WebTextDirectionLeftToRight);
1771 host_->NotifyTextDirection();
1772 return true;
1775 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1776 size_t before, size_t after) {
1777 RenderFrameHostImpl* rfh = GetFocusedFrame();
1778 if (rfh)
1779 rfh->ExtendSelectionAndDelete(before, after);
1782 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1783 gfx::Rect intersected_rect(
1784 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1786 if (intersected_rect.IsEmpty())
1787 return;
1789 host_->ScrollFocusedEditableNodeIntoRect(
1790 ConvertRectFromScreen(intersected_rect));
1793 bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id) {
1794 return false;
1797 void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id) {
1800 ////////////////////////////////////////////////////////////////////////////////
1801 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1803 void RenderWidgetHostViewAura::OnDisplayAdded(
1804 const gfx::Display& new_display) {
1807 void RenderWidgetHostViewAura::OnDisplayRemoved(
1808 const gfx::Display& old_display) {
1811 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
1812 const gfx::Display& display, uint32_t metrics) {
1813 // The screen info should be updated regardless of the metric change.
1814 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
1815 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
1816 UpdateScreenInfo(window_);
1817 current_cursor_.SetDisplayInfo(display);
1818 UpdateCursorIfOverSelf();
1822 ////////////////////////////////////////////////////////////////////////////////
1823 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1825 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1826 return gfx::Size();
1829 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
1830 return gfx::Size();
1833 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1834 const gfx::Rect& new_bounds) {
1835 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
1836 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1837 // WebContentsViewAura since changes to the Window's bounds need to be
1838 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1839 // SetBounds() itself. No matter how we got here, any redundant calls are
1840 // harmless.
1841 SetSize(new_bounds.size());
1843 if (GetInputMethod())
1844 GetInputMethod()->OnCaretBoundsChanged(this);
1847 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1848 if (mouse_locked_)
1849 return ui::kCursorNone;
1850 return current_cursor_.GetNativeCursor();
1853 int RenderWidgetHostViewAura::GetNonClientComponent(
1854 const gfx::Point& point) const {
1855 return HTCLIENT;
1858 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1859 aura::Window* child,
1860 const gfx::Point& location) {
1861 return true;
1864 bool RenderWidgetHostViewAura::CanFocus() {
1865 return popup_type_ == blink::WebPopupTypeNone;
1868 void RenderWidgetHostViewAura::OnCaptureLost() {
1869 host_->LostCapture();
1872 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
1873 NOTREACHED();
1876 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1877 float device_scale_factor) {
1878 if (!host_ || !window_->GetRootWindow())
1879 return;
1881 UpdateScreenInfo(window_);
1883 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1884 GetDisplayNearestWindow(window_);
1885 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
1886 current_cursor_.SetDisplayInfo(display);
1887 SnapToPhysicalPixelBoundary();
1890 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
1891 #if defined(OS_WIN)
1892 HWND parent = NULL;
1893 // If the tab was hidden and it's closed, host_->is_hidden would have been
1894 // reset to false in RenderWidgetHostImpl::RendererExited.
1895 if (!window_->GetRootWindow() || host_->is_hidden()) {
1896 parent = ui::GetHiddenWindow();
1897 } else {
1898 parent = window_->GetHost()->GetAcceleratedWidget();
1900 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1901 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
1903 // The LegacyRenderWidgetHostHWND instance is destroyed when its window is
1904 // destroyed. Normally we control when that happens via the Destroy call
1905 // in the dtor. However there may be cases where the window is destroyed
1906 // by Windows, i.e. the parent window is destroyed before the
1907 // RenderWidgetHostViewAura instance goes away etc. To avoid that we
1908 // destroy the LegacyRenderWidgetHostHWND instance here.
1909 if (legacy_render_widget_host_HWND_) {
1910 legacy_render_widget_host_HWND_->set_host(NULL);
1911 legacy_render_widget_host_HWND_->Destroy();
1912 // The Destroy call above will delete the LegacyRenderWidgetHostHWND
1913 // instance.
1914 legacy_render_widget_host_HWND_ = NULL;
1916 #endif
1918 // Make sure that the input method no longer references to this object before
1919 // this object is removed from the root window (i.e. this object loses access
1920 // to the input method).
1921 ui::InputMethod* input_method = GetInputMethod();
1922 if (input_method)
1923 input_method->DetachTextInputClient(this);
1925 if (overscroll_controller_)
1926 overscroll_controller_->Reset();
1929 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1930 // Ask the RWH to drop reference to us.
1931 if (!is_guest_view_hack_)
1932 host_->ViewDestroyed();
1934 delete this;
1937 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1940 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1941 return false;
1944 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1947 ////////////////////////////////////////////////////////////////////////////////
1948 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1950 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1951 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1953 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1954 popup_child_host_view_->OnKeyEvent(event);
1955 if (event->handled())
1956 return;
1959 // We need to handle the Escape key for Pepper Flash.
1960 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
1961 // Focus the window we were created from.
1962 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
1963 aura::Window* host = *(host_tracker_->windows().begin());
1964 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
1965 if (client) {
1966 // Calling host->Focus() may delete |this|. We create a local observer
1967 // for that. In that case we exit without further access to any members.
1968 aura::WindowTracker tracker;
1969 aura::Window* window = window_;
1970 tracker.Add(window);
1971 host->Focus();
1972 if (!tracker.Contains(window)) {
1973 event->SetHandled();
1974 return;
1978 Shutdown();
1979 } else {
1980 if (event->key_code() == ui::VKEY_RETURN) {
1981 // Do not forward return key release events if no press event was handled.
1982 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
1983 return;
1984 // Accept return key character events between press and release events.
1985 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
1988 // We don't have to communicate with an input method here.
1989 NativeWebKeyboardEvent webkit_event(*event);
1990 ForwardKeyboardEvent(webkit_event);
1992 event->SetHandled();
1995 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
1996 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
1998 if (mouse_locked_) {
1999 aura::client::CursorClient* cursor_client =
2000 aura::client::GetCursorClient(window_->GetRootWindow());
2001 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
2003 if (event->type() == ui::ET_MOUSEWHEEL) {
2004 blink::WebMouseWheelEvent mouse_wheel_event =
2005 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2006 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2007 host_->ForwardWheelEvent(mouse_wheel_event);
2008 return;
2011 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
2013 // If we receive non client mouse messages while we are in the locked state
2014 // it probably means that the mouse left the borders of our window and
2015 // needs to be moved back to the center.
2016 if (event->flags() & ui::EF_IS_NON_CLIENT) {
2017 synthetic_move_sent_ = true;
2018 window_->MoveCursorTo(center);
2019 return;
2022 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2024 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
2025 event->type() == ui::ET_MOUSE_DRAGGED) &&
2026 mouse_event.x == center.x() && mouse_event.y == center.y();
2028 // For fractional scale factors, the conversion from pixels to dip and
2029 // vice versa could result in off by 1 or 2 errors which hurts us because
2030 // we want to avoid sending the artificial move to center event to the
2031 // renderer. Sending the move to center to the renderer cause the cursor
2032 // to bounce around the center of the screen leading to the lock operation
2033 // not working correctly.
2034 // Workaround is to treat a mouse move or drag event off by at most 2 px
2035 // from the center as a move to center event.
2036 if (synthetic_move_sent_ &&
2037 IsFractionalScaleFactor(current_device_scale_factor_)) {
2038 if (event->type() == ui::ET_MOUSE_MOVED ||
2039 event->type() == ui::ET_MOUSE_DRAGGED) {
2040 if ((abs(mouse_event.x - center.x()) <= 2) &&
2041 (abs(mouse_event.y - center.y()) <= 2)) {
2042 is_move_to_center_event = true;
2047 ModifyEventMovementAndCoords(&mouse_event);
2049 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2050 if (should_not_forward) {
2051 synthetic_move_sent_ = false;
2052 } else {
2053 // Check if the mouse has reached the border and needs to be centered.
2054 if (ShouldMoveToCenter()) {
2055 synthetic_move_sent_ = true;
2056 window_->MoveCursorTo(center);
2058 bool is_selection_popup = popup_child_host_view_ &&
2059 popup_child_host_view_->NeedsInputGrab();
2060 // Forward event to renderer.
2061 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2062 !(event->flags() & ui::EF_FROM_TOUCH)) {
2063 host_->ForwardMouseEvent(mouse_event);
2064 // Ensure that we get keyboard focus on mouse down as a plugin window
2065 // may have grabbed keyboard focus.
2066 if (event->type() == ui::ET_MOUSE_PRESSED)
2067 SetKeyboardFocus();
2070 return;
2073 // As the overscroll is handled during scroll events from the trackpad, the
2074 // RWHVA window is transformed by the overscroll controller. This transform
2075 // triggers a synthetic mouse-move event to be generated (by the aura
2076 // RootWindow). But this event interferes with the overscroll gesture. So,
2077 // ignore such synthetic mouse-move events if an overscroll gesture is in
2078 // progress.
2079 if (overscroll_controller_ &&
2080 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE &&
2081 event->flags() & ui::EF_IS_SYNTHESIZED &&
2082 (event->type() == ui::ET_MOUSE_ENTERED ||
2083 event->type() == ui::ET_MOUSE_EXITED ||
2084 event->type() == ui::ET_MOUSE_MOVED)) {
2085 event->StopPropagation();
2086 return;
2089 if (event->type() == ui::ET_MOUSEWHEEL) {
2090 #if defined(OS_WIN)
2091 // We get mouse wheel/scroll messages even if we are not in the foreground.
2092 // So here we check if we have any owned popup windows in the foreground and
2093 // dismiss them.
2094 aura::WindowTreeHost* host = window_->GetHost();
2095 if (host) {
2096 HWND parent = host->GetAcceleratedWidget();
2097 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2098 EnumThreadWindows(GetCurrentThreadId(),
2099 DismissOwnedPopups,
2100 reinterpret_cast<LPARAM>(toplevel_hwnd));
2102 #endif
2103 // The Disambiguation popup does not parent itself from this window, so we
2104 // manually dismiss it.
2105 HideDisambiguationPopup();
2107 blink::WebMouseWheelEvent mouse_wheel_event =
2108 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2109 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0) {
2110 if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
2111 host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
2112 this, &mouse_wheel_event);
2113 } else {
2114 ProcessMouseWheelEvent(mouse_wheel_event);
2117 } else {
2118 bool is_selection_popup =
2119 popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab();
2120 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2121 !(event->flags() & ui::EF_FROM_TOUCH)) {
2122 // Confirm existing composition text on mouse press, to make sure
2123 // the input caret won't be moved with an ongoing composition text.
2124 if (event->type() == ui::ET_MOUSE_PRESSED)
2125 FinishImeCompositionSession();
2127 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2128 ModifyEventMovementAndCoords(&mouse_event);
2129 if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
2130 host_->delegate()->GetInputEventRouter()->RouteMouseEvent(this,
2131 &mouse_event);
2132 } else {
2133 ProcessMouseEvent(mouse_event);
2136 // Ensure that we get keyboard focus on mouse down as a plugin window may
2137 // have grabbed keyboard focus.
2138 if (event->type() == ui::ET_MOUSE_PRESSED)
2139 SetKeyboardFocus();
2143 switch (event->type()) {
2144 case ui::ET_MOUSE_PRESSED:
2145 window_->SetCapture();
2146 break;
2147 case ui::ET_MOUSE_RELEASED:
2148 if (!NeedsMouseCapture())
2149 window_->ReleaseCapture();
2150 break;
2151 default:
2152 break;
2155 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2156 // note that it might be something other than a WebContentsViewAura instance.
2157 // TODO(pkotwicz): Find a better way of doing this.
2158 // In fullscreen mode which is typically used by flash, don't forward
2159 // the mouse events to the parent. The renderer and the plugin process
2160 // handle these events.
2161 if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
2162 !(event->flags() & ui::EF_FROM_TOUCH)) {
2163 event->ConvertLocationToTarget(window_, window_->parent());
2164 window_->parent()->delegate()->OnMouseEvent(event);
2167 if (!IsXButtonUpEvent(event))
2168 event->SetHandled();
2171 uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
2172 const gfx::Point& point,
2173 gfx::Point* transformed_point) {
2174 cc::SurfaceId id =
2175 delegated_frame_host_->SurfaceIdAtPoint(point, transformed_point);
2176 // It is possible that the renderer has not yet produced a surface, in which
2177 // case we return our current namespace.
2178 if (id.is_null())
2179 return GetSurfaceIdNamespace();
2180 return cc::SurfaceIdAllocator::NamespaceForId(id);
2183 void RenderWidgetHostViewAura::ProcessMouseEvent(
2184 const blink::WebMouseEvent& event) {
2185 host_->ForwardMouseEvent(event);
2188 void RenderWidgetHostViewAura::ProcessMouseWheelEvent(
2189 const blink::WebMouseWheelEvent& event) {
2190 host_->ForwardWheelEvent(event);
2193 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2194 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2196 if (event->type() == ui::ET_SCROLL) {
2197 #if !defined(OS_WIN)
2198 // TODO(ananta)
2199 // Investigate if this is true for Windows 8 Metro ASH as well.
2200 if (event->finger_count() != 2)
2201 return;
2202 #endif
2203 blink::WebGestureEvent gesture_event =
2204 MakeWebGestureEventFlingCancel();
2205 host_->ForwardGestureEvent(gesture_event);
2206 blink::WebMouseWheelEvent mouse_wheel_event =
2207 MakeWebMouseWheelEvent(*event);
2208 host_->ForwardWheelEvent(mouse_wheel_event);
2209 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2210 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2211 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2212 blink::WebGestureEvent gesture_event = MakeWebGestureEvent(*event);
2213 host_->ForwardGestureEvent(gesture_event);
2214 if (event->type() == ui::ET_SCROLL_FLING_START)
2215 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2218 event->SetHandled();
2221 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2222 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2224 bool had_no_pointer = !pointer_state_.GetPointerCount();
2226 // Update the touch event first.
2227 if (!pointer_state_.OnTouch(*event)) {
2228 event->StopPropagation();
2229 return;
2232 blink::WebTouchEvent touch_event;
2233 bool handled = selection_controller_->WillHandleTouchEvent(pointer_state_);
2234 if (handled) {
2235 event->SetHandled();
2236 } else {
2237 touch_event = ui::CreateWebTouchEventFromMotionEvent(
2238 pointer_state_, event->may_cause_scrolling());
2240 pointer_state_.CleanupRemovedTouchPoints(*event);
2242 if (handled)
2243 return;
2245 if (had_no_pointer)
2246 selection_controller_client_->OnTouchDown();
2247 if (!pointer_state_.GetPointerCount())
2248 selection_controller_client_->OnTouchUp();
2250 // It is important to always mark events as being handled asynchronously when
2251 // they are forwarded. This ensures that the current event does not get
2252 // processed by the gesture recognizer before events currently awaiting
2253 // dispatch in the touch queue.
2254 event->DisableSynchronousHandling();
2256 // Set unchanged touch point to StateStationary for touchmove and
2257 // touchcancel to make sure only send one ack per WebTouchEvent.
2258 MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
2259 host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency());
2262 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2263 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2265 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2266 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2267 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
2268 event->SetHandled();
2269 return;
2272 HandleGestureForTouchSelection(event);
2273 if (event->handled())
2274 return;
2276 // Confirm existing composition text on TAP gesture, to make sure the input
2277 // caret won't be moved with an ongoing composition text.
2278 if (event->type() == ui::ET_GESTURE_TAP)
2279 FinishImeCompositionSession();
2281 blink::WebGestureEvent gesture = MakeWebGestureEvent(*event);
2282 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
2283 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2284 // event to stop any in-progress flings.
2285 blink::WebGestureEvent fling_cancel = gesture;
2286 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
2287 fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
2288 host_->ForwardGestureEvent(fling_cancel);
2291 if (gesture.type != blink::WebInputEvent::Undefined) {
2292 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
2294 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
2295 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
2296 event->type() == ui::ET_GESTURE_SCROLL_END) {
2297 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
2298 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
2299 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
2303 // If a gesture is not processed by the webpage, then WebKit processes it
2304 // (e.g. generates synthetic mouse events).
2305 event->SetHandled();
2308 ////////////////////////////////////////////////////////////////////////////////
2309 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2311 bool RenderWidgetHostViewAura::ShouldActivate() const {
2312 aura::WindowTreeHost* host = window_->GetHost();
2313 if (!host)
2314 return true;
2315 const ui::Event* event = host->dispatcher()->current_event();
2316 if (!event)
2317 return true;
2318 return is_fullscreen_;
2321 ////////////////////////////////////////////////////////////////////////////////
2322 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2324 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2325 NotifyRendererOfCursorVisibilityState(is_visible);
2328 ////////////////////////////////////////////////////////////////////////////////
2329 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2331 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2332 aura::Window* lost_focus) {
2333 DCHECK(window_ == gained_focus || window_ == lost_focus);
2334 if (window_ == gained_focus) {
2335 // We need to honor input bypass if the associated tab is does not want
2336 // input. This gives the current focused window a chance to be the text
2337 // input client and handle events.
2338 if (host_->ignore_input_events())
2339 return;
2341 host_->GotFocus();
2342 host_->SetActive(true);
2344 ui::InputMethod* input_method = GetInputMethod();
2345 if (input_method) {
2346 // Ask the system-wide IME to send all TextInputClient messages to |this|
2347 // object.
2348 input_method->SetFocusedTextInputClient(this);
2350 // Often the application can set focus to the view in response to a key
2351 // down. However the following char event shouldn't be sent to the web
2352 // page.
2353 host_->SuppressNextCharEvents();
2356 BrowserAccessibilityManager* manager =
2357 host_->GetRootBrowserAccessibilityManager();
2358 if (manager)
2359 manager->OnWindowFocused();
2360 } else if (window_ == lost_focus) {
2361 host_->SetActive(false);
2362 host_->Blur();
2364 DetachFromInputMethod();
2366 selection_controller_->HideAndDisallowShowingAutomatically();
2368 if (overscroll_controller_)
2369 overscroll_controller_->Cancel();
2371 BrowserAccessibilityManager* manager =
2372 host_->GetRootBrowserAccessibilityManager();
2373 if (manager)
2374 manager->OnWindowBlurred();
2376 // If we lose the focus while fullscreen, close the window; Pepper Flash
2377 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2378 // window if we lose the focus to a window on another display.
2379 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2380 bool focusing_other_display =
2381 gained_focus && screen->GetNumDisplays() > 1 &&
2382 (screen->GetDisplayNearestWindow(window_).id() !=
2383 screen->GetDisplayNearestWindow(gained_focus).id());
2384 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
2385 #if defined(OS_WIN)
2386 // On Windows, if we are switching to a non Aura Window on a different
2387 // screen we should not close the fullscreen window.
2388 if (!gained_focus) {
2389 POINT point = {0};
2390 ::GetCursorPos(&point);
2391 if (screen->GetDisplayNearestWindow(window_).id() !=
2392 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2393 return;
2395 #endif
2396 Shutdown();
2397 return;
2400 // Close the child popup window if we lose focus (e.g. due to a JS alert or
2401 // system modal dialog). This is particularly important if
2402 // |popup_child_host_view_| has mouse capture.
2403 if (popup_child_host_view_)
2404 popup_child_host_view_->Shutdown();
2408 ////////////////////////////////////////////////////////////////////////////////
2409 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2411 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
2412 const gfx::Point& new_origin) {
2413 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2414 "new_origin", new_origin.ToString());
2416 UpdateScreenInfo(window_);
2419 ////////////////////////////////////////////////////////////////////////////////
2420 // RenderWidgetHostViewAura, private:
2422 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2423 selection_controller_.reset();
2424 selection_controller_client_.reset();
2426 if (UseSurfacesEnabled() && host_->delegate() &&
2427 host_->delegate()->GetInputEventRouter()) {
2428 host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
2429 GetSurfaceIdNamespace());
2431 delegated_frame_host_.reset();
2432 window_observer_.reset();
2433 if (window_->GetHost())
2434 window_->GetHost()->RemoveObserver(this);
2435 UnlockMouse();
2436 if (popup_parent_host_view_) {
2437 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
2438 popup_parent_host_view_->popup_child_host_view_ == this);
2439 popup_parent_host_view_->popup_child_host_view_ = NULL;
2441 if (popup_child_host_view_) {
2442 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
2443 popup_child_host_view_->popup_parent_host_view_ == this);
2444 popup_child_host_view_->popup_parent_host_view_ = NULL;
2446 event_filter_for_popup_exit_.reset();
2447 aura::client::SetTooltipText(window_, NULL);
2448 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
2450 // This call is usually no-op since |this| object is already removed from the
2451 // Aura root window and we don't have a way to get an input method object
2452 // associated with the window, but just in case.
2453 DetachFromInputMethod();
2455 #if defined(OS_WIN)
2456 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2457 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2458 // be set to NULL.
2459 DCHECK(!legacy_render_widget_host_HWND_);
2460 #endif
2463 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2464 if (host_->GetProcess()->FastShutdownStarted())
2465 return;
2467 aura::Window* root_window = window_->GetRootWindow();
2468 if (!root_window)
2469 return;
2471 gfx::Point root_window_point =
2472 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2473 aura::client::ScreenPositionClient* screen_position_client =
2474 aura::client::GetScreenPositionClient(root_window);
2475 if (screen_position_client) {
2476 screen_position_client->ConvertPointFromScreen(
2477 root_window, &root_window_point);
2480 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
2481 return;
2483 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
2484 // Do not show loading cursor when the cursor is currently hidden.
2485 if (is_loading_ && cursor != ui::kCursorNone)
2486 cursor = ui::kCursorPointer;
2488 aura::client::CursorClient* cursor_client =
2489 aura::client::GetCursorClient(root_window);
2490 if (cursor_client) {
2491 cursor_client->SetCursor(cursor);
2495 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2496 aura::Window* root_window = window_->GetRootWindow();
2497 if (!root_window)
2498 return NULL;
2499 return root_window->GetHost()->GetInputMethod();
2502 void RenderWidgetHostViewAura::Shutdown() {
2503 if (!in_shutdown_) {
2504 in_shutdown_ = true;
2505 host_->Shutdown();
2509 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2510 return popup_type_ == blink::WebPopupTypePage;
2513 bool RenderWidgetHostViewAura::NeedsMouseCapture() {
2514 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2515 return NeedsInputGrab();
2516 #endif
2517 return false;
2520 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2521 if (!has_composition_text_)
2522 return;
2523 if (host_) {
2524 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2525 false);
2527 ImeCancelComposition();
2530 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2531 blink::WebMouseEvent* event) {
2532 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2533 // reset any global_mouse_position set previously.
2534 if (event->type == blink::WebInputEvent::MouseEnter ||
2535 event->type == blink::WebInputEvent::MouseLeave)
2536 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2538 // Movement is computed by taking the difference of the new cursor position
2539 // and the previous. Under mouse lock the cursor will be warped back to the
2540 // center so that we are not limited by clipping boundaries.
2541 // We do not measure movement as the delta from cursor to center because
2542 // we may receive more mouse movement events before our warp has taken
2543 // effect.
2544 event->movementX = event->globalX - global_mouse_position_.x();
2545 event->movementY = event->globalY - global_mouse_position_.y();
2547 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2549 // Under mouse lock, coordinates of mouse are locked to what they were when
2550 // mouse lock was entered.
2551 if (mouse_locked_) {
2552 event->x = unlocked_mouse_position_.x();
2553 event->y = unlocked_mouse_position_.y();
2554 event->windowX = unlocked_mouse_position_.x();
2555 event->windowY = unlocked_mouse_position_.y();
2556 event->globalX = unlocked_global_mouse_position_.x();
2557 event->globalY = unlocked_global_mouse_position_.y();
2558 } else {
2559 unlocked_mouse_position_.SetPoint(event->x, event->y);
2560 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2564 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2565 bool is_visible) {
2566 if (host_->is_hidden() ||
2567 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2568 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2569 return;
2571 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2572 host_->SendCursorVisibilityState(is_visible);
2575 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
2576 if (!enabled)
2577 overscroll_controller_.reset();
2578 else if (!overscroll_controller_)
2579 overscroll_controller_.reset(new OverscrollController());
2582 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
2583 // The top left corner of our view in window coordinates might not land on a
2584 // device pixel boundary if we have a non-integer device scale. In that case,
2585 // to avoid the web contents area looking blurry we translate the web contents
2586 // in the +x, +y direction to land on the nearest pixel boundary. This may
2587 // cause the bottom and right edges to be clipped slightly, but that's ok.
2588 aura::Window* snapped = NULL;
2589 // On desktop, use the root window. On alternative environment (ash),
2590 // use the toplevel window which must be already snapped.
2591 if (gfx::Screen::GetScreenFor(window_) !=
2592 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
2593 snapped = window_->GetRootWindow();
2594 } else {
2595 snapped = window_->GetToplevelWindow();
2597 if (snapped && snapped != window_)
2598 ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
2600 has_snapped_to_boundary_ = true;
2603 void RenderWidgetHostViewAura::OnShowContextMenu() {
2604 #if defined(OS_WIN)
2605 showing_context_menu_ = true;
2606 #endif
2609 void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
2610 scoped_ptr<TouchSelectionControllerClientAura> client) {
2611 selection_controller_client_.swap(client);
2612 CreateSelectionController();
2615 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
2616 SnapToPhysicalPixelBoundary();
2617 // Don't recursively call SetBounds if this bounds update is the result of
2618 // a Window::SetBoundsInternal call.
2619 if (!in_bounds_changed_)
2620 window_->SetBounds(rect);
2621 host_->WasResized();
2622 delegated_frame_host_->WasResized();
2623 #if defined(OS_WIN)
2624 // Create the legacy dummy window which corresponds to the bounds of the
2625 // webcontents. This will be passed as the container window for windowless
2626 // plugins.
2627 // Plugins like Flash assume the container window which is returned via the
2628 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
2629 // This is not true in Aura where we have only HWND which is the main Aura
2630 // window. If we return this window to plugins like Flash then it causes the
2631 // coordinate translations done by these plugins to break.
2632 // Additonally the legacy dummy window is needed for accessibility and for
2633 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
2634 if (!legacy_window_destroyed_ && GetNativeViewId()) {
2635 if (!legacy_render_widget_host_HWND_) {
2636 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
2637 reinterpret_cast<HWND>(GetNativeViewId()));
2639 if (legacy_render_widget_host_HWND_) {
2640 legacy_render_widget_host_HWND_->set_host(this);
2641 legacy_render_widget_host_HWND_->SetBounds(
2642 window_->GetBoundsInRootWindow());
2643 // There are cases where the parent window is created, made visible and
2644 // the associated RenderWidget is also visible before the
2645 // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
2646 // here.
2647 if (!host_->is_hidden())
2648 legacy_render_widget_host_HWND_->Show();
2652 if (mouse_locked_)
2653 UpdateMouseLockRegion();
2654 #endif
2657 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2658 const gfx::Rect& rect,
2659 const gfx::Rect& clip) {
2660 if (!clip.IsEmpty()) {
2661 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
2662 if (!to_paint.IsEmpty())
2663 window_->SchedulePaintInRect(to_paint);
2664 } else {
2665 window_->SchedulePaintInRect(rect);
2669 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2670 gfx::Rect rect = window_->bounds();
2671 rect = ConvertRectToScreen(rect);
2672 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
2673 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
2675 return global_mouse_position_.x() < rect.x() + border_x ||
2676 global_mouse_position_.x() > rect.right() - border_x ||
2677 global_mouse_position_.y() < rect.y() + border_y ||
2678 global_mouse_position_.y() > rect.bottom() - border_y;
2681 void RenderWidgetHostViewAura::AddedToRootWindow() {
2682 window_->GetHost()->AddObserver(this);
2683 UpdateScreenInfo(window_);
2685 aura::client::CursorClient* cursor_client =
2686 aura::client::GetCursorClient(window_->GetRootWindow());
2687 if (cursor_client) {
2688 cursor_client->AddObserver(this);
2689 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
2691 if (HasFocus()) {
2692 ui::InputMethod* input_method = GetInputMethod();
2693 if (input_method)
2694 input_method->SetFocusedTextInputClient(this);
2697 #if defined(OS_WIN)
2698 // The parent may have changed here. Ensure that the legacy window is
2699 // reparented accordingly.
2700 if (legacy_render_widget_host_HWND_)
2701 legacy_render_widget_host_HWND_->UpdateParent(
2702 reinterpret_cast<HWND>(GetNativeViewId()));
2703 #endif
2705 delegated_frame_host_->SetCompositor(window_->GetHost()->compositor());
2706 if (window_->GetHost()->compositor())
2707 begin_frame_observer_proxy_.SetCompositor(window_->GetHost()->compositor());
2710 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2711 aura::client::CursorClient* cursor_client =
2712 aura::client::GetCursorClient(window_->GetRootWindow());
2713 if (cursor_client)
2714 cursor_client->RemoveObserver(this);
2716 DetachFromInputMethod();
2718 window_->GetHost()->RemoveObserver(this);
2719 delegated_frame_host_->ResetCompositor();
2720 begin_frame_observer_proxy_.ResetCompositor();
2722 #if defined(OS_WIN)
2723 // Update the legacy window's parent temporarily to the desktop window. It
2724 // will eventually get reparented to the right root.
2725 if (legacy_render_widget_host_HWND_)
2726 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
2727 #endif
2730 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2731 ui::InputMethod* input_method = GetInputMethod();
2732 if (input_method)
2733 input_method->DetachTextInputClient(this);
2736 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2737 const NativeWebKeyboardEvent& event) {
2738 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2739 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
2740 ui::GetTextEditKeyBindingsDelegate();
2741 std::vector<ui::TextEditCommandAuraLinux> commands;
2742 if (!event.skip_in_browser &&
2743 keybinding_delegate &&
2744 event.os_event &&
2745 keybinding_delegate->MatchEvent(*event.os_event, &commands)) {
2746 // Transform from ui/ types to content/ types.
2747 EditCommands edit_commands;
2748 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it =
2749 commands.begin(); it != commands.end(); ++it) {
2750 edit_commands.push_back(EditCommand(it->GetCommandString(),
2751 it->argument()));
2753 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2754 host_->GetRoutingID(), edit_commands));
2755 NativeWebKeyboardEvent copy_event(event);
2756 copy_event.match_edit_command = true;
2757 host_->ForwardKeyboardEvent(copy_event);
2758 return;
2760 #endif
2762 host_->ForwardKeyboardEvent(event);
2765 void RenderWidgetHostViewAura::SelectionUpdated(bool is_editable,
2766 bool is_empty_text_form_control,
2767 const ui::SelectionBound& start,
2768 const ui::SelectionBound& end) {
2769 selection_controller_->OnSelectionEditable(is_editable);
2770 selection_controller_->OnSelectionEmpty(is_empty_text_form_control);
2771 selection_controller_->OnSelectionBoundsChanged(start, end);
2774 void RenderWidgetHostViewAura::CreateSelectionController() {
2775 ui::TouchSelectionController::Config tsc_config;
2776 tsc_config.max_tap_duration = base::TimeDelta::FromMilliseconds(
2777 ui::GestureConfiguration::GetInstance()->long_press_time_in_ms());
2778 tsc_config.tap_slop = ui::GestureConfiguration::GetInstance()
2779 ->max_touch_move_in_pixels_for_click();
2780 tsc_config.show_on_tap_for_empty_editable = true;
2781 tsc_config.enable_longpress_drag_selection = false;
2782 selection_controller_.reset(new ui::TouchSelectionController(
2783 selection_controller_client_.get(), tsc_config));
2786 void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
2787 ui::GestureEvent* event) {
2788 switch (event->type()) {
2789 case ui::ET_GESTURE_LONG_PRESS:
2790 if (selection_controller_->WillHandleLongPressEvent(
2791 base::TimeTicks() + event->time_stamp(), event->location_f())) {
2792 event->SetHandled();
2794 break;
2795 case ui::ET_GESTURE_TAP:
2796 if (selection_controller_->WillHandleTapEvent(event->location_f()))
2797 event->SetHandled();
2798 break;
2799 case ui::ET_GESTURE_SCROLL_BEGIN:
2800 selection_controller_client_->OnScrollStarted();
2801 break;
2802 case ui::ET_GESTURE_SCROLL_END:
2803 selection_controller_client_->OnScrollCompleted();
2804 break;
2805 default:
2806 break;
2810 ////////////////////////////////////////////////////////////////////////////////
2811 // DelegatedFrameHost, public:
2813 ui::Layer* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const {
2814 return window_->layer();
2817 bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const {
2818 return !host_->is_hidden();
2821 gfx::Size RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const {
2822 return window_->bounds().size();
2825 bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const {
2826 #if !defined(OS_CHROMEOS)
2827 // On Windows and Linux, holding pointer moves will not help throttling
2828 // resizes.
2829 // TODO(piman): on Windows we need to block (nested message loop?) the
2830 // WM_SIZE event. On Linux we need to throttle at the WM level using
2831 // _NET_WM_SYNC_REQUEST.
2832 return false;
2833 #else
2834 if (host_->auto_resize_enabled())
2835 return false;
2836 return true;
2837 #endif
2840 scoped_ptr<ResizeLock>
2841 RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock(
2842 bool defer_compositor_lock) {
2843 gfx::Size desired_size = window_->bounds().size();
2844 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
2845 window_->GetHost(),
2846 desired_size,
2847 defer_compositor_lock,
2848 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2851 void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() {
2852 host_->WasResized();
2855 void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck(
2856 int output_surface_id,
2857 const cc::CompositorFrameAck& ack) {
2858 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
2859 output_surface_id, ack));
2862 void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
2863 int output_surface_id,
2864 const cc::CompositorFrameAck& ack) {
2865 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
2866 output_surface_id, ack));
2869 void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
2870 host_->ScheduleComposite();
2873 void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters(
2874 const base::TimeTicks& timebase,
2875 const base::TimeDelta& interval) {
2876 host_->UpdateVSyncParameters(timebase, interval);
2879 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
2880 ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
2883 uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
2884 return delegated_frame_host_->GetSurfaceIdNamespace();
2887 ////////////////////////////////////////////////////////////////////////////////
2888 // RenderWidgetHostViewBase, public:
2890 // static
2891 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2892 GetScreenInfoForWindow(results, NULL);
2895 } // namespace content