Make USB permissions work in the new permission message system
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura.cc
blobf8fdba0e1ab225ce0944c70822ccb2c63ade0c6c
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_impl.h"
41 #include "content/browser/renderer_host/ui_events_helper.h"
42 #include "content/browser/renderer_host/web_input_event_aura.h"
43 #include "content/common/gpu/client/gl_helper.h"
44 #include "content/common/gpu/gpu_messages.h"
45 #include "content/common/view_messages.h"
46 #include "content/public/browser/content_browser_client.h"
47 #include "content/public/browser/overscroll_configuration.h"
48 #include "content/public/browser/render_view_host.h"
49 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
50 #include "content/public/browser/user_metrics.h"
51 #include "content/public/common/content_switches.h"
52 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
53 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
54 #include "third_party/WebKit/public/web/WebInputEvent.h"
55 #include "ui/aura/client/aura_constants.h"
56 #include "ui/aura/client/cursor_client.h"
57 #include "ui/aura/client/cursor_client_observer.h"
58 #include "ui/aura/client/focus_client.h"
59 #include "ui/aura/client/screen_position_client.h"
60 #include "ui/aura/client/window_tree_client.h"
61 #include "ui/aura/env.h"
62 #include "ui/aura/window.h"
63 #include "ui/aura/window_event_dispatcher.h"
64 #include "ui/aura/window_observer.h"
65 #include "ui/aura/window_tracker.h"
66 #include "ui/aura/window_tree_host.h"
67 #include "ui/base/clipboard/scoped_clipboard_writer.h"
68 #include "ui/base/hit_test.h"
69 #include "ui/base/ime/input_method.h"
70 #include "ui/base/ui_base_types.h"
71 #include "ui/compositor/compositor_vsync_manager.h"
72 #include "ui/compositor/dip_util.h"
73 #include "ui/events/blink/blink_event_util.h"
74 #include "ui/events/event.h"
75 #include "ui/events/event_utils.h"
76 #include "ui/events/gesture_detection/gesture_configuration.h"
77 #include "ui/events/gestures/gesture_recognizer.h"
78 #include "ui/gfx/canvas.h"
79 #include "ui/gfx/display.h"
80 #include "ui/gfx/geometry/rect_conversions.h"
81 #include "ui/gfx/geometry/size_conversions.h"
82 #include "ui/gfx/screen.h"
83 #include "ui/gfx/skia_util.h"
84 #include "ui/touch_selection/touch_selection_controller.h"
85 #include "ui/wm/public/activation_client.h"
86 #include "ui/wm/public/scoped_tooltip_disabler.h"
87 #include "ui/wm/public/tooltip_client.h"
88 #include "ui/wm/public/transient_window_client.h"
89 #include "ui/wm/public/window_types.h"
91 #if defined(OS_WIN)
92 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
93 #include "content/browser/accessibility/browser_accessibility_win.h"
94 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
95 #include "content/common/plugin_constants_win.h"
96 #include "ui/base/win/hidden_window.h"
97 #include "ui/gfx/gdi_util.h"
98 #include "ui/gfx/win/dpi.h"
99 #endif
101 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
102 #include "content/common/input_messages.h"
103 #include "ui/events/linux/text_edit_command_auralinux.h"
104 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
105 #endif
107 using gfx::RectToSkIRect;
108 using gfx::SkIRectToRect;
110 using blink::WebScreenInfo;
111 using blink::WebInputEvent;
112 using blink::WebGestureEvent;
113 using blink::WebTouchEvent;
115 namespace content {
117 namespace {
119 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
120 // the border of the view, in order to get valid movement information. However,
121 // forcing the cursor back to the center of the view after each mouse move
122 // doesn't work well. It reduces the frequency of useful mouse move messages
123 // significantly. Therefore, we move the cursor to the center of the view only
124 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
125 // of the border area, in percentage of the corresponding dimension.
126 const int kMouseLockBorderPercentage = 15;
128 // When accelerated compositing is enabled and a widget resize is pending,
129 // we delay further resizes of the UI. The following constant is the maximum
130 // length of time that we should delay further UI resizes while waiting for a
131 // resized frame from a renderer.
132 const int kResizeLockTimeoutMs = 67;
134 #if defined(OS_WIN)
135 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
136 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
138 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
139 RenderWidgetHostViewAura* widget =
140 reinterpret_cast<RenderWidgetHostViewAura*>(param);
141 if (GetProp(window, kWidgetOwnerProperty) == widget) {
142 // Properties set on HWNDs must be removed to avoid leaks.
143 RemoveProp(window, kWidgetOwnerProperty);
144 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
146 return TRUE;
149 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
150 RenderWidgetHostViewAura* widget =
151 reinterpret_cast<RenderWidgetHostViewAura*>(param);
152 if (GetProp(window, kWidgetOwnerProperty) == widget)
153 SetParent(window, ui::GetHiddenWindow());
154 return TRUE;
157 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
158 RenderWidgetHostViewAura* widget =
159 reinterpret_cast<RenderWidgetHostViewAura*>(param);
161 if (GetProp(window, kWidgetOwnerProperty) == widget &&
162 widget->GetNativeView()->GetHost()) {
163 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
164 SetParent(window, parent);
166 return TRUE;
169 struct CutoutRectsParams {
170 RenderWidgetHostViewAura* widget;
171 std::vector<gfx::Rect> cutout_rects;
172 std::map<HWND, WebPluginGeometry>* geometry;
175 // Used to update the region for the windowed plugin to draw in. We start with
176 // the clip rect from the renderer, then remove the cutout rects from the
177 // renderer, and then remove the transient windows from the root window and the
178 // constrained windows from the parent window.
179 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
180 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
182 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
183 // First calculate the offset of this plugin from the root window, since
184 // the cutouts are relative to the root window.
185 HWND parent =
186 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
187 POINT offset;
188 offset.x = offset.y = 0;
189 MapWindowPoints(window, parent, &offset, 1);
191 // Now get the cached clip rect and cutouts for this plugin window that came
192 // from the renderer.
193 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
194 while (i != params->geometry->end() &&
195 i->second.window != window &&
196 GetParent(i->second.window) != window) {
197 ++i;
200 if (i == params->geometry->end()) {
201 NOTREACHED();
202 return TRUE;
205 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
206 i->second.clip_rect.y(),
207 i->second.clip_rect.right(),
208 i->second.clip_rect.bottom());
209 // We start with the cutout rects that came from the renderer, then add the
210 // ones that came from transient and constrained windows.
211 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
212 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
213 gfx::Rect offset_cutout = params->cutout_rects[i];
214 offset_cutout.Offset(-offset.x, -offset.y);
215 cutout_rects.push_back(offset_cutout);
217 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
218 // If we don't have any cutout rects then no point in messing with the
219 // window region.
220 if (cutout_rects.size())
221 SetWindowRgn(window, hrgn, TRUE);
223 return TRUE;
226 // A callback function for EnumThreadWindows to enumerate and dismiss
227 // any owned popup windows.
228 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
229 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
231 if (::IsWindowVisible(window)) {
232 const HWND owner = ::GetWindow(window, GW_OWNER);
233 if (toplevel_hwnd == owner) {
234 ::PostMessage(window, WM_CANCELMODE, 0, 0);
238 return TRUE;
240 #endif
242 // We don't mark these as handled so that they're sent back to the
243 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
244 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
245 #if defined(OS_WIN)
246 switch (event->native_event().message) {
247 case WM_XBUTTONUP:
248 case WM_NCXBUTTONUP:
249 return true;
251 #endif
252 return false;
255 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
256 const gfx::Display display = window ?
257 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
258 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
259 results->rect = display.bounds();
260 results->availableRect = display.work_area();
261 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
262 results->depth = 24;
263 results->depthPerComponent = 8;
264 results->deviceScaleFactor = display.device_scale_factor();
266 // The Display rotation and the WebScreenInfo orientation are not the same
267 // angle. The former is the physical display rotation while the later is the
268 // rotation required by the content to be shown properly on the screen, in
269 // other words, relative to the physical display.
270 results->orientationAngle = display.RotationAsDegree();
271 if (results->orientationAngle == 90)
272 results->orientationAngle = 270;
273 else if (results->orientationAngle == 270)
274 results->orientationAngle = 90;
276 results->orientationType =
277 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
280 bool IsFractionalScaleFactor(float scale_factor) {
281 return (scale_factor - static_cast<int>(scale_factor)) > 0;
284 // Reset unchanged touch point to StateStationary for touchmove and
285 // touchcancel.
286 void MarkUnchangedTouchPointsAsStationary(
287 blink::WebTouchEvent* event,
288 int changed_touch_id) {
289 if (event->type == blink::WebInputEvent::TouchMove ||
290 event->type == blink::WebInputEvent::TouchCancel) {
291 for (size_t i = 0; i < event->touchesLength; ++i) {
292 if (event->touches[i].id != changed_touch_id)
293 event->touches[i].state = blink::WebTouchPoint::StateStationary;
298 } // namespace
300 // We need to watch for mouse events outside a Web Popup or its parent
301 // and dismiss the popup for certain events.
302 class RenderWidgetHostViewAura::EventFilterForPopupExit
303 : public ui::EventHandler {
304 public:
305 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
306 : rwhva_(rwhva) {
307 DCHECK(rwhva_);
308 aura::Env::GetInstance()->AddPreTargetHandler(this);
311 ~EventFilterForPopupExit() override {
312 aura::Env::GetInstance()->RemovePreTargetHandler(this);
315 // Overridden from ui::EventHandler
316 void OnMouseEvent(ui::MouseEvent* event) override {
317 rwhva_->ApplyEventFilterForPopupExit(event);
320 void OnTouchEvent(ui::TouchEvent* event) override {
321 rwhva_->ApplyEventFilterForPopupExit(event);
324 private:
325 RenderWidgetHostViewAura* rwhva_;
327 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
330 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
331 ui::LocatedEvent* event) {
332 if (in_shutdown_ || is_fullscreen_ || !event->target())
333 return;
335 if (event->type() != ui::ET_MOUSE_PRESSED &&
336 event->type() != ui::ET_TOUCH_PRESSED) {
337 return;
340 aura::Window* target = static_cast<aura::Window*>(event->target());
341 if (target != window_ &&
342 (!popup_parent_host_view_ ||
343 target != popup_parent_host_view_->window_)) {
344 // If we enter this code path it means that we did not receive any focus
345 // lost notifications for the popup window. Ensure that blink is aware
346 // of the fact that focus was lost for the host window by sending a Blur
347 // notification.
348 if (popup_parent_host_view_ && popup_parent_host_view_->host_)
349 popup_parent_host_view_->host_->Blur();
350 // Note: popup_parent_host_view_ may be NULL when there are multiple
351 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
352 Shutdown();
356 // We have to implement the WindowObserver interface on a separate object
357 // because clang doesn't like implementing multiple interfaces that have
358 // methods with the same name. This object is owned by the
359 // RenderWidgetHostViewAura.
360 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
361 public:
362 explicit WindowObserver(RenderWidgetHostViewAura* view)
363 : view_(view) {
364 view_->window_->AddObserver(this);
367 ~WindowObserver() override { view_->window_->RemoveObserver(this); }
369 // Overridden from aura::WindowObserver:
370 void OnWindowAddedToRootWindow(aura::Window* window) override {
371 if (window == view_->window_)
372 view_->AddedToRootWindow();
375 void OnWindowRemovingFromRootWindow(aura::Window* window,
376 aura::Window* new_root) override {
377 if (window == view_->window_)
378 view_->RemovingFromRootWindow();
381 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
382 view_->ParentHierarchyChanged();
385 private:
386 RenderWidgetHostViewAura* view_;
388 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
391 // This class provides functionality to observe the ancestors of the RWHVA for
392 // bounds changes. This is done to snap the RWHVA window to a pixel boundary,
393 // which could change when the bounds relative to the root changes.
394 // An example where this happens is below:-
395 // The fast resize code path for bookmarks where in the parent of RWHVA which
396 // is WCV has its bounds changed before the bookmark is hidden. This results in
397 // the traditional bounds change notification for the WCV reporting the old
398 // bounds as the bookmark is still around. Observing all the ancestors of the
399 // RWHVA window enables us to know when the bounds of the window relative to
400 // root changes and allows us to snap accordingly.
401 class RenderWidgetHostViewAura::WindowAncestorObserver
402 : public aura::WindowObserver {
403 public:
404 explicit WindowAncestorObserver(RenderWidgetHostViewAura* view)
405 : view_(view) {
406 aura::Window* parent = view_->window_->parent();
407 while (parent) {
408 parent->AddObserver(this);
409 ancestors_.insert(parent);
410 parent = parent->parent();
414 ~WindowAncestorObserver() override {
415 RemoveAncestorObservers();
418 void OnWindowBoundsChanged(aura::Window* window,
419 const gfx::Rect& old_bounds,
420 const gfx::Rect& new_bounds) override {
421 DCHECK(ancestors_.find(window) != ancestors_.end());
422 if (new_bounds.origin() != old_bounds.origin())
423 view_->HandleParentBoundsChanged();
426 private:
427 void RemoveAncestorObservers() {
428 for (auto ancestor : ancestors_)
429 ancestor->RemoveObserver(this);
430 ancestors_.clear();
433 RenderWidgetHostViewAura* view_;
434 std::set<aura::Window*> ancestors_;
436 DISALLOW_COPY_AND_ASSIGN(WindowAncestorObserver);
439 ////////////////////////////////////////////////////////////////////////////////
440 // RenderWidgetHostViewAura, public:
442 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
443 bool is_guest_view_hack)
444 : host_(RenderWidgetHostImpl::From(host)),
445 window_(new aura::Window(this)),
446 delegated_frame_host_(new DelegatedFrameHost(this)),
447 in_shutdown_(false),
448 in_bounds_changed_(false),
449 is_fullscreen_(false),
450 popup_parent_host_view_(NULL),
451 popup_child_host_view_(NULL),
452 is_loading_(false),
453 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
454 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
455 text_input_flags_(0),
456 can_compose_inline_(true),
457 has_composition_text_(false),
458 accept_return_character_(false),
459 last_swapped_software_frame_scale_factor_(1.f),
460 paint_canvas_(NULL),
461 synthetic_move_sent_(false),
462 cursor_visibility_state_in_renderer_(UNKNOWN),
463 #if defined(OS_WIN)
464 legacy_render_widget_host_HWND_(NULL),
465 legacy_window_destroyed_(false),
466 showing_context_menu_(false),
467 #endif
468 has_snapped_to_boundary_(false),
469 is_guest_view_hack_(is_guest_view_hack),
470 begin_frame_observer_proxy_(this),
471 weak_ptr_factory_(this) {
472 if (!is_guest_view_hack_)
473 host_->SetView(this);
475 window_observer_.reset(new WindowObserver(this));
477 aura::client::SetTooltipText(window_, &tooltip_);
478 aura::client::SetActivationDelegate(window_, this);
479 aura::client::SetFocusChangeObserver(window_, this);
480 window_->set_layer_owner_delegate(delegated_frame_host_.get());
481 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
483 bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
484 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
485 SetOverscrollControllerEnabled(overscroll_enabled);
487 selection_controller_client_.reset(
488 new TouchSelectionControllerClientAura(this));
489 CreateSelectionController();
492 ////////////////////////////////////////////////////////////////////////////////
493 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
495 bool RenderWidgetHostViewAura::OnMessageReceived(
496 const IPC::Message& message) {
497 bool handled = true;
498 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
499 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
500 OnSetNeedsBeginFrames)
501 IPC_MESSAGE_UNHANDLED(handled = false)
502 IPC_END_MESSAGE_MAP()
503 return handled;
506 void RenderWidgetHostViewAura::InitAsChild(
507 gfx::NativeView parent_view) {
508 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
509 window_->Init(ui::LAYER_SOLID_COLOR);
510 window_->SetName("RenderWidgetHostViewAura");
511 window_->layer()->SetColor(background_color_);
514 void RenderWidgetHostViewAura::InitAsPopup(
515 RenderWidgetHostView* parent_host_view,
516 const gfx::Rect& bounds_in_screen) {
517 popup_parent_host_view_ =
518 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
520 // TransientWindowClient may be NULL during tests.
521 aura::client::TransientWindowClient* transient_window_client =
522 aura::client::GetTransientWindowClient();
523 RenderWidgetHostViewAura* old_child =
524 popup_parent_host_view_->popup_child_host_view_;
525 if (old_child) {
526 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
527 // similar mechanism to ensure a second popup doesn't cause the first one
528 // to never get a chance to filter events. See crbug.com/160589.
529 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
530 if (transient_window_client) {
531 transient_window_client->RemoveTransientChild(
532 popup_parent_host_view_->window_, old_child->window_);
534 old_child->popup_parent_host_view_ = NULL;
536 popup_parent_host_view_->popup_child_host_view_ = this;
537 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
538 window_->Init(ui::LAYER_SOLID_COLOR);
539 window_->SetName("RenderWidgetHostViewAura");
540 window_->layer()->SetColor(background_color_);
542 // Setting the transient child allows for the popup to get mouse events when
543 // in a system modal dialog. Do this before calling ParentWindowWithContext
544 // below so that the transient parent is visible to WindowTreeClient.
545 // This fixes crbug.com/328593.
546 if (transient_window_client) {
547 transient_window_client->AddTransientChild(
548 popup_parent_host_view_->window_, window_);
551 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
552 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
554 SetBounds(bounds_in_screen);
555 Show();
556 if (NeedsMouseCapture())
557 window_->SetCapture();
559 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
562 void RenderWidgetHostViewAura::InitAsFullscreen(
563 RenderWidgetHostView* reference_host_view) {
564 is_fullscreen_ = true;
565 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
566 window_->Init(ui::LAYER_SOLID_COLOR);
567 window_->SetName("RenderWidgetHostViewAura");
568 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
569 window_->layer()->SetColor(background_color_);
571 aura::Window* parent = NULL;
572 gfx::Rect bounds;
573 if (reference_host_view) {
574 aura::Window* reference_window =
575 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
576 if (reference_window) {
577 host_tracker_.reset(new aura::WindowTracker);
578 host_tracker_->Add(reference_window);
580 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
581 GetDisplayNearestWindow(reference_window);
582 parent = reference_window->GetRootWindow();
583 bounds = display.bounds();
585 aura::client::ParentWindowWithContext(window_, parent, bounds);
586 Show();
587 Focus();
590 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
591 return host_;
594 void RenderWidgetHostViewAura::Show() {
595 window_->Show();
597 DCHECK(host_);
598 if (!host_->is_hidden())
599 return;
601 bool has_saved_frame = delegated_frame_host_->HasSavedFrame();
602 ui::LatencyInfo renderer_latency_info, browser_latency_info;
603 if (has_saved_frame) {
604 browser_latency_info.AddLatencyNumber(
605 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
606 } else {
607 renderer_latency_info.AddLatencyNumber(
608 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
610 host_->WasShown(renderer_latency_info);
612 aura::Window* root = window_->GetRootWindow();
613 if (root) {
614 aura::client::CursorClient* cursor_client =
615 aura::client::GetCursorClient(root);
616 if (cursor_client)
617 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
620 delegated_frame_host_->WasShown(browser_latency_info);
622 #if defined(OS_WIN)
623 if (legacy_render_widget_host_HWND_) {
624 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
625 // window before reparenting any plugins. This ensures that the plugin
626 // windows stay on top of the child Zorder in the parent and receive
627 // mouse events, etc.
628 legacy_render_widget_host_HWND_->UpdateParent(
629 GetNativeView()->GetHost()->GetAcceleratedWidget());
630 legacy_render_widget_host_HWND_->SetBounds(
631 window_->GetBoundsInRootWindow());
633 LPARAM lparam = reinterpret_cast<LPARAM>(this);
634 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
636 if (legacy_render_widget_host_HWND_)
637 legacy_render_widget_host_HWND_->Show();
638 #endif
641 void RenderWidgetHostViewAura::Hide() {
642 window_->Hide();
644 if (host_ && !host_->is_hidden()) {
645 host_->WasHidden();
646 delegated_frame_host_->WasHidden();
648 #if defined(OS_WIN)
649 constrained_rects_.clear();
650 aura::WindowTreeHost* host = window_->GetHost();
651 if (host) {
652 HWND parent = host->GetAcceleratedWidget();
653 LPARAM lparam = reinterpret_cast<LPARAM>(this);
654 EnumChildWindows(parent, HideWindowsCallback, lparam);
655 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
656 // hidden window on the same lines as Windowed plugin windows.
657 if (legacy_render_widget_host_HWND_)
658 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
660 #endif
663 #if defined(OS_WIN)
664 if (legacy_render_widget_host_HWND_)
665 legacy_render_widget_host_HWND_->Hide();
666 #endif
669 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
670 // For a SetSize operation, we don't care what coordinate system the origin
671 // of the window is in, it's only important to make sure that the origin
672 // remains constant after the operation.
673 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
676 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
677 gfx::Point relative_origin(rect.origin());
679 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
680 // Window::SetBounds() takes parent coordinates, so do the conversion here.
681 aura::Window* root = window_->GetRootWindow();
682 if (root) {
683 aura::client::ScreenPositionClient* screen_position_client =
684 aura::client::GetScreenPositionClient(root);
685 if (screen_position_client) {
686 screen_position_client->ConvertPointFromScreen(
687 window_->parent(), &relative_origin);
691 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
694 gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
695 return last_scroll_offset_;
698 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
699 return window_;
702 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
703 #if defined(OS_WIN)
704 aura::WindowTreeHost* host = window_->GetHost();
705 if (host)
706 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
707 #endif
708 return static_cast<gfx::NativeViewId>(NULL);
711 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
712 #if defined(OS_WIN)
713 aura::WindowTreeHost* host = window_->GetHost();
714 if (!host)
715 return static_cast<gfx::NativeViewAccessible>(NULL);
716 BrowserAccessibilityManager* manager =
717 host_->GetOrCreateRootBrowserAccessibilityManager();
718 if (manager)
719 return manager->GetRoot()->ToBrowserAccessibilityWin();
720 #endif
722 NOTIMPLEMENTED();
723 return static_cast<gfx::NativeViewAccessible>(NULL);
726 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
727 return this;
730 void RenderWidgetHostViewAura::OnSetNeedsBeginFrames(bool needs_begin_frames) {
731 begin_frame_observer_proxy_.SetNeedsBeginFrames(needs_begin_frames);
734 void RenderWidgetHostViewAura::SendBeginFrame(const cc::BeginFrameArgs& args) {
735 delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval);
736 host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
739 void RenderWidgetHostViewAura::SetKeyboardFocus() {
740 #if defined(OS_WIN)
741 if (CanFocus()) {
742 aura::WindowTreeHost* host = window_->GetHost();
743 if (host)
744 ::SetFocus(host->GetAcceleratedWidget());
746 #endif
749 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
750 if (!host_->IsRenderView())
751 return NULL;
752 RenderViewHost* rvh = RenderViewHost::From(host_);
753 FrameTreeNode* focused_frame =
754 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
755 if (!focused_frame)
756 return NULL;
758 return focused_frame->current_frame_host();
761 bool RenderWidgetHostViewAura::CanRendererHandleEvent(
762 const ui::MouseEvent* event,
763 bool mouse_locked,
764 bool selection_popup) {
765 #if defined(OS_WIN)
766 bool showing_context_menu = showing_context_menu_;
767 showing_context_menu_ = false;
768 #endif
770 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
771 return false;
773 if ((mouse_locked || selection_popup) &&
774 (event->type() == ui::ET_MOUSE_EXITED))
775 return false;
777 #if defined(OS_WIN)
778 // Don't forward the mouse leave message which is received when the context
779 // menu is displayed by the page. This confuses the page and causes state
780 // changes.
781 if (showing_context_menu) {
782 if (event->type() == ui::ET_MOUSE_EXITED)
783 return false;
785 // Renderer cannot handle WM_XBUTTON or NC events.
786 switch (event->native_event().message) {
787 case WM_XBUTTONDOWN:
788 case WM_XBUTTONUP:
789 case WM_XBUTTONDBLCLK:
790 case WM_NCMOUSELEAVE:
791 case WM_NCMOUSEMOVE:
792 case WM_NCLBUTTONDOWN:
793 case WM_NCLBUTTONUP:
794 case WM_NCLBUTTONDBLCLK:
795 case WM_NCRBUTTONDOWN:
796 case WM_NCRBUTTONUP:
797 case WM_NCRBUTTONDBLCLK:
798 case WM_NCMBUTTONDOWN:
799 case WM_NCMBUTTONUP:
800 case WM_NCMBUTTONDBLCLK:
801 case WM_NCXBUTTONDOWN:
802 case WM_NCXBUTTONUP:
803 case WM_NCXBUTTONDBLCLK:
804 return false;
805 default:
806 break;
808 #elif defined(USE_X11)
809 // Renderer only supports standard mouse buttons, so ignore programmable
810 // buttons.
811 switch (event->type()) {
812 case ui::ET_MOUSE_PRESSED:
813 case ui::ET_MOUSE_RELEASED: {
814 const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
815 ui::EF_MIDDLE_MOUSE_BUTTON |
816 ui::EF_RIGHT_MOUSE_BUTTON;
817 return (event->flags() & kAllowedButtons) != 0;
819 default:
820 break;
822 #endif
823 return true;
826 void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
827 SnapToPhysicalPixelBoundary();
828 #if defined(OS_WIN)
829 if (legacy_render_widget_host_HWND_) {
830 legacy_render_widget_host_HWND_->SetBounds(
831 window_->GetBoundsInRootWindow());
833 #endif
834 if (!in_shutdown_)
835 host_->SendScreenRects();
838 void RenderWidgetHostViewAura::ParentHierarchyChanged() {
839 ancestor_window_observer_.reset(new WindowAncestorObserver(this));
840 // Snap when we receive a hierarchy changed. http://crbug.com/388908.
841 HandleParentBoundsChanged();
844 void RenderWidgetHostViewAura::MovePluginWindows(
845 const std::vector<WebPluginGeometry>& plugin_window_moves) {
846 #if defined(OS_WIN)
847 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
848 // over the browser UI.
849 if (!window_->GetRootWindow()) {
850 DCHECK(plugin_window_moves.empty());
851 return;
853 HWND parent = window_->GetHost()->GetAcceleratedWidget();
854 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
855 std::vector<WebPluginGeometry> moves = plugin_window_moves;
857 gfx::Rect view_port(view_bounds.size());
859 for (size_t i = 0; i < moves.size(); ++i) {
860 gfx::Rect clip(moves[i].clip_rect);
861 gfx::Vector2d view_port_offset(
862 moves[i].window_rect.OffsetFromOrigin());
863 clip.Offset(view_port_offset);
864 clip.Intersect(view_port);
865 clip.Offset(-view_port_offset);
866 moves[i].clip_rect = clip;
868 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
870 plugin_window_moves_[moves[i].window] = moves[i];
872 // constrained_rects_ are relative to the root window. We want to convert
873 // them to be relative to the plugin window.
874 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
875 gfx::Rect offset_cutout = constrained_rects_[j];
876 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
877 moves[i].cutout_rects.push_back(offset_cutout);
881 MovePluginWindowsHelper(parent, moves);
883 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
884 // |this|.
885 for (size_t i = 0; i < moves.size(); ++i) {
886 HWND window = moves[i].window;
887 if (GetParent(window) != parent) {
888 window = GetParent(window);
890 if (!GetProp(window, kWidgetOwnerProperty))
891 SetProp(window, kWidgetOwnerProperty, this);
893 #endif // defined(OS_WIN)
896 void RenderWidgetHostViewAura::Focus() {
897 // Make sure we have a FocusClient before attempting to Focus(). In some
898 // situations we may not yet be in a valid Window hierarchy (such as reloading
899 // after out of memory discarded the tab).
900 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
901 if (client)
902 window_->Focus();
905 bool RenderWidgetHostViewAura::HasFocus() const {
906 return window_->HasFocus();
909 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
910 return delegated_frame_host_->CanCopyToBitmap();
913 bool RenderWidgetHostViewAura::IsShowing() {
914 return window_->IsVisible();
917 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
918 return window_->GetBoundsInScreen();
921 void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
922 RenderWidgetHostViewBase::SetBackgroundColor(color);
923 bool opaque = GetBackgroundOpaque();
924 host_->SetBackgroundOpaque(opaque);
925 window_->layer()->SetFillsBoundsOpaquely(opaque);
926 window_->layer()->SetColor(color);
929 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
930 gfx::Rect requested_rect(GetRequestedRendererSize());
931 requested_rect.Inset(insets_);
932 return requested_rect.size();
935 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
936 if (insets != insets_) {
937 insets_ = insets;
938 host_->WasResized();
942 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
943 current_cursor_ = cursor;
944 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
945 GetDisplayNearestWindow(window_);
946 current_cursor_.SetDisplayInfo(display);
947 UpdateCursorIfOverSelf();
950 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
951 is_loading_ = is_loading;
952 UpdateCursorIfOverSelf();
955 void RenderWidgetHostViewAura::TextInputStateChanged(
956 const ViewHostMsg_TextInputState_Params& params) {
957 if (text_input_type_ != params.type ||
958 text_input_mode_ != params.mode ||
959 can_compose_inline_ != params.can_compose_inline ||
960 text_input_flags_ != params.flags) {
961 text_input_type_ = params.type;
962 text_input_mode_ = params.mode;
963 can_compose_inline_ = params.can_compose_inline;
964 text_input_flags_ = params.flags;
965 if (GetInputMethod())
966 GetInputMethod()->OnTextInputTypeChanged(this);
968 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
969 if (GetInputMethod())
970 GetInputMethod()->ShowImeIfNeeded();
974 void RenderWidgetHostViewAura::ImeCancelComposition() {
975 if (GetInputMethod())
976 GetInputMethod()->CancelComposition(this);
977 has_composition_text_ = false;
980 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
981 const gfx::Range& range,
982 const std::vector<gfx::Rect>& character_bounds) {
983 composition_character_bounds_ = character_bounds;
986 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
987 int error_code) {
988 UpdateCursorIfOverSelf();
989 Destroy();
992 void RenderWidgetHostViewAura::Destroy() {
993 // Beware, this function is not called on all destruction paths. It will
994 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
995 // destruction/cleanup code should happen there, not here.
996 in_shutdown_ = true;
997 delete window_;
1000 void RenderWidgetHostViewAura::SetTooltipText(
1001 const base::string16& tooltip_text) {
1002 tooltip_ = tooltip_text;
1003 aura::Window* root_window = window_->GetRootWindow();
1004 aura::client::TooltipClient* tooltip_client =
1005 aura::client::GetTooltipClient(root_window);
1006 if (tooltip_client) {
1007 tooltip_client->UpdateTooltip(window_);
1008 // Content tooltips should be visible indefinitely.
1009 tooltip_client->SetTooltipShownTimeout(window_, 0);
1013 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1014 size_t offset,
1015 const gfx::Range& range) {
1016 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1018 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1019 if (text.empty() || range.is_empty())
1020 return;
1021 size_t pos = range.GetMin() - offset;
1022 size_t n = range.length();
1024 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
1025 if (pos >= text.length()) {
1026 NOTREACHED() << "The text can not cover range.";
1027 return;
1030 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1031 ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
1032 clipboard_writer.WriteText(text.substr(pos, n));
1033 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1036 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
1037 return delegated_frame_host_->GetRequestedRendererSize();
1040 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1041 const ViewHostMsg_SelectionBounds_Params& params) {
1042 ui::SelectionBound anchor_bound, focus_bound;
1043 anchor_bound.SetEdge(params.anchor_rect.origin(),
1044 params.anchor_rect.bottom_left());
1045 focus_bound.SetEdge(params.focus_rect.origin(),
1046 params.focus_rect.bottom_left());
1048 if (params.anchor_rect == params.focus_rect) {
1049 anchor_bound.set_type(ui::SelectionBound::CENTER);
1050 focus_bound.set_type(ui::SelectionBound::CENTER);
1051 } else {
1052 // Whether text is LTR at the anchor handle.
1053 bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight;
1054 // Whether text is LTR at the focus handle.
1055 bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight;
1057 if ((params.is_anchor_first && anchor_LTR) ||
1058 (!params.is_anchor_first && !anchor_LTR)) {
1059 anchor_bound.set_type(ui::SelectionBound::LEFT);
1060 } else {
1061 anchor_bound.set_type(ui::SelectionBound::RIGHT);
1063 if ((params.is_anchor_first && focus_LTR) ||
1064 (!params.is_anchor_first && !focus_LTR)) {
1065 focus_bound.set_type(ui::SelectionBound::RIGHT);
1066 } else {
1067 focus_bound.set_type(ui::SelectionBound::LEFT);
1071 if (anchor_bound == selection_anchor_ && focus_bound == selection_focus_)
1072 return;
1074 selection_anchor_ = anchor_bound;
1075 selection_focus_ = focus_bound;
1076 if (GetInputMethod())
1077 GetInputMethod()->OnCaretBoundsChanged(this);
1080 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1081 const gfx::Rect& src_subrect,
1082 const gfx::Size& dst_size,
1083 ReadbackRequestCallback& callback,
1084 const SkColorType preferred_color_type) {
1085 delegated_frame_host_->CopyFromCompositingSurface(
1086 src_subrect, dst_size, callback, preferred_color_type);
1089 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1090 const gfx::Rect& src_subrect,
1091 const scoped_refptr<media::VideoFrame>& target,
1092 const base::Callback<void(bool)>& callback) {
1093 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
1094 src_subrect, target, callback);
1097 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1098 return delegated_frame_host_->CanCopyToVideoFrame();
1101 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1102 return delegated_frame_host_->CanSubscribeFrame();
1105 void RenderWidgetHostViewAura::BeginFrameSubscription(
1106 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1107 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
1110 void RenderWidgetHostViewAura::EndFrameSubscription() {
1111 delegated_frame_host_->EndFrameSubscription();
1114 #if defined(OS_WIN)
1115 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1116 return (legacy_render_widget_host_HWND_ != NULL);
1119 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1120 const std::vector<gfx::Rect>& rects) {
1121 // Check this before setting constrained_rects_, so that next time they're set
1122 // and we have a root window we don't early return.
1123 if (!window_->GetHost())
1124 return;
1126 if (rects == constrained_rects_)
1127 return;
1129 constrained_rects_ = rects;
1131 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1132 CutoutRectsParams params;
1133 params.widget = this;
1134 params.cutout_rects = constrained_rects_;
1135 params.geometry = &plugin_window_moves_;
1136 LPARAM lparam = reinterpret_cast<LPARAM>(&params);
1137 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1140 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1141 // Clip the cursor if chrome is running on regular desktop.
1142 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1143 RECT window_rect =
1144 gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
1145 ::ClipCursor(&window_rect);
1149 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1150 legacy_render_widget_host_HWND_ = NULL;
1151 legacy_window_destroyed_ = true;
1153 #endif
1155 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1156 uint32 output_surface_id,
1157 scoped_ptr<cc::CompositorFrame> frame) {
1158 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1160 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1161 if (!frame->delegated_frame_data)
1162 return;
1163 delegated_frame_host_->SwapDelegatedFrame(
1164 output_surface_id, frame->delegated_frame_data.Pass(),
1165 frame->metadata.device_scale_factor, frame->metadata.latency_info,
1166 &frame->metadata.satisfies_sequences);
1167 SelectionUpdated(frame->metadata.selection.is_editable,
1168 frame->metadata.selection.is_empty_text_form_control,
1169 ConvertSelectionBound(frame->metadata.selection.start),
1170 ConvertSelectionBound(frame->metadata.selection.end));
1173 void RenderWidgetHostViewAura::DidStopFlinging() {
1174 selection_controller_client_->OnScrollCompleted();
1177 #if defined(OS_WIN)
1178 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1179 gfx::NativeViewAccessible accessible_parent) {
1182 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1183 const {
1184 if (legacy_render_widget_host_HWND_) {
1185 return reinterpret_cast<gfx::NativeViewId>(
1186 legacy_render_widget_host_HWND_->hwnd());
1188 return NULL;
1190 #endif
1192 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1193 const gfx::Size& desired_size) {
1194 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1195 // matter what is returned here as GetBackingStore is the only caller of this
1196 // method. TODO(jbates) implement this if other Aura code needs it.
1197 return false;
1200 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1201 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1204 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1205 aura::Window* top_level = window_->GetToplevelWindow();
1206 gfx::Rect bounds(top_level->GetBoundsInScreen());
1208 #if defined(OS_WIN)
1209 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1210 // remove the legacy hwnd, so a better fix will need to be decided when that
1211 // happens.
1212 if (UsesNativeWindowFrame()) {
1213 // aura::Window doesn't take into account non-client area of native windows
1214 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1215 aura::WindowTreeHost* host = top_level->GetHost();
1216 if (!host)
1217 return top_level->GetBoundsInScreen();
1218 RECT window_rect = {0};
1219 HWND hwnd = host->GetAcceleratedWidget();
1220 ::GetWindowRect(hwnd, &window_rect);
1221 bounds = gfx::Rect(window_rect);
1223 // Maximized windows are outdented from the work area by the frame thickness
1224 // even though this "frame" is not painted. This confuses code (and people)
1225 // that think of a maximized window as corresponding exactly to the work
1226 // area. Correct for this by subtracting the frame thickness back off.
1227 if (::IsZoomed(hwnd)) {
1228 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
1229 GetSystemMetrics(SM_CYSIZEFRAME));
1231 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1232 GetSystemMetrics(SM_CXPADDEDBORDER));
1236 bounds = gfx::win::ScreenToDIPRect(bounds);
1237 #endif
1239 return bounds;
1242 void RenderWidgetHostViewAura::WheelEventAck(
1243 const blink::WebMouseWheelEvent& event,
1244 InputEventAckState ack_result) {
1245 if (overscroll_controller_) {
1246 overscroll_controller_->ReceivedEventACK(
1247 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1251 void RenderWidgetHostViewAura::GestureEventAck(
1252 const blink::WebGestureEvent& event,
1253 InputEventAckState ack_result) {
1254 if (overscroll_controller_) {
1255 overscroll_controller_->ReceivedEventACK(
1256 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1260 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1261 const TouchEventWithLatencyInfo& touch,
1262 InputEventAckState ack_result) {
1263 ScopedVector<ui::TouchEvent> events;
1264 aura::WindowTreeHost* host = window_->GetHost();
1265 // |host| is NULL during tests.
1266 if (!host)
1267 return;
1269 ui::EventResult result = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
1270 ? ui::ER_HANDLED
1271 : ui::ER_UNHANDLED;
1273 blink::WebTouchPoint::State required_state;
1274 switch (touch.event.type) {
1275 case blink::WebInputEvent::TouchStart:
1276 required_state = blink::WebTouchPoint::StatePressed;
1277 break;
1278 case blink::WebInputEvent::TouchEnd:
1279 required_state = blink::WebTouchPoint::StateReleased;
1280 break;
1281 case blink::WebInputEvent::TouchMove:
1282 required_state = blink::WebTouchPoint::StateMoved;
1283 break;
1284 case blink::WebInputEvent::TouchCancel:
1285 required_state = blink::WebTouchPoint::StateCancelled;
1286 break;
1287 default:
1288 required_state = blink::WebTouchPoint::StateUndefined;
1289 NOTREACHED();
1290 break;
1293 // Only send acks for one changed touch point.
1294 bool sent_ack = false;
1295 for (size_t i = 0; i < touch.event.touchesLength; ++i) {
1296 if (touch.event.touches[i].state == required_state) {
1297 DCHECK(!sent_ack);
1298 host->dispatcher()->ProcessedTouchEvent(touch.event.uniqueTouchEventId,
1299 window_, result);
1300 sent_ack = true;
1305 scoped_ptr<SyntheticGestureTarget>
1306 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1307 return scoped_ptr<SyntheticGestureTarget>(
1308 new SyntheticGestureTargetAura(host_));
1311 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
1312 const blink::WebInputEvent& input_event) {
1313 bool consumed = false;
1314 if (input_event.type == WebInputEvent::GestureFlingStart) {
1315 const WebGestureEvent& gesture_event =
1316 static_cast<const WebGestureEvent&>(input_event);
1317 // Zero-velocity touchpad flings are an Aura-specific signal that the
1318 // touchpad scroll has ended, and should not be forwarded to the renderer.
1319 if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
1320 !gesture_event.data.flingStart.velocityX &&
1321 !gesture_event.data.flingStart.velocityY) {
1322 consumed = true;
1326 if (overscroll_controller_)
1327 consumed |= overscroll_controller_->WillHandleEvent(input_event);
1329 // Touch events should always propagate to the renderer.
1330 if (WebTouchEvent::isTouchEventType(input_event.type))
1331 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1333 // Reporting consumed for a fling suggests that there's now an *active* fling
1334 // that requires both animation and a fling-end notification. However, the
1335 // OverscrollController consumes a fling to stop its propagation; it doesn't
1336 // actually tick a fling animation. Report no consumer to convey this.
1337 if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart)
1338 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
1340 return consumed ? INPUT_EVENT_ACK_STATE_CONSUMED
1341 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1344 BrowserAccessibilityManager*
1345 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1346 BrowserAccessibilityDelegate* delegate) {
1347 BrowserAccessibilityManager* manager = NULL;
1348 #if defined(OS_WIN)
1349 manager = new BrowserAccessibilityManagerWin(
1350 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
1351 #else
1352 manager = BrowserAccessibilityManager::Create(
1353 BrowserAccessibilityManager::GetEmptyDocument(), delegate);
1354 #endif
1355 return manager;
1358 gfx::AcceleratedWidget
1359 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1360 #if defined(OS_WIN)
1361 if (legacy_render_widget_host_HWND_)
1362 return legacy_render_widget_host_HWND_->hwnd();
1363 #endif
1364 return gfx::kNullAcceleratedWidget;
1367 gfx::NativeViewAccessible
1368 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1369 #if defined(OS_WIN)
1370 if (legacy_render_widget_host_HWND_)
1371 return legacy_render_widget_host_HWND_->window_accessible();
1372 #endif
1373 return NULL;
1376 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1377 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1380 void RenderWidgetHostViewAura::ShowDisambiguationPopup(
1381 const gfx::Rect& rect_pixels,
1382 const SkBitmap& zoomed_bitmap) {
1383 RenderViewHostDelegate* delegate = NULL;
1384 if (host_->IsRenderView())
1385 delegate = RenderViewHost::From(host_)->GetDelegate();
1386 // Suppress the link disambiguation popup if the virtual keyboard is currently
1387 // requested, as it doesn't interact well with the keyboard.
1388 if (delegate && delegate->IsVirtualKeyboardRequested())
1389 return;
1391 // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
1392 // by scaling it by the inverse of the device scale factor.
1393 gfx::RectF screen_target_rect_f(rect_pixels);
1394 screen_target_rect_f.Scale(1.0f / current_device_scale_factor_);
1395 disambiguation_target_rect_ = gfx::ToEnclosingRect(screen_target_rect_f);
1397 float scale = static_cast<float>(zoomed_bitmap.width()) /
1398 static_cast<float>(rect_pixels.width());
1399 gfx::Size zoomed_size(gfx::ToCeiledSize(
1400 gfx::ScaleSize(disambiguation_target_rect_.size(), scale)));
1402 // Save of a copy of the |last_scroll_offset_| for comparison when the copy
1403 // callback fires, to ensure that we haven't scrolled.
1404 disambiguation_scroll_offset_ = last_scroll_offset_;
1406 CopyFromCompositingSurface(
1407 disambiguation_target_rect_,
1408 zoomed_size,
1409 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
1410 weak_ptr_factory_.GetWeakPtr()),
1411 kN32_SkColorType);
1414 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1415 const SkBitmap& result,
1416 ReadbackResponse response) {
1417 if ((response != READBACK_SUCCESS) ||
1418 disambiguation_scroll_offset_ != last_scroll_offset_)
1419 return;
1421 // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
1422 // actually show the disambiguation popup.
1423 RenderViewHostDelegate* delegate = NULL;
1424 if (host_->IsRenderView())
1425 delegate = RenderViewHost::From(host_)->GetDelegate();
1426 RenderViewHostDelegateView* delegate_view = NULL;
1427 if (delegate) {
1428 delegate_view = delegate->GetDelegateView();
1429 if (delegate->IsVirtualKeyboardRequested())
1430 return;
1432 if (delegate_view) {
1433 delegate_view->ShowDisambiguationPopup(
1434 disambiguation_target_rect_,
1435 result,
1436 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture,
1437 weak_ptr_factory_.GetWeakPtr()),
1438 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse,
1439 weak_ptr_factory_.GetWeakPtr()));
1443 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1444 RenderViewHostDelegate* delegate = NULL;
1445 if (host_->IsRenderView())
1446 delegate = RenderViewHost::From(host_)->GetDelegate();
1447 RenderViewHostDelegateView* delegate_view = NULL;
1448 if (delegate)
1449 delegate_view = delegate->GetDelegateView();
1450 if (delegate_view)
1451 delegate_view->HideDisambiguationPopup();
1454 void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
1455 ui::GestureEvent* event) {
1456 blink::WebGestureEvent web_gesture = content::MakeWebGestureEvent(*event);
1457 // If we fail to make a WebGestureEvent that is a Tap from the provided event,
1458 // don't forward it to Blink.
1459 if (web_gesture.type < blink::WebInputEvent::Type::GestureTap ||
1460 web_gesture.type > blink::WebInputEvent::Type::GestureTapCancel)
1461 return;
1463 host_->ForwardGestureEvent(web_gesture);
1466 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1467 ui::MouseEvent* event) {
1468 blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(*event);
1469 host_->ForwardMouseEvent(web_mouse);
1472 bool RenderWidgetHostViewAura::LockMouse() {
1473 aura::Window* root_window = window_->GetRootWindow();
1474 if (!root_window)
1475 return false;
1477 if (mouse_locked_)
1478 return true;
1480 mouse_locked_ = true;
1481 #if !defined(OS_WIN)
1482 window_->SetCapture();
1483 #else
1484 UpdateMouseLockRegion();
1485 #endif
1486 aura::client::CursorClient* cursor_client =
1487 aura::client::GetCursorClient(root_window);
1488 if (cursor_client) {
1489 cursor_client->HideCursor();
1490 cursor_client->LockCursor();
1493 if (ShouldMoveToCenter()) {
1494 synthetic_move_sent_ = true;
1495 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1497 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1498 return true;
1501 void RenderWidgetHostViewAura::UnlockMouse() {
1502 tooltip_disabler_.reset();
1504 aura::Window* root_window = window_->GetRootWindow();
1505 if (!mouse_locked_ || !root_window)
1506 return;
1508 mouse_locked_ = false;
1510 #if !defined(OS_WIN)
1511 window_->ReleaseCapture();
1512 #else
1513 ::ClipCursor(NULL);
1514 #endif
1515 window_->MoveCursorTo(unlocked_mouse_position_);
1516 aura::client::CursorClient* cursor_client =
1517 aura::client::GetCursorClient(root_window);
1518 if (cursor_client) {
1519 cursor_client->UnlockCursor();
1520 cursor_client->ShowCursor();
1523 host_->LostMouseLock();
1526 ////////////////////////////////////////////////////////////////////////////////
1527 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1528 void RenderWidgetHostViewAura::SetCompositionText(
1529 const ui::CompositionText& composition) {
1530 if (!host_)
1531 return;
1533 // TODO(suzhe): convert both renderer_host and renderer to use
1534 // ui::CompositionText.
1535 std::vector<blink::WebCompositionUnderline> underlines;
1536 underlines.reserve(composition.underlines.size());
1537 for (std::vector<ui::CompositionUnderline>::const_iterator it =
1538 composition.underlines.begin();
1539 it != composition.underlines.end(); ++it) {
1540 underlines.push_back(
1541 blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset),
1542 static_cast<unsigned>(it->end_offset),
1543 it->color,
1544 it->thick,
1545 it->background_color));
1548 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1549 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1550 host_->ImeSetComposition(composition.text, underlines,
1551 composition.selection.end(),
1552 composition.selection.end());
1554 has_composition_text_ = !composition.text.empty();
1557 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1558 if (host_ && has_composition_text_) {
1559 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1560 false);
1562 has_composition_text_ = false;
1565 void RenderWidgetHostViewAura::ClearCompositionText() {
1566 if (host_ && has_composition_text_)
1567 host_->ImeCancelComposition();
1568 has_composition_text_ = false;
1571 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1572 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1573 if (host_)
1574 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1575 has_composition_text_ = false;
1578 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
1579 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1580 popup_child_host_view_->InsertChar(ch, flags);
1581 return;
1584 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1585 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
1586 double now = ui::EventTimeForNow().InSecondsF();
1587 // Send a blink::WebInputEvent::Char event to |host_|.
1588 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
1589 true /* is_char */,
1591 flags,
1592 now);
1593 ForwardKeyboardEvent(webkit_event);
1597 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1598 return text_input_type_;
1601 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1602 return text_input_mode_;
1605 int RenderWidgetHostViewAura::GetTextInputFlags() const {
1606 return text_input_flags_;
1609 bool RenderWidgetHostViewAura::CanComposeInline() const {
1610 return can_compose_inline_;
1613 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
1614 const gfx::Rect& rect) const {
1615 gfx::Point origin = rect.origin();
1616 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1618 aura::Window* root_window = window_->GetRootWindow();
1619 if (!root_window)
1620 return rect;
1621 aura::client::ScreenPositionClient* screen_position_client =
1622 aura::client::GetScreenPositionClient(root_window);
1623 if (!screen_position_client)
1624 return rect;
1625 screen_position_client->ConvertPointToScreen(window_, &origin);
1626 screen_position_client->ConvertPointToScreen(window_, &end);
1627 return gfx::Rect(origin.x(),
1628 origin.y(),
1629 end.x() - origin.x(),
1630 end.y() - origin.y());
1633 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
1634 const gfx::Rect& rect) const {
1635 gfx::Point origin = rect.origin();
1636 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1638 aura::Window* root_window = window_->GetRootWindow();
1639 if (root_window) {
1640 aura::client::ScreenPositionClient* screen_position_client =
1641 aura::client::GetScreenPositionClient(root_window);
1642 screen_position_client->ConvertPointFromScreen(window_, &origin);
1643 screen_position_client->ConvertPointFromScreen(window_, &end);
1644 return gfx::Rect(origin.x(),
1645 origin.y(),
1646 end.x() - origin.x(),
1647 end.y() - origin.y());
1650 return rect;
1653 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1654 return ConvertRectToScreen(
1655 ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_));
1658 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1659 uint32 index,
1660 gfx::Rect* rect) const {
1661 DCHECK(rect);
1662 if (index >= composition_character_bounds_.size())
1663 return false;
1664 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1665 return true;
1668 bool RenderWidgetHostViewAura::HasCompositionText() const {
1669 return has_composition_text_;
1672 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
1673 range->set_start(selection_text_offset_);
1674 range->set_end(selection_text_offset_ + selection_text_.length());
1675 return true;
1678 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1679 gfx::Range* range) const {
1680 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1681 NOTIMPLEMENTED();
1682 return false;
1685 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1686 range->set_start(selection_range_.start());
1687 range->set_end(selection_range_.end());
1688 return true;
1691 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1692 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1693 NOTIMPLEMENTED();
1694 return false;
1697 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1698 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1699 NOTIMPLEMENTED();
1700 return false;
1703 bool RenderWidgetHostViewAura::GetTextFromRange(
1704 const gfx::Range& range,
1705 base::string16* text) const {
1706 gfx::Range selection_text_range(selection_text_offset_,
1707 selection_text_offset_ + selection_text_.length());
1709 if (!selection_text_range.Contains(range)) {
1710 text->clear();
1711 return false;
1713 if (selection_text_range.EqualsIgnoringDirection(range)) {
1714 // Avoid calling substr whose performance is low.
1715 *text = selection_text_;
1716 } else {
1717 *text = selection_text_.substr(
1718 range.GetMin() - selection_text_offset_,
1719 range.length());
1721 return true;
1724 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1725 if (!host_)
1726 return;
1728 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1729 // TextEvent.
1732 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1733 base::i18n::TextDirection direction) {
1734 if (!host_)
1735 return false;
1736 host_->UpdateTextDirection(
1737 direction == base::i18n::RIGHT_TO_LEFT ?
1738 blink::WebTextDirectionRightToLeft :
1739 blink::WebTextDirectionLeftToRight);
1740 host_->NotifyTextDirection();
1741 return true;
1744 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1745 size_t before, size_t after) {
1746 RenderFrameHostImpl* rfh = GetFocusedFrame();
1747 if (rfh)
1748 rfh->ExtendSelectionAndDelete(before, after);
1751 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1752 gfx::Rect intersected_rect(
1753 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1755 if (intersected_rect.IsEmpty())
1756 return;
1758 host_->ScrollFocusedEditableNodeIntoRect(
1759 ConvertRectFromScreen(intersected_rect));
1762 bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id) {
1763 return false;
1766 void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id) {
1769 ////////////////////////////////////////////////////////////////////////////////
1770 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1772 void RenderWidgetHostViewAura::OnDisplayAdded(
1773 const gfx::Display& new_display) {
1776 void RenderWidgetHostViewAura::OnDisplayRemoved(
1777 const gfx::Display& old_display) {
1780 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
1781 const gfx::Display& display, uint32_t metrics) {
1782 // The screen info should be updated regardless of the metric change.
1783 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
1784 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
1785 UpdateScreenInfo(window_);
1786 current_cursor_.SetDisplayInfo(display);
1787 UpdateCursorIfOverSelf();
1791 ////////////////////////////////////////////////////////////////////////////////
1792 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1794 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1795 return gfx::Size();
1798 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
1799 return gfx::Size();
1802 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1803 const gfx::Rect& new_bounds) {
1804 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
1805 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1806 // WebContentsViewAura since changes to the Window's bounds need to be
1807 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1808 // SetBounds() itself. No matter how we got here, any redundant calls are
1809 // harmless.
1810 SetSize(new_bounds.size());
1812 if (GetInputMethod())
1813 GetInputMethod()->OnCaretBoundsChanged(this);
1816 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1817 if (mouse_locked_)
1818 return ui::kCursorNone;
1819 return current_cursor_.GetNativeCursor();
1822 int RenderWidgetHostViewAura::GetNonClientComponent(
1823 const gfx::Point& point) const {
1824 return HTCLIENT;
1827 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1828 aura::Window* child,
1829 const gfx::Point& location) {
1830 return true;
1833 bool RenderWidgetHostViewAura::CanFocus() {
1834 return popup_type_ == blink::WebPopupTypeNone;
1837 void RenderWidgetHostViewAura::OnCaptureLost() {
1838 host_->LostCapture();
1841 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
1842 NOTREACHED();
1845 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1846 float device_scale_factor) {
1847 if (!host_ || !window_->GetRootWindow())
1848 return;
1850 UpdateScreenInfo(window_);
1852 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1853 GetDisplayNearestWindow(window_);
1854 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
1855 current_cursor_.SetDisplayInfo(display);
1856 SnapToPhysicalPixelBoundary();
1859 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
1860 #if defined(OS_WIN)
1861 HWND parent = NULL;
1862 // If the tab was hidden and it's closed, host_->is_hidden would have been
1863 // reset to false in RenderWidgetHostImpl::RendererExited.
1864 if (!window_->GetRootWindow() || host_->is_hidden()) {
1865 parent = ui::GetHiddenWindow();
1866 } else {
1867 parent = window_->GetHost()->GetAcceleratedWidget();
1869 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1870 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
1872 // The LegacyRenderWidgetHostHWND instance is destroyed when its window is
1873 // destroyed. Normally we control when that happens via the Destroy call
1874 // in the dtor. However there may be cases where the window is destroyed
1875 // by Windows, i.e. the parent window is destroyed before the
1876 // RenderWidgetHostViewAura instance goes away etc. To avoid that we
1877 // destroy the LegacyRenderWidgetHostHWND instance here.
1878 if (legacy_render_widget_host_HWND_) {
1879 legacy_render_widget_host_HWND_->set_host(NULL);
1880 legacy_render_widget_host_HWND_->Destroy();
1881 // The Destroy call above will delete the LegacyRenderWidgetHostHWND
1882 // instance.
1883 legacy_render_widget_host_HWND_ = NULL;
1885 #endif
1887 // Make sure that the input method no longer references to this object before
1888 // this object is removed from the root window (i.e. this object loses access
1889 // to the input method).
1890 ui::InputMethod* input_method = GetInputMethod();
1891 if (input_method)
1892 input_method->DetachTextInputClient(this);
1894 if (overscroll_controller_)
1895 overscroll_controller_->Reset();
1898 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1899 // Ask the RWH to drop reference to us.
1900 if (!is_guest_view_hack_)
1901 host_->ViewDestroyed();
1903 delete this;
1906 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1909 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1910 return false;
1913 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1916 ////////////////////////////////////////////////////////////////////////////////
1917 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1919 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1920 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1922 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1923 popup_child_host_view_->OnKeyEvent(event);
1924 if (event->handled())
1925 return;
1928 // We need to handle the Escape key for Pepper Flash.
1929 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
1930 // Focus the window we were created from.
1931 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
1932 aura::Window* host = *(host_tracker_->windows().begin());
1933 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
1934 if (client) {
1935 // Calling host->Focus() may delete |this|. We create a local observer
1936 // for that. In that case we exit without further access to any members.
1937 aura::WindowTracker tracker;
1938 aura::Window* window = window_;
1939 tracker.Add(window);
1940 host->Focus();
1941 if (!tracker.Contains(window)) {
1942 event->SetHandled();
1943 return;
1947 Shutdown();
1948 } else {
1949 if (event->key_code() == ui::VKEY_RETURN) {
1950 // Do not forward return key release events if no press event was handled.
1951 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
1952 return;
1953 // Accept return key character events between press and release events.
1954 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
1957 // We don't have to communicate with an input method here.
1958 NativeWebKeyboardEvent webkit_event(*event);
1959 ForwardKeyboardEvent(webkit_event);
1961 event->SetHandled();
1964 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
1965 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
1967 if (mouse_locked_) {
1968 aura::client::CursorClient* cursor_client =
1969 aura::client::GetCursorClient(window_->GetRootWindow());
1970 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
1972 if (event->type() == ui::ET_MOUSEWHEEL) {
1973 blink::WebMouseWheelEvent mouse_wheel_event =
1974 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
1975 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
1976 host_->ForwardWheelEvent(mouse_wheel_event);
1977 return;
1980 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
1982 // If we receive non client mouse messages while we are in the locked state
1983 // it probably means that the mouse left the borders of our window and
1984 // needs to be moved back to the center.
1985 if (event->flags() & ui::EF_IS_NON_CLIENT) {
1986 synthetic_move_sent_ = true;
1987 window_->MoveCursorTo(center);
1988 return;
1991 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
1993 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
1994 event->type() == ui::ET_MOUSE_DRAGGED) &&
1995 mouse_event.x == center.x() && mouse_event.y == center.y();
1997 // For fractional scale factors, the conversion from pixels to dip and
1998 // vice versa could result in off by 1 or 2 errors which hurts us because
1999 // we want to avoid sending the artificial move to center event to the
2000 // renderer. Sending the move to center to the renderer cause the cursor
2001 // to bounce around the center of the screen leading to the lock operation
2002 // not working correctly.
2003 // Workaround is to treat a mouse move or drag event off by at most 2 px
2004 // from the center as a move to center event.
2005 if (synthetic_move_sent_ &&
2006 IsFractionalScaleFactor(current_device_scale_factor_)) {
2007 if (event->type() == ui::ET_MOUSE_MOVED ||
2008 event->type() == ui::ET_MOUSE_DRAGGED) {
2009 if ((abs(mouse_event.x - center.x()) <= 2) &&
2010 (abs(mouse_event.y - center.y()) <= 2)) {
2011 is_move_to_center_event = true;
2016 ModifyEventMovementAndCoords(&mouse_event);
2018 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2019 if (should_not_forward) {
2020 synthetic_move_sent_ = false;
2021 } else {
2022 // Check if the mouse has reached the border and needs to be centered.
2023 if (ShouldMoveToCenter()) {
2024 synthetic_move_sent_ = true;
2025 window_->MoveCursorTo(center);
2027 bool is_selection_popup = popup_child_host_view_ &&
2028 popup_child_host_view_->NeedsInputGrab();
2029 // Forward event to renderer.
2030 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2031 !(event->flags() & ui::EF_FROM_TOUCH)) {
2032 host_->ForwardMouseEvent(mouse_event);
2033 // Ensure that we get keyboard focus on mouse down as a plugin window
2034 // may have grabbed keyboard focus.
2035 if (event->type() == ui::ET_MOUSE_PRESSED)
2036 SetKeyboardFocus();
2039 return;
2042 // As the overscroll is handled during scroll events from the trackpad, the
2043 // RWHVA window is transformed by the overscroll controller. This transform
2044 // triggers a synthetic mouse-move event to be generated (by the aura
2045 // RootWindow). But this event interferes with the overscroll gesture. So,
2046 // ignore such synthetic mouse-move events if an overscroll gesture is in
2047 // progress.
2048 if (overscroll_controller_ &&
2049 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE &&
2050 event->flags() & ui::EF_IS_SYNTHESIZED &&
2051 (event->type() == ui::ET_MOUSE_ENTERED ||
2052 event->type() == ui::ET_MOUSE_EXITED ||
2053 event->type() == ui::ET_MOUSE_MOVED)) {
2054 event->StopPropagation();
2055 return;
2058 if (event->type() == ui::ET_MOUSEWHEEL) {
2059 #if defined(OS_WIN)
2060 // We get mouse wheel/scroll messages even if we are not in the foreground.
2061 // So here we check if we have any owned popup windows in the foreground and
2062 // dismiss them.
2063 aura::WindowTreeHost* host = window_->GetHost();
2064 if (host) {
2065 HWND parent = host->GetAcceleratedWidget();
2066 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2067 EnumThreadWindows(GetCurrentThreadId(),
2068 DismissOwnedPopups,
2069 reinterpret_cast<LPARAM>(toplevel_hwnd));
2071 #endif
2072 // The Disambiguation popup does not parent itself from this window, so we
2073 // manually dismiss it.
2074 HideDisambiguationPopup();
2076 blink::WebMouseWheelEvent mouse_wheel_event =
2077 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2078 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2079 host_->ForwardWheelEvent(mouse_wheel_event);
2080 } else {
2081 bool is_selection_popup = popup_child_host_view_ &&
2082 popup_child_host_view_->NeedsInputGrab();
2083 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2084 !(event->flags() & ui::EF_FROM_TOUCH)) {
2085 // Confirm existing composition text on mouse press, to make sure
2086 // the input caret won't be moved with an ongoing composition text.
2087 if (event->type() == ui::ET_MOUSE_PRESSED)
2088 FinishImeCompositionSession();
2090 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2091 ModifyEventMovementAndCoords(&mouse_event);
2092 host_->ForwardMouseEvent(mouse_event);
2093 // Ensure that we get keyboard focus on mouse down as a plugin window may
2094 // have grabbed keyboard focus.
2095 if (event->type() == ui::ET_MOUSE_PRESSED)
2096 SetKeyboardFocus();
2100 switch (event->type()) {
2101 case ui::ET_MOUSE_PRESSED:
2102 window_->SetCapture();
2103 break;
2104 case ui::ET_MOUSE_RELEASED:
2105 if (!NeedsMouseCapture())
2106 window_->ReleaseCapture();
2107 break;
2108 default:
2109 break;
2112 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2113 // note that it might be something other than a WebContentsViewAura instance.
2114 // TODO(pkotwicz): Find a better way of doing this.
2115 // In fullscreen mode which is typically used by flash, don't forward
2116 // the mouse events to the parent. The renderer and the plugin process
2117 // handle these events.
2118 if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
2119 !(event->flags() & ui::EF_FROM_TOUCH)) {
2120 event->ConvertLocationToTarget(window_, window_->parent());
2121 window_->parent()->delegate()->OnMouseEvent(event);
2124 if (!IsXButtonUpEvent(event))
2125 event->SetHandled();
2128 uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
2129 const gfx::Point& point,
2130 gfx::Point* transformed_point) {
2131 return cc::SurfaceIdAllocator::NamespaceForId(
2132 delegated_frame_host_->SurfaceIdAtPoint(point, transformed_point));
2135 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2136 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2138 if (event->type() == ui::ET_SCROLL) {
2139 #if !defined(OS_WIN)
2140 // TODO(ananta)
2141 // Investigate if this is true for Windows 8 Metro ASH as well.
2142 if (event->finger_count() != 2)
2143 return;
2144 #endif
2145 blink::WebGestureEvent gesture_event =
2146 MakeWebGestureEventFlingCancel();
2147 host_->ForwardGestureEvent(gesture_event);
2148 blink::WebMouseWheelEvent mouse_wheel_event =
2149 MakeWebMouseWheelEvent(*event);
2150 host_->ForwardWheelEvent(mouse_wheel_event);
2151 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2152 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2153 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2154 blink::WebGestureEvent gesture_event = MakeWebGestureEvent(*event);
2155 host_->ForwardGestureEvent(gesture_event);
2156 if (event->type() == ui::ET_SCROLL_FLING_START)
2157 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2160 event->SetHandled();
2163 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2164 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2166 bool had_no_pointer = !pointer_state_.GetPointerCount();
2168 // Update the touch event first.
2169 if (!pointer_state_.OnTouch(*event)) {
2170 event->StopPropagation();
2171 return;
2174 blink::WebTouchEvent touch_event;
2175 bool handled = selection_controller_->WillHandleTouchEvent(pointer_state_);
2176 if (handled) {
2177 event->SetHandled();
2178 } else {
2179 touch_event = ui::CreateWebTouchEventFromMotionEvent(
2180 pointer_state_, event->may_cause_scrolling());
2182 pointer_state_.CleanupRemovedTouchPoints(*event);
2184 if (handled)
2185 return;
2187 if (had_no_pointer)
2188 selection_controller_client_->OnTouchDown();
2189 if (!pointer_state_.GetPointerCount())
2190 selection_controller_client_->OnTouchUp();
2192 // It is important to always mark events as being handled asynchronously when
2193 // they are forwarded. This ensures that the current event does not get
2194 // processed by the gesture recognizer before events currently awaiting
2195 // dispatch in the touch queue.
2196 event->DisableSynchronousHandling();
2198 // Set unchanged touch point to StateStationary for touchmove and
2199 // touchcancel to make sure only send one ack per WebTouchEvent.
2200 MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
2201 host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency());
2204 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2205 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2207 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2208 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2209 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
2210 event->SetHandled();
2211 return;
2214 HandleGestureForTouchSelection(event);
2215 if (event->handled())
2216 return;
2218 // Confirm existing composition text on TAP gesture, to make sure the input
2219 // caret won't be moved with an ongoing composition text.
2220 if (event->type() == ui::ET_GESTURE_TAP)
2221 FinishImeCompositionSession();
2223 blink::WebGestureEvent gesture = MakeWebGestureEvent(*event);
2224 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
2225 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2226 // event to stop any in-progress flings.
2227 blink::WebGestureEvent fling_cancel = gesture;
2228 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
2229 fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
2230 host_->ForwardGestureEvent(fling_cancel);
2233 if (gesture.type != blink::WebInputEvent::Undefined) {
2234 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
2236 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
2237 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
2238 event->type() == ui::ET_GESTURE_SCROLL_END) {
2239 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
2240 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
2241 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
2245 // If a gesture is not processed by the webpage, then WebKit processes it
2246 // (e.g. generates synthetic mouse events).
2247 event->SetHandled();
2250 ////////////////////////////////////////////////////////////////////////////////
2251 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2253 bool RenderWidgetHostViewAura::ShouldActivate() const {
2254 aura::WindowTreeHost* host = window_->GetHost();
2255 if (!host)
2256 return true;
2257 const ui::Event* event = host->dispatcher()->current_event();
2258 if (!event)
2259 return true;
2260 return is_fullscreen_;
2263 ////////////////////////////////////////////////////////////////////////////////
2264 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2266 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2267 NotifyRendererOfCursorVisibilityState(is_visible);
2270 ////////////////////////////////////////////////////////////////////////////////
2271 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2273 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2274 aura::Window* lost_focus) {
2275 DCHECK(window_ == gained_focus || window_ == lost_focus);
2276 if (window_ == gained_focus) {
2277 // We need to honor input bypass if the associated tab is does not want
2278 // input. This gives the current focused window a chance to be the text
2279 // input client and handle events.
2280 if (host_->ignore_input_events())
2281 return;
2283 host_->GotFocus();
2284 host_->SetActive(true);
2286 ui::InputMethod* input_method = GetInputMethod();
2287 if (input_method) {
2288 // Ask the system-wide IME to send all TextInputClient messages to |this|
2289 // object.
2290 input_method->SetFocusedTextInputClient(this);
2292 // Often the application can set focus to the view in response to a key
2293 // down. However the following char event shouldn't be sent to the web
2294 // page.
2295 host_->SuppressNextCharEvents();
2298 BrowserAccessibilityManager* manager =
2299 host_->GetRootBrowserAccessibilityManager();
2300 if (manager)
2301 manager->OnWindowFocused();
2302 } else if (window_ == lost_focus) {
2303 host_->SetActive(false);
2304 host_->Blur();
2306 DetachFromInputMethod();
2308 selection_controller_->HideAndDisallowShowingAutomatically();
2310 if (overscroll_controller_)
2311 overscroll_controller_->Cancel();
2313 BrowserAccessibilityManager* manager =
2314 host_->GetRootBrowserAccessibilityManager();
2315 if (manager)
2316 manager->OnWindowBlurred();
2318 // If we lose the focus while fullscreen, close the window; Pepper Flash
2319 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2320 // window if we lose the focus to a window on another display.
2321 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2322 bool focusing_other_display =
2323 gained_focus && screen->GetNumDisplays() > 1 &&
2324 (screen->GetDisplayNearestWindow(window_).id() !=
2325 screen->GetDisplayNearestWindow(gained_focus).id());
2326 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
2327 #if defined(OS_WIN)
2328 // On Windows, if we are switching to a non Aura Window on a different
2329 // screen we should not close the fullscreen window.
2330 if (!gained_focus) {
2331 POINT point = {0};
2332 ::GetCursorPos(&point);
2333 if (screen->GetDisplayNearestWindow(window_).id() !=
2334 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2335 return;
2337 #endif
2338 Shutdown();
2339 return;
2342 // Close the child popup window if we lose focus (e.g. due to a JS alert or
2343 // system modal dialog). This is particularly important if
2344 // |popup_child_host_view_| has mouse capture.
2345 if (popup_child_host_view_)
2346 popup_child_host_view_->Shutdown();
2350 ////////////////////////////////////////////////////////////////////////////////
2351 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2353 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
2354 const gfx::Point& new_origin) {
2355 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2356 "new_origin", new_origin.ToString());
2358 UpdateScreenInfo(window_);
2361 ////////////////////////////////////////////////////////////////////////////////
2362 // RenderWidgetHostViewAura, private:
2364 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2365 selection_controller_.reset();
2366 selection_controller_client_.reset();
2367 delegated_frame_host_.reset();
2368 window_observer_.reset();
2369 if (window_->GetHost())
2370 window_->GetHost()->RemoveObserver(this);
2371 UnlockMouse();
2372 if (popup_parent_host_view_) {
2373 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
2374 popup_parent_host_view_->popup_child_host_view_ == this);
2375 popup_parent_host_view_->popup_child_host_view_ = NULL;
2377 if (popup_child_host_view_) {
2378 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
2379 popup_child_host_view_->popup_parent_host_view_ == this);
2380 popup_child_host_view_->popup_parent_host_view_ = NULL;
2382 event_filter_for_popup_exit_.reset();
2383 aura::client::SetTooltipText(window_, NULL);
2384 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
2386 // This call is usually no-op since |this| object is already removed from the
2387 // Aura root window and we don't have a way to get an input method object
2388 // associated with the window, but just in case.
2389 DetachFromInputMethod();
2391 #if defined(OS_WIN)
2392 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2393 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2394 // be set to NULL.
2395 DCHECK(!legacy_render_widget_host_HWND_);
2396 #endif
2399 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2400 aura::Window* root_window = window_->GetRootWindow();
2401 if (!root_window)
2402 return;
2404 gfx::Point root_window_point =
2405 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2406 aura::client::ScreenPositionClient* screen_position_client =
2407 aura::client::GetScreenPositionClient(root_window);
2408 if (screen_position_client) {
2409 screen_position_client->ConvertPointFromScreen(
2410 root_window, &root_window_point);
2413 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
2414 return;
2416 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
2417 // Do not show loading cursor when the cursor is currently hidden.
2418 if (is_loading_ && cursor != ui::kCursorNone)
2419 cursor = ui::kCursorPointer;
2421 aura::client::CursorClient* cursor_client =
2422 aura::client::GetCursorClient(root_window);
2423 if (cursor_client) {
2424 cursor_client->SetCursor(cursor);
2428 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2429 aura::Window* root_window = window_->GetRootWindow();
2430 if (!root_window)
2431 return NULL;
2432 return root_window->GetHost()->GetInputMethod();
2435 void RenderWidgetHostViewAura::Shutdown() {
2436 if (!in_shutdown_) {
2437 in_shutdown_ = true;
2438 host_->Shutdown();
2442 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2443 return popup_type_ == blink::WebPopupTypePage;
2446 bool RenderWidgetHostViewAura::NeedsMouseCapture() {
2447 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2448 return NeedsInputGrab();
2449 #endif
2450 return false;
2453 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2454 if (!has_composition_text_)
2455 return;
2456 if (host_) {
2457 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2458 false);
2460 ImeCancelComposition();
2463 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2464 blink::WebMouseEvent* event) {
2465 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2466 // reset any global_mouse_position set previously.
2467 if (event->type == blink::WebInputEvent::MouseEnter ||
2468 event->type == blink::WebInputEvent::MouseLeave)
2469 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2471 // Movement is computed by taking the difference of the new cursor position
2472 // and the previous. Under mouse lock the cursor will be warped back to the
2473 // center so that we are not limited by clipping boundaries.
2474 // We do not measure movement as the delta from cursor to center because
2475 // we may receive more mouse movement events before our warp has taken
2476 // effect.
2477 event->movementX = event->globalX - global_mouse_position_.x();
2478 event->movementY = event->globalY - global_mouse_position_.y();
2480 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2482 // Under mouse lock, coordinates of mouse are locked to what they were when
2483 // mouse lock was entered.
2484 if (mouse_locked_) {
2485 event->x = unlocked_mouse_position_.x();
2486 event->y = unlocked_mouse_position_.y();
2487 event->windowX = unlocked_mouse_position_.x();
2488 event->windowY = unlocked_mouse_position_.y();
2489 event->globalX = unlocked_global_mouse_position_.x();
2490 event->globalY = unlocked_global_mouse_position_.y();
2491 } else {
2492 unlocked_mouse_position_.SetPoint(event->x, event->y);
2493 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2497 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2498 bool is_visible) {
2499 if (host_->is_hidden() ||
2500 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2501 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2502 return;
2504 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2505 host_->SendCursorVisibilityState(is_visible);
2508 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
2509 if (!enabled)
2510 overscroll_controller_.reset();
2511 else if (!overscroll_controller_)
2512 overscroll_controller_.reset(new OverscrollController());
2515 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
2516 // The top left corner of our view in window coordinates might not land on a
2517 // device pixel boundary if we have a non-integer device scale. In that case,
2518 // to avoid the web contents area looking blurry we translate the web contents
2519 // in the +x, +y direction to land on the nearest pixel boundary. This may
2520 // cause the bottom and right edges to be clipped slightly, but that's ok.
2521 aura::Window* snapped = NULL;
2522 // On desktop, use the root window. On alternative environment (ash),
2523 // use the toplevel window which must be already snapped.
2524 if (gfx::Screen::GetScreenFor(window_) !=
2525 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
2526 snapped = window_->GetRootWindow();
2527 } else {
2528 snapped = window_->GetToplevelWindow();
2530 if (snapped && snapped != window_)
2531 ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
2533 has_snapped_to_boundary_ = true;
2536 void RenderWidgetHostViewAura::OnShowContextMenu() {
2537 #if defined(OS_WIN)
2538 showing_context_menu_ = true;
2539 #endif
2542 void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
2543 scoped_ptr<TouchSelectionControllerClientAura> client) {
2544 selection_controller_client_.swap(client);
2545 CreateSelectionController();
2548 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
2549 SnapToPhysicalPixelBoundary();
2550 // Don't recursively call SetBounds if this bounds update is the result of
2551 // a Window::SetBoundsInternal call.
2552 if (!in_bounds_changed_)
2553 window_->SetBounds(rect);
2554 host_->WasResized();
2555 delegated_frame_host_->WasResized();
2556 #if defined(OS_WIN)
2557 // Create the legacy dummy window which corresponds to the bounds of the
2558 // webcontents. This will be passed as the container window for windowless
2559 // plugins.
2560 // Plugins like Flash assume the container window which is returned via the
2561 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
2562 // This is not true in Aura where we have only HWND which is the main Aura
2563 // window. If we return this window to plugins like Flash then it causes the
2564 // coordinate translations done by these plugins to break.
2565 // Additonally the legacy dummy window is needed for accessibility and for
2566 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
2567 if (!legacy_window_destroyed_ && GetNativeViewId()) {
2568 if (!legacy_render_widget_host_HWND_) {
2569 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
2570 reinterpret_cast<HWND>(GetNativeViewId()));
2572 if (legacy_render_widget_host_HWND_) {
2573 legacy_render_widget_host_HWND_->set_host(this);
2574 legacy_render_widget_host_HWND_->SetBounds(
2575 window_->GetBoundsInRootWindow());
2576 // There are cases where the parent window is created, made visible and
2577 // the associated RenderWidget is also visible before the
2578 // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
2579 // here.
2580 if (!host_->is_hidden())
2581 legacy_render_widget_host_HWND_->Show();
2585 if (mouse_locked_)
2586 UpdateMouseLockRegion();
2587 #endif
2590 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2591 const gfx::Rect& rect,
2592 const gfx::Rect& clip) {
2593 if (!clip.IsEmpty()) {
2594 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
2595 if (!to_paint.IsEmpty())
2596 window_->SchedulePaintInRect(to_paint);
2597 } else {
2598 window_->SchedulePaintInRect(rect);
2602 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2603 gfx::Rect rect = window_->bounds();
2604 rect = ConvertRectToScreen(rect);
2605 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
2606 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
2608 return global_mouse_position_.x() < rect.x() + border_x ||
2609 global_mouse_position_.x() > rect.right() - border_x ||
2610 global_mouse_position_.y() < rect.y() + border_y ||
2611 global_mouse_position_.y() > rect.bottom() - border_y;
2614 void RenderWidgetHostViewAura::AddedToRootWindow() {
2615 window_->GetHost()->AddObserver(this);
2616 UpdateScreenInfo(window_);
2618 aura::client::CursorClient* cursor_client =
2619 aura::client::GetCursorClient(window_->GetRootWindow());
2620 if (cursor_client) {
2621 cursor_client->AddObserver(this);
2622 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
2624 if (HasFocus()) {
2625 ui::InputMethod* input_method = GetInputMethod();
2626 if (input_method)
2627 input_method->SetFocusedTextInputClient(this);
2630 #if defined(OS_WIN)
2631 // The parent may have changed here. Ensure that the legacy window is
2632 // reparented accordingly.
2633 if (legacy_render_widget_host_HWND_)
2634 legacy_render_widget_host_HWND_->UpdateParent(
2635 reinterpret_cast<HWND>(GetNativeViewId()));
2636 #endif
2638 delegated_frame_host_->SetCompositor(window_->GetHost()->compositor());
2639 if (window_->GetHost()->compositor())
2640 begin_frame_observer_proxy_.SetCompositor(window_->GetHost()->compositor());
2643 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2644 aura::client::CursorClient* cursor_client =
2645 aura::client::GetCursorClient(window_->GetRootWindow());
2646 if (cursor_client)
2647 cursor_client->RemoveObserver(this);
2649 DetachFromInputMethod();
2651 window_->GetHost()->RemoveObserver(this);
2652 delegated_frame_host_->ResetCompositor();
2653 begin_frame_observer_proxy_.ResetCompositor();
2655 #if defined(OS_WIN)
2656 // Update the legacy window's parent temporarily to the desktop window. It
2657 // will eventually get reparented to the right root.
2658 if (legacy_render_widget_host_HWND_)
2659 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
2660 #endif
2663 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2664 ui::InputMethod* input_method = GetInputMethod();
2665 if (input_method)
2666 input_method->DetachTextInputClient(this);
2669 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2670 const NativeWebKeyboardEvent& event) {
2671 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2672 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
2673 ui::GetTextEditKeyBindingsDelegate();
2674 std::vector<ui::TextEditCommandAuraLinux> commands;
2675 if (!event.skip_in_browser &&
2676 keybinding_delegate &&
2677 event.os_event &&
2678 keybinding_delegate->MatchEvent(*event.os_event, &commands)) {
2679 // Transform from ui/ types to content/ types.
2680 EditCommands edit_commands;
2681 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it =
2682 commands.begin(); it != commands.end(); ++it) {
2683 edit_commands.push_back(EditCommand(it->GetCommandString(),
2684 it->argument()));
2686 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2687 host_->GetRoutingID(), edit_commands));
2688 NativeWebKeyboardEvent copy_event(event);
2689 copy_event.match_edit_command = true;
2690 host_->ForwardKeyboardEvent(copy_event);
2691 return;
2693 #endif
2695 host_->ForwardKeyboardEvent(event);
2698 void RenderWidgetHostViewAura::SelectionUpdated(bool is_editable,
2699 bool is_empty_text_form_control,
2700 const ui::SelectionBound& start,
2701 const ui::SelectionBound& end) {
2702 selection_controller_->OnSelectionEditable(is_editable);
2703 selection_controller_->OnSelectionEmpty(is_empty_text_form_control);
2704 selection_controller_->OnSelectionBoundsChanged(start, end);
2707 void RenderWidgetHostViewAura::CreateSelectionController() {
2708 ui::TouchSelectionController::Config tsc_config;
2709 tsc_config.tap_timeout = base::TimeDelta::FromMilliseconds(
2710 ui::GestureConfiguration::GetInstance()->show_press_delay_in_ms());
2711 tsc_config.tap_slop = ui::GestureConfiguration::GetInstance()
2712 ->max_touch_move_in_pixels_for_click();
2713 tsc_config.show_on_tap_for_empty_editable = true;
2714 tsc_config.enable_longpress_drag_selection = false;
2715 selection_controller_.reset(new ui::TouchSelectionController(
2716 selection_controller_client_.get(), tsc_config));
2719 void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
2720 ui::GestureEvent* event) {
2721 switch (event->type()) {
2722 case ui::ET_GESTURE_LONG_PRESS:
2723 if (selection_controller_->WillHandleLongPressEvent(
2724 base::TimeTicks() + event->time_stamp(), event->location_f())) {
2725 event->SetHandled();
2727 break;
2728 case ui::ET_GESTURE_TAP:
2729 if (selection_controller_->WillHandleTapEvent(event->location_f()))
2730 event->SetHandled();
2731 break;
2732 case ui::ET_GESTURE_SCROLL_BEGIN:
2733 selection_controller_client_->OnScrollStarted();
2734 break;
2735 case ui::ET_GESTURE_SCROLL_END:
2736 selection_controller_client_->OnScrollCompleted();
2737 break;
2738 default:
2739 break;
2743 ////////////////////////////////////////////////////////////////////////////////
2744 // DelegatedFrameHost, public:
2746 ui::Layer* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const {
2747 return window_->layer();
2750 bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const {
2751 return !host_->is_hidden();
2754 gfx::Size RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const {
2755 return window_->bounds().size();
2758 bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const {
2759 #if !defined(OS_CHROMEOS)
2760 // On Windows and Linux, holding pointer moves will not help throttling
2761 // resizes.
2762 // TODO(piman): on Windows we need to block (nested message loop?) the
2763 // WM_SIZE event. On Linux we need to throttle at the WM level using
2764 // _NET_WM_SYNC_REQUEST.
2765 return false;
2766 #else
2767 if (host_->auto_resize_enabled())
2768 return false;
2769 return true;
2770 #endif
2773 scoped_ptr<ResizeLock>
2774 RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock(
2775 bool defer_compositor_lock) {
2776 gfx::Size desired_size = window_->bounds().size();
2777 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
2778 window_->GetHost(),
2779 desired_size,
2780 defer_compositor_lock,
2781 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2784 void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() {
2785 host_->WasResized();
2788 void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck(
2789 int output_surface_id,
2790 const cc::CompositorFrameAck& ack) {
2791 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
2792 output_surface_id, ack));
2795 void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
2796 int output_surface_id,
2797 const cc::CompositorFrameAck& ack) {
2798 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
2799 output_surface_id, ack));
2802 void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
2803 host_->ScheduleComposite();
2806 void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters(
2807 const base::TimeTicks& timebase,
2808 const base::TimeDelta& interval) {
2809 host_->UpdateVSyncParameters(timebase, interval);
2812 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
2813 ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
2816 uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
2817 return delegated_frame_host_->GetSurfaceIdNamespace();
2820 ////////////////////////////////////////////////////////////////////////////////
2821 // RenderWidgetHostViewBase, public:
2823 // static
2824 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2825 GetScreenInfoForWindow(results, NULL);
2828 } // namespace content