Account for flings consumed by the InputRouterClient
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura.cc
blob563c91fef0538083ec3ac7d4b6f08cd097a4ed45
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/web_input_event_util.h"
34 #include "content/browser/renderer_host/overscroll_controller.h"
35 #include "content/browser/renderer_host/render_view_host_delegate.h"
36 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
37 #include "content/browser/renderer_host/render_view_host_impl.h"
38 #include "content/browser/renderer_host/render_widget_host_impl.h"
39 #include "content/browser/renderer_host/ui_events_helper.h"
40 #include "content/browser/renderer_host/web_input_event_aura.h"
41 #include "content/common/gpu/client/gl_helper.h"
42 #include "content/common/gpu/gpu_messages.h"
43 #include "content/common/view_messages.h"
44 #include "content/public/browser/content_browser_client.h"
45 #include "content/public/browser/overscroll_configuration.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
48 #include "content/public/browser/user_metrics.h"
49 #include "content/public/common/content_switches.h"
50 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
51 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
52 #include "third_party/WebKit/public/web/WebInputEvent.h"
53 #include "ui/aura/client/aura_constants.h"
54 #include "ui/aura/client/cursor_client.h"
55 #include "ui/aura/client/cursor_client_observer.h"
56 #include "ui/aura/client/focus_client.h"
57 #include "ui/aura/client/screen_position_client.h"
58 #include "ui/aura/client/window_tree_client.h"
59 #include "ui/aura/env.h"
60 #include "ui/aura/window.h"
61 #include "ui/aura/window_event_dispatcher.h"
62 #include "ui/aura/window_observer.h"
63 #include "ui/aura/window_tracker.h"
64 #include "ui/aura/window_tree_host.h"
65 #include "ui/base/clipboard/scoped_clipboard_writer.h"
66 #include "ui/base/hit_test.h"
67 #include "ui/base/ime/input_method.h"
68 #include "ui/base/ui_base_types.h"
69 #include "ui/compositor/compositor_vsync_manager.h"
70 #include "ui/compositor/dip_util.h"
71 #include "ui/events/blink/blink_event_util.h"
72 #include "ui/events/event.h"
73 #include "ui/events/event_utils.h"
74 #include "ui/events/gestures/gesture_recognizer.h"
75 #include "ui/gfx/canvas.h"
76 #include "ui/gfx/display.h"
77 #include "ui/gfx/geometry/rect_conversions.h"
78 #include "ui/gfx/geometry/size_conversions.h"
79 #include "ui/gfx/screen.h"
80 #include "ui/gfx/skia_util.h"
81 #include "ui/wm/public/activation_client.h"
82 #include "ui/wm/public/scoped_tooltip_disabler.h"
83 #include "ui/wm/public/tooltip_client.h"
84 #include "ui/wm/public/transient_window_client.h"
85 #include "ui/wm/public/window_types.h"
87 #if defined(OS_WIN)
88 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
89 #include "content/browser/accessibility/browser_accessibility_win.h"
90 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
91 #include "content/common/plugin_constants_win.h"
92 #include "ui/base/win/hidden_window.h"
93 #include "ui/gfx/gdi_util.h"
94 #include "ui/gfx/win/dpi.h"
95 #endif
97 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
98 #include "content/common/input_messages.h"
99 #include "ui/events/linux/text_edit_command_auralinux.h"
100 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
101 #endif
103 using gfx::RectToSkIRect;
104 using gfx::SkIRectToRect;
106 using blink::WebScreenInfo;
107 using blink::WebInputEvent;
108 using blink::WebGestureEvent;
109 using blink::WebTouchEvent;
111 namespace content {
113 namespace {
115 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
116 // the border of the view, in order to get valid movement information. However,
117 // forcing the cursor back to the center of the view after each mouse move
118 // doesn't work well. It reduces the frequency of useful mouse move messages
119 // significantly. Therefore, we move the cursor to the center of the view only
120 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
121 // of the border area, in percentage of the corresponding dimension.
122 const int kMouseLockBorderPercentage = 15;
124 // When accelerated compositing is enabled and a widget resize is pending,
125 // we delay further resizes of the UI. The following constant is the maximum
126 // length of time that we should delay further UI resizes while waiting for a
127 // resized frame from a renderer.
128 const int kResizeLockTimeoutMs = 67;
130 #if defined(OS_WIN)
131 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
132 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
134 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
135 RenderWidgetHostViewAura* widget =
136 reinterpret_cast<RenderWidgetHostViewAura*>(param);
137 if (GetProp(window, kWidgetOwnerProperty) == widget) {
138 // Properties set on HWNDs must be removed to avoid leaks.
139 RemoveProp(window, kWidgetOwnerProperty);
140 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
142 return TRUE;
145 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
146 RenderWidgetHostViewAura* widget =
147 reinterpret_cast<RenderWidgetHostViewAura*>(param);
148 if (GetProp(window, kWidgetOwnerProperty) == widget)
149 SetParent(window, ui::GetHiddenWindow());
150 return TRUE;
153 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
154 RenderWidgetHostViewAura* widget =
155 reinterpret_cast<RenderWidgetHostViewAura*>(param);
157 if (GetProp(window, kWidgetOwnerProperty) == widget &&
158 widget->GetNativeView()->GetHost()) {
159 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
160 SetParent(window, parent);
162 return TRUE;
165 struct CutoutRectsParams {
166 RenderWidgetHostViewAura* widget;
167 std::vector<gfx::Rect> cutout_rects;
168 std::map<HWND, WebPluginGeometry>* geometry;
171 // Used to update the region for the windowed plugin to draw in. We start with
172 // the clip rect from the renderer, then remove the cutout rects from the
173 // renderer, and then remove the transient windows from the root window and the
174 // constrained windows from the parent window.
175 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
176 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
178 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
179 // First calculate the offset of this plugin from the root window, since
180 // the cutouts are relative to the root window.
181 HWND parent =
182 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
183 POINT offset;
184 offset.x = offset.y = 0;
185 MapWindowPoints(window, parent, &offset, 1);
187 // Now get the cached clip rect and cutouts for this plugin window that came
188 // from the renderer.
189 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
190 while (i != params->geometry->end() &&
191 i->second.window != window &&
192 GetParent(i->second.window) != window) {
193 ++i;
196 if (i == params->geometry->end()) {
197 NOTREACHED();
198 return TRUE;
201 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
202 i->second.clip_rect.y(),
203 i->second.clip_rect.right(),
204 i->second.clip_rect.bottom());
205 // We start with the cutout rects that came from the renderer, then add the
206 // ones that came from transient and constrained windows.
207 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
208 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
209 gfx::Rect offset_cutout = params->cutout_rects[i];
210 offset_cutout.Offset(-offset.x, -offset.y);
211 cutout_rects.push_back(offset_cutout);
213 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
214 // If we don't have any cutout rects then no point in messing with the
215 // window region.
216 if (cutout_rects.size())
217 SetWindowRgn(window, hrgn, TRUE);
219 return TRUE;
222 // A callback function for EnumThreadWindows to enumerate and dismiss
223 // any owned popup windows.
224 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
225 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
227 if (::IsWindowVisible(window)) {
228 const HWND owner = ::GetWindow(window, GW_OWNER);
229 if (toplevel_hwnd == owner) {
230 ::PostMessage(window, WM_CANCELMODE, 0, 0);
234 return TRUE;
236 #endif
238 // We don't mark these as handled so that they're sent back to the
239 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
240 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
241 #if defined(OS_WIN)
242 switch (event->native_event().message) {
243 case WM_XBUTTONUP:
244 case WM_NCXBUTTONUP:
245 return true;
247 #endif
248 return false;
251 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
252 const gfx::Display display = window ?
253 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
254 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
255 results->rect = display.bounds();
256 results->availableRect = display.work_area();
257 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
258 results->depth = 24;
259 results->depthPerComponent = 8;
260 results->deviceScaleFactor = display.device_scale_factor();
262 // The Display rotation and the WebScreenInfo orientation are not the same
263 // angle. The former is the physical display rotation while the later is the
264 // rotation required by the content to be shown properly on the screen, in
265 // other words, relative to the physical display.
266 results->orientationAngle = display.RotationAsDegree();
267 if (results->orientationAngle == 90)
268 results->orientationAngle = 270;
269 else if (results->orientationAngle == 270)
270 results->orientationAngle = 90;
272 results->orientationType =
273 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
276 bool IsFractionalScaleFactor(float scale_factor) {
277 return (scale_factor - static_cast<int>(scale_factor)) > 0;
280 // Reset unchanged touch point to StateStationary for touchmove and
281 // touchcancel.
282 void MarkUnchangedTouchPointsAsStationary(
283 blink::WebTouchEvent* event,
284 int changed_touch_id) {
285 if (event->type == blink::WebInputEvent::TouchMove ||
286 event->type == blink::WebInputEvent::TouchCancel) {
287 for (size_t i = 0; i < event->touchesLength; ++i) {
288 if (event->touches[i].id != changed_touch_id)
289 event->touches[i].state = blink::WebTouchPoint::StateStationary;
294 } // namespace
296 // We need to watch for mouse events outside a Web Popup or its parent
297 // and dismiss the popup for certain events.
298 class RenderWidgetHostViewAura::EventFilterForPopupExit
299 : public ui::EventHandler {
300 public:
301 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
302 : rwhva_(rwhva) {
303 DCHECK(rwhva_);
304 aura::Env::GetInstance()->AddPreTargetHandler(this);
307 ~EventFilterForPopupExit() override {
308 aura::Env::GetInstance()->RemovePreTargetHandler(this);
311 // Overridden from ui::EventHandler
312 void OnMouseEvent(ui::MouseEvent* event) override {
313 rwhva_->ApplyEventFilterForPopupExit(event);
316 void OnTouchEvent(ui::TouchEvent* event) override {
317 rwhva_->ApplyEventFilterForPopupExit(event);
320 private:
321 RenderWidgetHostViewAura* rwhva_;
323 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
326 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
327 ui::LocatedEvent* event) {
328 if (in_shutdown_ || is_fullscreen_ || !event->target())
329 return;
331 if (event->type() != ui::ET_MOUSE_PRESSED &&
332 event->type() != ui::ET_TOUCH_PRESSED) {
333 return;
336 aura::Window* target = static_cast<aura::Window*>(event->target());
337 if (target != window_ &&
338 (!popup_parent_host_view_ ||
339 target != popup_parent_host_view_->window_)) {
340 // If we enter this code path it means that we did not receive any focus
341 // lost notifications for the popup window. Ensure that blink is aware
342 // of the fact that focus was lost for the host window by sending a Blur
343 // notification.
344 if (popup_parent_host_view_ && popup_parent_host_view_->host_)
345 popup_parent_host_view_->host_->Blur();
346 // Note: popup_parent_host_view_ may be NULL when there are multiple
347 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
348 Shutdown();
352 // We have to implement the WindowObserver interface on a separate object
353 // because clang doesn't like implementing multiple interfaces that have
354 // methods with the same name. This object is owned by the
355 // RenderWidgetHostViewAura.
356 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
357 public:
358 explicit WindowObserver(RenderWidgetHostViewAura* view)
359 : view_(view) {
360 view_->window_->AddObserver(this);
363 ~WindowObserver() override { view_->window_->RemoveObserver(this); }
365 // Overridden from aura::WindowObserver:
366 void OnWindowAddedToRootWindow(aura::Window* window) override {
367 if (window == view_->window_)
368 view_->AddedToRootWindow();
371 void OnWindowRemovingFromRootWindow(aura::Window* window,
372 aura::Window* new_root) override {
373 if (window == view_->window_)
374 view_->RemovingFromRootWindow();
377 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
378 view_->ParentHierarchyChanged();
381 private:
382 RenderWidgetHostViewAura* view_;
384 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
387 // This class provides functionality to observe the ancestors of the RWHVA for
388 // bounds changes. This is done to snap the RWHVA window to a pixel boundary,
389 // which could change when the bounds relative to the root changes.
390 // An example where this happens is below:-
391 // The fast resize code path for bookmarks where in the parent of RWHVA which
392 // is WCV has its bounds changed before the bookmark is hidden. This results in
393 // the traditional bounds change notification for the WCV reporting the old
394 // bounds as the bookmark is still around. Observing all the ancestors of the
395 // RWHVA window enables us to know when the bounds of the window relative to
396 // root changes and allows us to snap accordingly.
397 class RenderWidgetHostViewAura::WindowAncestorObserver
398 : public aura::WindowObserver {
399 public:
400 explicit WindowAncestorObserver(RenderWidgetHostViewAura* view)
401 : view_(view) {
402 aura::Window* parent = view_->window_->parent();
403 while (parent) {
404 parent->AddObserver(this);
405 ancestors_.insert(parent);
406 parent = parent->parent();
410 ~WindowAncestorObserver() override {
411 RemoveAncestorObservers();
414 void OnWindowBoundsChanged(aura::Window* window,
415 const gfx::Rect& old_bounds,
416 const gfx::Rect& new_bounds) override {
417 DCHECK(ancestors_.find(window) != ancestors_.end());
418 if (new_bounds.origin() != old_bounds.origin())
419 view_->HandleParentBoundsChanged();
422 private:
423 void RemoveAncestorObservers() {
424 for (auto ancestor : ancestors_)
425 ancestor->RemoveObserver(this);
426 ancestors_.clear();
429 RenderWidgetHostViewAura* view_;
430 std::set<aura::Window*> ancestors_;
432 DISALLOW_COPY_AND_ASSIGN(WindowAncestorObserver);
435 ////////////////////////////////////////////////////////////////////////////////
436 // RenderWidgetHostViewAura, public:
438 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
439 bool is_guest_view_hack)
440 : host_(RenderWidgetHostImpl::From(host)),
441 window_(new aura::Window(this)),
442 delegated_frame_host_(new DelegatedFrameHost(this)),
443 in_shutdown_(false),
444 in_bounds_changed_(false),
445 is_fullscreen_(false),
446 popup_parent_host_view_(NULL),
447 popup_child_host_view_(NULL),
448 is_loading_(false),
449 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
450 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
451 text_input_flags_(0),
452 can_compose_inline_(true),
453 has_composition_text_(false),
454 accept_return_character_(false),
455 last_swapped_software_frame_scale_factor_(1.f),
456 paint_canvas_(NULL),
457 synthetic_move_sent_(false),
458 cursor_visibility_state_in_renderer_(UNKNOWN),
459 #if defined(OS_WIN)
460 legacy_render_widget_host_HWND_(NULL),
461 legacy_window_destroyed_(false),
462 showing_context_menu_(false),
463 #endif
464 has_snapped_to_boundary_(false),
465 touch_editing_client_(NULL),
466 is_guest_view_hack_(is_guest_view_hack),
467 begin_frame_observer_proxy_(this),
468 weak_ptr_factory_(this) {
469 if (!is_guest_view_hack_)
470 host_->SetView(this);
472 window_observer_.reset(new WindowObserver(this));
474 aura::client::SetTooltipText(window_, &tooltip_);
475 aura::client::SetActivationDelegate(window_, this);
476 aura::client::SetFocusChangeObserver(window_, this);
477 window_->set_layer_owner_delegate(delegated_frame_host_.get());
478 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
480 bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
481 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
482 SetOverscrollControllerEnabled(overscroll_enabled);
485 ////////////////////////////////////////////////////////////////////////////////
486 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
488 bool RenderWidgetHostViewAura::OnMessageReceived(
489 const IPC::Message& message) {
490 bool handled = true;
491 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
492 // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
493 // messages for TextInput<State|Type>Changed. Corresponding code in
494 // RenderWidgetHostViewAndroid should also be moved at the same time.
495 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
496 OnTextInputStateChanged)
497 IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrames,
498 OnSetNeedsBeginFrames)
499 IPC_MESSAGE_UNHANDLED(handled = false)
500 IPC_END_MESSAGE_MAP()
501 return handled;
504 void RenderWidgetHostViewAura::InitAsChild(
505 gfx::NativeView parent_view) {
506 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
507 window_->Init(ui::LAYER_SOLID_COLOR);
508 window_->SetName("RenderWidgetHostViewAura");
509 window_->layer()->SetColor(background_color_);
512 void RenderWidgetHostViewAura::InitAsPopup(
513 RenderWidgetHostView* parent_host_view,
514 const gfx::Rect& bounds_in_screen) {
515 popup_parent_host_view_ =
516 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
518 // TransientWindowClient may be NULL during tests.
519 aura::client::TransientWindowClient* transient_window_client =
520 aura::client::GetTransientWindowClient();
521 RenderWidgetHostViewAura* old_child =
522 popup_parent_host_view_->popup_child_host_view_;
523 if (old_child) {
524 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
525 // similar mechanism to ensure a second popup doesn't cause the first one
526 // to never get a chance to filter events. See crbug.com/160589.
527 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
528 if (transient_window_client) {
529 transient_window_client->RemoveTransientChild(
530 popup_parent_host_view_->window_, old_child->window_);
532 old_child->popup_parent_host_view_ = NULL;
534 popup_parent_host_view_->popup_child_host_view_ = this;
535 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
536 window_->Init(ui::LAYER_SOLID_COLOR);
537 window_->SetName("RenderWidgetHostViewAura");
538 window_->layer()->SetColor(background_color_);
540 // Setting the transient child allows for the popup to get mouse events when
541 // in a system modal dialog. Do this before calling ParentWindowWithContext
542 // below so that the transient parent is visible to WindowTreeClient.
543 // This fixes crbug.com/328593.
544 if (transient_window_client) {
545 transient_window_client->AddTransientChild(
546 popup_parent_host_view_->window_, window_);
549 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
550 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
552 SetBounds(bounds_in_screen);
553 Show();
554 if (NeedsMouseCapture())
555 window_->SetCapture();
557 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
560 void RenderWidgetHostViewAura::InitAsFullscreen(
561 RenderWidgetHostView* reference_host_view) {
562 is_fullscreen_ = true;
563 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
564 window_->Init(ui::LAYER_SOLID_COLOR);
565 window_->SetName("RenderWidgetHostViewAura");
566 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
567 window_->layer()->SetColor(background_color_);
569 aura::Window* parent = NULL;
570 gfx::Rect bounds;
571 if (reference_host_view) {
572 aura::Window* reference_window =
573 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
574 if (reference_window) {
575 host_tracker_.reset(new aura::WindowTracker);
576 host_tracker_->Add(reference_window);
578 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
579 GetDisplayNearestWindow(reference_window);
580 parent = reference_window->GetRootWindow();
581 bounds = display.bounds();
583 aura::client::ParentWindowWithContext(window_, parent, bounds);
584 Show();
585 Focus();
588 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
589 return host_;
592 void RenderWidgetHostViewAura::Show() {
593 window_->Show();
595 DCHECK(host_);
596 if (!host_->is_hidden())
597 return;
599 bool has_saved_frame = delegated_frame_host_->HasSavedFrame();
600 ui::LatencyInfo renderer_latency_info, browser_latency_info;
601 if (has_saved_frame) {
602 browser_latency_info.AddLatencyNumber(
603 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
604 } else {
605 renderer_latency_info.AddLatencyNumber(
606 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
608 host_->WasShown(renderer_latency_info);
610 aura::Window* root = window_->GetRootWindow();
611 if (root) {
612 aura::client::CursorClient* cursor_client =
613 aura::client::GetCursorClient(root);
614 if (cursor_client)
615 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
618 delegated_frame_host_->WasShown(browser_latency_info);
620 #if defined(OS_WIN)
621 if (legacy_render_widget_host_HWND_) {
622 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
623 // window before reparenting any plugins. This ensures that the plugin
624 // windows stay on top of the child Zorder in the parent and receive
625 // mouse events, etc.
626 legacy_render_widget_host_HWND_->UpdateParent(
627 GetNativeView()->GetHost()->GetAcceleratedWidget());
628 legacy_render_widget_host_HWND_->SetBounds(
629 window_->GetBoundsInRootWindow());
631 LPARAM lparam = reinterpret_cast<LPARAM>(this);
632 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
634 if (legacy_render_widget_host_HWND_)
635 legacy_render_widget_host_HWND_->Show();
636 #endif
639 void RenderWidgetHostViewAura::Hide() {
640 window_->Hide();
642 if (host_ && !host_->is_hidden()) {
643 host_->WasHidden();
644 delegated_frame_host_->WasHidden();
646 #if defined(OS_WIN)
647 constrained_rects_.clear();
648 aura::WindowTreeHost* host = window_->GetHost();
649 if (host) {
650 HWND parent = host->GetAcceleratedWidget();
651 LPARAM lparam = reinterpret_cast<LPARAM>(this);
652 EnumChildWindows(parent, HideWindowsCallback, lparam);
653 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
654 // hidden window on the same lines as Windowed plugin windows.
655 if (legacy_render_widget_host_HWND_)
656 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
658 #endif
661 #if defined(OS_WIN)
662 if (legacy_render_widget_host_HWND_)
663 legacy_render_widget_host_HWND_->Hide();
664 #endif
667 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
668 // For a SetSize operation, we don't care what coordinate system the origin
669 // of the window is in, it's only important to make sure that the origin
670 // remains constant after the operation.
671 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
674 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
675 gfx::Point relative_origin(rect.origin());
677 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
678 // Window::SetBounds() takes parent coordinates, so do the conversion here.
679 aura::Window* root = window_->GetRootWindow();
680 if (root) {
681 aura::client::ScreenPositionClient* screen_position_client =
682 aura::client::GetScreenPositionClient(root);
683 if (screen_position_client) {
684 screen_position_client->ConvertPointFromScreen(
685 window_->parent(), &relative_origin);
689 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
692 gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
693 return last_scroll_offset_;
696 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
697 return window_;
700 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
701 #if defined(OS_WIN)
702 aura::WindowTreeHost* host = window_->GetHost();
703 if (host)
704 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
705 #endif
706 return static_cast<gfx::NativeViewId>(NULL);
709 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
710 #if defined(OS_WIN)
711 aura::WindowTreeHost* host = window_->GetHost();
712 if (!host)
713 return static_cast<gfx::NativeViewAccessible>(NULL);
714 BrowserAccessibilityManager* manager =
715 host_->GetOrCreateRootBrowserAccessibilityManager();
716 if (manager)
717 return manager->GetRoot()->ToBrowserAccessibilityWin();
718 #endif
720 NOTIMPLEMENTED();
721 return static_cast<gfx::NativeViewAccessible>(NULL);
724 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
725 return this;
728 void RenderWidgetHostViewAura::OnSetNeedsBeginFrames(bool needs_begin_frames) {
729 begin_frame_observer_proxy_.SetNeedsBeginFrames(needs_begin_frames);
732 void RenderWidgetHostViewAura::SendBeginFrame(const cc::BeginFrameArgs& args) {
733 delegated_frame_host_->SetVSyncParameters(args.frame_time, args.interval);
734 host_->Send(new ViewMsg_BeginFrame(host_->GetRoutingID(), args));
737 void RenderWidgetHostViewAura::SetKeyboardFocus() {
738 #if defined(OS_WIN)
739 if (CanFocus()) {
740 aura::WindowTreeHost* host = window_->GetHost();
741 if (host)
742 ::SetFocus(host->GetAcceleratedWidget());
744 #endif
747 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
748 if (!host_->IsRenderView())
749 return NULL;
750 RenderViewHost* rvh = RenderViewHost::From(host_);
751 FrameTreeNode* focused_frame =
752 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
753 if (!focused_frame)
754 return NULL;
756 return focused_frame->current_frame_host();
759 bool RenderWidgetHostViewAura::CanRendererHandleEvent(
760 const ui::MouseEvent* event,
761 bool mouse_locked,
762 bool selection_popup) {
763 #if defined(OS_WIN)
764 bool showing_context_menu = showing_context_menu_;
765 showing_context_menu_ = false;
766 #endif
768 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
769 return false;
771 if ((mouse_locked || selection_popup) &&
772 (event->type() == ui::ET_MOUSE_EXITED))
773 return false;
775 #if defined(OS_WIN)
776 // Don't forward the mouse leave message which is received when the context
777 // menu is displayed by the page. This confuses the page and causes state
778 // changes.
779 if (showing_context_menu) {
780 if (event->type() == ui::ET_MOUSE_EXITED)
781 return false;
783 // Renderer cannot handle WM_XBUTTON or NC events.
784 switch (event->native_event().message) {
785 case WM_XBUTTONDOWN:
786 case WM_XBUTTONUP:
787 case WM_XBUTTONDBLCLK:
788 case WM_NCMOUSELEAVE:
789 case WM_NCMOUSEMOVE:
790 case WM_NCLBUTTONDOWN:
791 case WM_NCLBUTTONUP:
792 case WM_NCLBUTTONDBLCLK:
793 case WM_NCRBUTTONDOWN:
794 case WM_NCRBUTTONUP:
795 case WM_NCRBUTTONDBLCLK:
796 case WM_NCMBUTTONDOWN:
797 case WM_NCMBUTTONUP:
798 case WM_NCMBUTTONDBLCLK:
799 case WM_NCXBUTTONDOWN:
800 case WM_NCXBUTTONUP:
801 case WM_NCXBUTTONDBLCLK:
802 return false;
803 default:
804 break;
806 #elif defined(USE_X11)
807 // Renderer only supports standard mouse buttons, so ignore programmable
808 // buttons.
809 switch (event->type()) {
810 case ui::ET_MOUSE_PRESSED:
811 case ui::ET_MOUSE_RELEASED: {
812 const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
813 ui::EF_MIDDLE_MOUSE_BUTTON |
814 ui::EF_RIGHT_MOUSE_BUTTON;
815 return (event->flags() & kAllowedButtons) != 0;
817 default:
818 break;
820 #endif
821 return true;
824 void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
825 SnapToPhysicalPixelBoundary();
826 #if defined(OS_WIN)
827 if (legacy_render_widget_host_HWND_) {
828 legacy_render_widget_host_HWND_->SetBounds(
829 window_->GetBoundsInRootWindow());
831 #endif
834 void RenderWidgetHostViewAura::ParentHierarchyChanged() {
835 ancestor_window_observer_.reset(new WindowAncestorObserver(this));
836 // Snap when we receive a hierarchy changed. http://crbug.com/388908.
837 HandleParentBoundsChanged();
840 void RenderWidgetHostViewAura::MovePluginWindows(
841 const std::vector<WebPluginGeometry>& plugin_window_moves) {
842 #if defined(OS_WIN)
843 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
844 // over the browser UI.
845 if (!window_->GetRootWindow()) {
846 DCHECK(plugin_window_moves.empty());
847 return;
849 HWND parent = window_->GetHost()->GetAcceleratedWidget();
850 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
851 std::vector<WebPluginGeometry> moves = plugin_window_moves;
853 gfx::Rect view_port(view_bounds.size());
855 for (size_t i = 0; i < moves.size(); ++i) {
856 gfx::Rect clip(moves[i].clip_rect);
857 gfx::Vector2d view_port_offset(
858 moves[i].window_rect.OffsetFromOrigin());
859 clip.Offset(view_port_offset);
860 clip.Intersect(view_port);
861 clip.Offset(-view_port_offset);
862 moves[i].clip_rect = clip;
864 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
866 plugin_window_moves_[moves[i].window] = moves[i];
868 // constrained_rects_ are relative to the root window. We want to convert
869 // them to be relative to the plugin window.
870 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
871 gfx::Rect offset_cutout = constrained_rects_[j];
872 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
873 moves[i].cutout_rects.push_back(offset_cutout);
877 MovePluginWindowsHelper(parent, moves);
879 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
880 // |this|.
881 for (size_t i = 0; i < moves.size(); ++i) {
882 HWND window = moves[i].window;
883 if (GetParent(window) != parent) {
884 window = GetParent(window);
886 if (!GetProp(window, kWidgetOwnerProperty))
887 SetProp(window, kWidgetOwnerProperty, this);
889 #endif // defined(OS_WIN)
892 void RenderWidgetHostViewAura::Focus() {
893 // Make sure we have a FocusClient before attempting to Focus(). In some
894 // situations we may not yet be in a valid Window hierarchy (such as reloading
895 // after out of memory discarded the tab).
896 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
897 if (client)
898 window_->Focus();
901 bool RenderWidgetHostViewAura::HasFocus() const {
902 return window_->HasFocus();
905 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
906 return delegated_frame_host_->CanCopyToBitmap();
909 bool RenderWidgetHostViewAura::IsShowing() {
910 return window_->IsVisible();
913 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
914 return window_->GetBoundsInScreen();
917 void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
918 RenderWidgetHostViewBase::SetBackgroundColor(color);
919 bool opaque = GetBackgroundOpaque();
920 host_->SetBackgroundOpaque(opaque);
921 window_->layer()->SetFillsBoundsOpaquely(opaque);
922 window_->layer()->SetColor(color);
925 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
926 gfx::Rect requested_rect(GetRequestedRendererSize());
927 requested_rect.Inset(insets_);
928 return requested_rect.size();
931 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
932 if (insets != insets_) {
933 insets_ = insets;
934 host_->WasResized();
938 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
939 current_cursor_ = cursor;
940 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
941 GetDisplayNearestWindow(window_);
942 current_cursor_.SetDisplayInfo(display);
943 UpdateCursorIfOverSelf();
946 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
947 is_loading_ = is_loading;
948 UpdateCursorIfOverSelf();
951 void RenderWidgetHostViewAura::TextInputTypeChanged(
952 ui::TextInputType type,
953 ui::TextInputMode input_mode,
954 bool can_compose_inline,
955 int flags) {
956 if (text_input_type_ != type ||
957 text_input_mode_ != input_mode ||
958 can_compose_inline_ != can_compose_inline ||
959 text_input_flags_ != flags) {
960 text_input_type_ = type;
961 text_input_mode_ = input_mode;
962 can_compose_inline_ = can_compose_inline;
963 text_input_flags_ = flags;
964 if (GetInputMethod())
965 GetInputMethod()->OnTextInputTypeChanged(this);
966 if (touch_editing_client_)
967 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
971 void RenderWidgetHostViewAura::OnTextInputStateChanged(
972 const ViewHostMsg_TextInputState_Params& params) {
973 text_input_flags_ = params.flags;
974 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
975 if (GetInputMethod())
976 GetInputMethod()->ShowImeIfNeeded();
980 void RenderWidgetHostViewAura::ImeCancelComposition() {
981 if (GetInputMethod())
982 GetInputMethod()->CancelComposition(this);
983 has_composition_text_ = false;
986 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
987 const gfx::Range& range,
988 const std::vector<gfx::Rect>& character_bounds) {
989 composition_character_bounds_ = character_bounds;
992 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
993 int error_code) {
994 UpdateCursorIfOverSelf();
995 Destroy();
998 void RenderWidgetHostViewAura::Destroy() {
999 // Beware, this function is not called on all destruction paths. It will
1000 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1001 // destruction/cleanup code should happen there, not here.
1002 in_shutdown_ = true;
1003 delete window_;
1006 void RenderWidgetHostViewAura::SetTooltipText(
1007 const base::string16& tooltip_text) {
1008 tooltip_ = tooltip_text;
1009 aura::Window* root_window = window_->GetRootWindow();
1010 aura::client::TooltipClient* tooltip_client =
1011 aura::client::GetTooltipClient(root_window);
1012 if (tooltip_client) {
1013 tooltip_client->UpdateTooltip(window_);
1014 // Content tooltips should be visible indefinitely.
1015 tooltip_client->SetTooltipShownTimeout(window_, 0);
1019 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
1020 size_t offset,
1021 const gfx::Range& range) {
1022 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1024 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1025 if (text.empty() || range.is_empty())
1026 return;
1027 size_t pos = range.GetMin() - offset;
1028 size_t n = range.length();
1030 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
1031 if (pos >= text.length()) {
1032 NOTREACHED() << "The text can not cover range.";
1033 return;
1036 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
1037 ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
1038 clipboard_writer.WriteText(text.substr(pos, n));
1039 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1042 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
1043 return delegated_frame_host_->GetRequestedRendererSize();
1046 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1047 const ViewHostMsg_SelectionBounds_Params& params) {
1048 ui::SelectionBound anchor_bound, focus_bound;
1049 anchor_bound.SetEdge(params.anchor_rect.origin(),
1050 params.anchor_rect.bottom_left());
1051 focus_bound.SetEdge(params.focus_rect.origin(),
1052 params.focus_rect.bottom_left());
1054 if (params.anchor_rect == params.focus_rect) {
1055 anchor_bound.set_type(ui::SelectionBound::CENTER);
1056 focus_bound.set_type(ui::SelectionBound::CENTER);
1057 } else {
1058 // Whether text is LTR at the anchor handle.
1059 bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight;
1060 // Whether text is LTR at the focus handle.
1061 bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight;
1063 if ((params.is_anchor_first && anchor_LTR) ||
1064 (!params.is_anchor_first && !anchor_LTR)) {
1065 anchor_bound.set_type(ui::SelectionBound::LEFT);
1066 } else {
1067 anchor_bound.set_type(ui::SelectionBound::RIGHT);
1069 if ((params.is_anchor_first && focus_LTR) ||
1070 (!params.is_anchor_first && !focus_LTR)) {
1071 focus_bound.set_type(ui::SelectionBound::RIGHT);
1072 } else {
1073 focus_bound.set_type(ui::SelectionBound::LEFT);
1077 if (anchor_bound == selection_anchor_ && focus_bound == selection_focus_)
1078 return;
1080 selection_anchor_ = anchor_bound;
1081 selection_focus_ = focus_bound;
1082 if (GetInputMethod())
1083 GetInputMethod()->OnCaretBoundsChanged(this);
1085 if (touch_editing_client_) {
1086 touch_editing_client_->OnSelectionOrCursorChanged(
1087 anchor_bound, focus_bound);
1091 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1092 const gfx::Rect& src_subrect,
1093 const gfx::Size& dst_size,
1094 ReadbackRequestCallback& callback,
1095 const SkColorType preferred_color_type) {
1096 delegated_frame_host_->CopyFromCompositingSurface(
1097 src_subrect, dst_size, callback, preferred_color_type);
1100 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1101 const gfx::Rect& src_subrect,
1102 const scoped_refptr<media::VideoFrame>& target,
1103 const base::Callback<void(bool)>& callback) {
1104 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
1105 src_subrect, target, callback);
1108 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1109 return delegated_frame_host_->CanCopyToVideoFrame();
1112 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1113 return delegated_frame_host_->CanSubscribeFrame();
1116 void RenderWidgetHostViewAura::BeginFrameSubscription(
1117 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1118 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
1121 void RenderWidgetHostViewAura::EndFrameSubscription() {
1122 delegated_frame_host_->EndFrameSubscription();
1125 #if defined(OS_WIN)
1126 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1127 return (legacy_render_widget_host_HWND_ != NULL);
1130 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1131 const std::vector<gfx::Rect>& rects) {
1132 // Check this before setting constrained_rects_, so that next time they're set
1133 // and we have a root window we don't early return.
1134 if (!window_->GetHost())
1135 return;
1137 if (rects == constrained_rects_)
1138 return;
1140 constrained_rects_ = rects;
1142 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1143 CutoutRectsParams params;
1144 params.widget = this;
1145 params.cutout_rects = constrained_rects_;
1146 params.geometry = &plugin_window_moves_;
1147 LPARAM lparam = reinterpret_cast<LPARAM>(&params);
1148 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1151 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1152 // Clip the cursor if chrome is running on regular desktop.
1153 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1154 RECT window_rect =
1155 gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
1156 ::ClipCursor(&window_rect);
1160 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1161 legacy_render_widget_host_HWND_ = NULL;
1162 legacy_window_destroyed_ = true;
1164 #endif
1166 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1167 uint32 output_surface_id,
1168 scoped_ptr<cc::CompositorFrame> frame) {
1169 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1171 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1172 if (frame->delegated_frame_data) {
1173 delegated_frame_host_->SwapDelegatedFrame(
1174 output_surface_id,
1175 frame->delegated_frame_data.Pass(),
1176 frame->metadata.device_scale_factor,
1177 frame->metadata.latency_info);
1178 return;
1181 if (frame->software_frame_data) {
1182 DLOG(ERROR) << "Unable to use software frame in aura";
1183 bad_message::ReceivedBadMessage(host_->GetProcess(),
1184 bad_message::RWHVA_SHARED_MEMORY);
1185 return;
1189 void RenderWidgetHostViewAura::DidStopFlinging() {
1190 if (touch_editing_client_)
1191 touch_editing_client_->DidStopFlinging();
1194 #if defined(OS_WIN)
1195 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1196 gfx::NativeViewAccessible accessible_parent) {
1199 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1200 const {
1201 if (legacy_render_widget_host_HWND_) {
1202 return reinterpret_cast<gfx::NativeViewId>(
1203 legacy_render_widget_host_HWND_->hwnd());
1205 return NULL;
1207 #endif
1209 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1210 const gfx::Size& desired_size) {
1211 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1212 // matter what is returned here as GetBackingStore is the only caller of this
1213 // method. TODO(jbates) implement this if other Aura code needs it.
1214 return false;
1217 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1218 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1221 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1222 aura::Window* top_level = window_->GetToplevelWindow();
1223 gfx::Rect bounds(top_level->GetBoundsInScreen());
1225 #if defined(OS_WIN)
1226 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1227 // remove the legacy hwnd, so a better fix will need to be decided when that
1228 // happens.
1229 if (UsesNativeWindowFrame()) {
1230 // aura::Window doesn't take into account non-client area of native windows
1231 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1232 aura::WindowTreeHost* host = top_level->GetHost();
1233 if (!host)
1234 return top_level->GetBoundsInScreen();
1235 RECT window_rect = {0};
1236 HWND hwnd = host->GetAcceleratedWidget();
1237 ::GetWindowRect(hwnd, &window_rect);
1238 bounds = gfx::Rect(window_rect);
1240 // Maximized windows are outdented from the work area by the frame thickness
1241 // even though this "frame" is not painted. This confuses code (and people)
1242 // that think of a maximized window as corresponding exactly to the work
1243 // area. Correct for this by subtracting the frame thickness back off.
1244 if (::IsZoomed(hwnd)) {
1245 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
1246 GetSystemMetrics(SM_CYSIZEFRAME));
1248 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1249 GetSystemMetrics(SM_CXPADDEDBORDER));
1253 bounds = gfx::win::ScreenToDIPRect(bounds);
1254 #endif
1256 return bounds;
1259 void RenderWidgetHostViewAura::WheelEventAck(
1260 const blink::WebMouseWheelEvent& event,
1261 InputEventAckState ack_result) {
1262 if (overscroll_controller_) {
1263 overscroll_controller_->ReceivedEventACK(
1264 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1268 void RenderWidgetHostViewAura::GestureEventAck(
1269 const blink::WebGestureEvent& event,
1270 InputEventAckState ack_result) {
1271 if (touch_editing_client_)
1272 touch_editing_client_->GestureEventAck(event.type);
1274 if (overscroll_controller_) {
1275 overscroll_controller_->ReceivedEventACK(
1276 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1280 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1281 const TouchEventWithLatencyInfo& touch,
1282 InputEventAckState ack_result) {
1283 ScopedVector<ui::TouchEvent> events;
1284 aura::WindowTreeHost* host = window_->GetHost();
1285 // |host| is NULL during tests.
1286 if (!host)
1287 return;
1289 ui::EventResult result = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
1290 ? ui::ER_HANDLED
1291 : ui::ER_UNHANDLED;
1293 blink::WebTouchPoint::State required_state;
1294 switch (touch.event.type) {
1295 case blink::WebInputEvent::TouchStart:
1296 required_state = blink::WebTouchPoint::StatePressed;
1297 break;
1298 case blink::WebInputEvent::TouchEnd:
1299 required_state = blink::WebTouchPoint::StateReleased;
1300 break;
1301 case blink::WebInputEvent::TouchMove:
1302 required_state = blink::WebTouchPoint::StateMoved;
1303 break;
1304 case blink::WebInputEvent::TouchCancel:
1305 required_state = blink::WebTouchPoint::StateCancelled;
1306 break;
1307 default:
1308 required_state = blink::WebTouchPoint::StateUndefined;
1309 NOTREACHED();
1310 break;
1313 // Only send acks for one changed touch point.
1314 bool sent_ack = false;
1315 for (size_t i = 0; i < touch.event.touchesLength; ++i) {
1316 if (touch.event.touches[i].state == required_state) {
1317 DCHECK(!sent_ack);
1318 host->dispatcher()->ProcessedTouchEvent(touch.event.uniqueTouchEventId,
1319 window_, result);
1320 sent_ack = true;
1325 scoped_ptr<SyntheticGestureTarget>
1326 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1327 return scoped_ptr<SyntheticGestureTarget>(
1328 new SyntheticGestureTargetAura(host_));
1331 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
1332 const blink::WebInputEvent& input_event) {
1333 bool consumed = false;
1334 if (input_event.type == WebInputEvent::GestureFlingStart) {
1335 const WebGestureEvent& gesture_event =
1336 static_cast<const WebGestureEvent&>(input_event);
1337 // Zero-velocity touchpad flings are an Aura-specific signal that the
1338 // touchpad scroll has ended, and should not be forwarded to the renderer.
1339 if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
1340 !gesture_event.data.flingStart.velocityX &&
1341 !gesture_event.data.flingStart.velocityY) {
1342 consumed = true;
1346 if (overscroll_controller_)
1347 consumed |= overscroll_controller_->WillHandleEvent(input_event);
1349 // Touch events should always propagate to the renderer.
1350 if (WebTouchEvent::isTouchEventType(input_event.type))
1351 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1353 // Reporting consumed for a fling suggests that there's now an *active* fling
1354 // that requires both animation and a fling-end notification. However, the
1355 // OverscrollController consumes a fling to stop its propagation; it doesn't
1356 // actually tick a fling animation. Report no consumer to convey this.
1357 if (consumed && input_event.type == blink::WebInputEvent::GestureFlingStart)
1358 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
1360 return consumed ? INPUT_EVENT_ACK_STATE_CONSUMED
1361 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1364 BrowserAccessibilityManager*
1365 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1366 BrowserAccessibilityDelegate* delegate) {
1367 BrowserAccessibilityManager* manager = NULL;
1368 #if defined(OS_WIN)
1369 manager = new BrowserAccessibilityManagerWin(
1370 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
1371 #else
1372 manager = BrowserAccessibilityManager::Create(
1373 BrowserAccessibilityManager::GetEmptyDocument(), delegate);
1374 #endif
1375 return manager;
1378 gfx::AcceleratedWidget
1379 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1380 #if defined(OS_WIN)
1381 if (legacy_render_widget_host_HWND_)
1382 return legacy_render_widget_host_HWND_->hwnd();
1383 #endif
1384 return gfx::kNullAcceleratedWidget;
1387 gfx::NativeViewAccessible
1388 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1389 #if defined(OS_WIN)
1390 if (legacy_render_widget_host_HWND_)
1391 return legacy_render_widget_host_HWND_->window_accessible();
1392 #endif
1393 return NULL;
1397 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1398 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1401 void RenderWidgetHostViewAura::ShowDisambiguationPopup(
1402 const gfx::Rect& rect_pixels,
1403 const SkBitmap& zoomed_bitmap) {
1404 RenderViewHostDelegate* delegate = NULL;
1405 if (host_->IsRenderView())
1406 delegate = RenderViewHost::From(host_)->GetDelegate();
1407 // Suppress the link disambiguation popup if the virtual keyboard is currently
1408 // requested, as it doesn't interact well with the keyboard.
1409 if (delegate && delegate->IsVirtualKeyboardRequested())
1410 return;
1412 // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
1413 // by scaling it by the inverse of the device scale factor.
1414 gfx::RectF screen_target_rect_f(rect_pixels);
1415 screen_target_rect_f.Scale(1.0f / current_device_scale_factor_);
1416 disambiguation_target_rect_ = gfx::ToEnclosingRect(screen_target_rect_f);
1418 float scale = static_cast<float>(zoomed_bitmap.width()) /
1419 static_cast<float>(rect_pixels.width());
1420 gfx::Size zoomed_size(gfx::ToCeiledSize(
1421 gfx::ScaleSize(disambiguation_target_rect_.size(), scale)));
1423 // Save of a copy of the |last_scroll_offset_| for comparison when the copy
1424 // callback fires, to ensure that we haven't scrolled.
1425 disambiguation_scroll_offset_ = last_scroll_offset_;
1427 CopyFromCompositingSurface(
1428 disambiguation_target_rect_,
1429 zoomed_size,
1430 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
1431 weak_ptr_factory_.GetWeakPtr()),
1432 kN32_SkColorType);
1435 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1436 const SkBitmap& result,
1437 ReadbackResponse response) {
1438 if ((response != READBACK_SUCCESS) ||
1439 disambiguation_scroll_offset_ != last_scroll_offset_)
1440 return;
1442 // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
1443 // actually show the disambiguation popup.
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->IsVirtualKeyboardRequested())
1451 return;
1453 if (delegate_view) {
1454 delegate_view->ShowDisambiguationPopup(
1455 disambiguation_target_rect_,
1456 result,
1457 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture,
1458 weak_ptr_factory_.GetWeakPtr()),
1459 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse,
1460 weak_ptr_factory_.GetWeakPtr()));
1464 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1465 RenderViewHostDelegate* delegate = NULL;
1466 if (host_->IsRenderView())
1467 delegate = RenderViewHost::From(host_)->GetDelegate();
1468 RenderViewHostDelegateView* delegate_view = NULL;
1469 if (delegate)
1470 delegate_view = delegate->GetDelegateView();
1471 if (delegate_view)
1472 delegate_view->HideDisambiguationPopup();
1475 void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
1476 ui::GestureEvent* event) {
1477 blink::WebGestureEvent web_gesture = content::MakeWebGestureEvent(*event);
1478 // If we fail to make a WebGestureEvent that is a Tap from the provided event,
1479 // don't forward it to Blink.
1480 if (web_gesture.type < blink::WebInputEvent::Type::GestureTap ||
1481 web_gesture.type > blink::WebInputEvent::Type::GestureTapCancel)
1482 return;
1484 host_->ForwardGestureEvent(web_gesture);
1487 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1488 ui::MouseEvent* event) {
1489 blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(*event);
1490 host_->ForwardMouseEvent(web_mouse);
1493 bool RenderWidgetHostViewAura::LockMouse() {
1494 aura::Window* root_window = window_->GetRootWindow();
1495 if (!root_window)
1496 return false;
1498 if (mouse_locked_)
1499 return true;
1501 mouse_locked_ = true;
1502 #if !defined(OS_WIN)
1503 window_->SetCapture();
1504 #else
1505 UpdateMouseLockRegion();
1506 #endif
1507 aura::client::CursorClient* cursor_client =
1508 aura::client::GetCursorClient(root_window);
1509 if (cursor_client) {
1510 cursor_client->HideCursor();
1511 cursor_client->LockCursor();
1514 if (ShouldMoveToCenter()) {
1515 synthetic_move_sent_ = true;
1516 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1518 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1519 return true;
1522 void RenderWidgetHostViewAura::UnlockMouse() {
1523 tooltip_disabler_.reset();
1525 aura::Window* root_window = window_->GetRootWindow();
1526 if (!mouse_locked_ || !root_window)
1527 return;
1529 mouse_locked_ = false;
1531 #if !defined(OS_WIN)
1532 window_->ReleaseCapture();
1533 #else
1534 ::ClipCursor(NULL);
1535 #endif
1536 window_->MoveCursorTo(unlocked_mouse_position_);
1537 aura::client::CursorClient* cursor_client =
1538 aura::client::GetCursorClient(root_window);
1539 if (cursor_client) {
1540 cursor_client->UnlockCursor();
1541 cursor_client->ShowCursor();
1544 host_->LostMouseLock();
1547 ////////////////////////////////////////////////////////////////////////////////
1548 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1549 void RenderWidgetHostViewAura::SetCompositionText(
1550 const ui::CompositionText& composition) {
1551 if (!host_)
1552 return;
1554 // TODO(suzhe): convert both renderer_host and renderer to use
1555 // ui::CompositionText.
1556 std::vector<blink::WebCompositionUnderline> underlines;
1557 underlines.reserve(composition.underlines.size());
1558 for (std::vector<ui::CompositionUnderline>::const_iterator it =
1559 composition.underlines.begin();
1560 it != composition.underlines.end(); ++it) {
1561 underlines.push_back(
1562 blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset),
1563 static_cast<unsigned>(it->end_offset),
1564 it->color,
1565 it->thick,
1566 it->background_color));
1569 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1570 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1571 host_->ImeSetComposition(composition.text, underlines,
1572 composition.selection.end(),
1573 composition.selection.end());
1575 has_composition_text_ = !composition.text.empty();
1578 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1579 if (host_ && has_composition_text_) {
1580 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1581 false);
1583 has_composition_text_ = false;
1586 void RenderWidgetHostViewAura::ClearCompositionText() {
1587 if (host_ && has_composition_text_)
1588 host_->ImeCancelComposition();
1589 has_composition_text_ = false;
1592 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1593 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1594 if (host_)
1595 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1596 has_composition_text_ = false;
1599 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
1600 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1601 popup_child_host_view_->InsertChar(ch, flags);
1602 return;
1605 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1606 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
1607 double now = ui::EventTimeForNow().InSecondsF();
1608 // Send a blink::WebInputEvent::Char event to |host_|.
1609 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
1610 true /* is_char */,
1612 flags,
1613 now);
1614 ForwardKeyboardEvent(webkit_event);
1618 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
1619 return window_;
1622 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1623 return text_input_type_;
1626 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1627 return text_input_mode_;
1630 int RenderWidgetHostViewAura::GetTextInputFlags() const {
1631 return text_input_flags_;
1634 bool RenderWidgetHostViewAura::CanComposeInline() const {
1635 return can_compose_inline_;
1638 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
1639 const gfx::Rect& rect) const {
1640 gfx::Point origin = rect.origin();
1641 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1643 aura::Window* root_window = window_->GetRootWindow();
1644 if (!root_window)
1645 return rect;
1646 aura::client::ScreenPositionClient* screen_position_client =
1647 aura::client::GetScreenPositionClient(root_window);
1648 if (!screen_position_client)
1649 return rect;
1650 screen_position_client->ConvertPointToScreen(window_, &origin);
1651 screen_position_client->ConvertPointToScreen(window_, &end);
1652 return gfx::Rect(origin.x(),
1653 origin.y(),
1654 end.x() - origin.x(),
1655 end.y() - origin.y());
1658 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
1659 const gfx::Rect& rect) const {
1660 gfx::Point origin = rect.origin();
1661 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1663 aura::Window* root_window = window_->GetRootWindow();
1664 if (root_window) {
1665 aura::client::ScreenPositionClient* screen_position_client =
1666 aura::client::GetScreenPositionClient(root_window);
1667 screen_position_client->ConvertPointFromScreen(window_, &origin);
1668 screen_position_client->ConvertPointFromScreen(window_, &end);
1669 return gfx::Rect(origin.x(),
1670 origin.y(),
1671 end.x() - origin.x(),
1672 end.y() - origin.y());
1675 return rect;
1678 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1679 gfx::Rect rect =
1680 ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_);
1681 return ConvertRectToScreen(rect);
1684 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1685 uint32 index,
1686 gfx::Rect* rect) const {
1687 DCHECK(rect);
1688 if (index >= composition_character_bounds_.size())
1689 return false;
1690 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1691 return true;
1694 bool RenderWidgetHostViewAura::HasCompositionText() const {
1695 return has_composition_text_;
1698 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
1699 range->set_start(selection_text_offset_);
1700 range->set_end(selection_text_offset_ + selection_text_.length());
1701 return true;
1704 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1705 gfx::Range* range) const {
1706 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1707 NOTIMPLEMENTED();
1708 return false;
1711 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1712 range->set_start(selection_range_.start());
1713 range->set_end(selection_range_.end());
1714 return true;
1717 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1718 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1719 NOTIMPLEMENTED();
1720 return false;
1723 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1724 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1725 NOTIMPLEMENTED();
1726 return false;
1729 bool RenderWidgetHostViewAura::GetTextFromRange(
1730 const gfx::Range& range,
1731 base::string16* text) const {
1732 gfx::Range selection_text_range(selection_text_offset_,
1733 selection_text_offset_ + selection_text_.length());
1735 if (!selection_text_range.Contains(range)) {
1736 text->clear();
1737 return false;
1739 if (selection_text_range.EqualsIgnoringDirection(range)) {
1740 // Avoid calling substr whose performance is low.
1741 *text = selection_text_;
1742 } else {
1743 *text = selection_text_.substr(
1744 range.GetMin() - selection_text_offset_,
1745 range.length());
1747 return true;
1750 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1751 if (!host_)
1752 return;
1754 if (GetInputMethod())
1755 host_->SetInputMethodActive(GetInputMethod()->IsActive());
1757 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1758 // TextEvent.
1761 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1762 base::i18n::TextDirection direction) {
1763 if (!host_)
1764 return false;
1765 host_->UpdateTextDirection(
1766 direction == base::i18n::RIGHT_TO_LEFT ?
1767 blink::WebTextDirectionRightToLeft :
1768 blink::WebTextDirectionLeftToRight);
1769 host_->NotifyTextDirection();
1770 return true;
1773 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1774 size_t before, size_t after) {
1775 RenderFrameHostImpl* rfh = GetFocusedFrame();
1776 if (rfh)
1777 rfh->ExtendSelectionAndDelete(before, after);
1780 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1781 gfx::Rect intersected_rect(
1782 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1784 if (intersected_rect.IsEmpty())
1785 return;
1787 host_->ScrollFocusedEditableNodeIntoRect(
1788 ConvertRectFromScreen(intersected_rect));
1791 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
1792 host_->CandidateWindowShown();
1795 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
1796 host_->CandidateWindowUpdated();
1799 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
1800 host_->CandidateWindowHidden();
1803 bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id) {
1804 return false;
1807 void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id) {
1810 ////////////////////////////////////////////////////////////////////////////////
1811 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1813 void RenderWidgetHostViewAura::OnDisplayAdded(
1814 const gfx::Display& new_display) {
1817 void RenderWidgetHostViewAura::OnDisplayRemoved(
1818 const gfx::Display& old_display) {
1821 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
1822 const gfx::Display& display, uint32_t metrics) {
1823 // The screen info should be updated regardless of the metric change.
1824 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
1825 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
1826 UpdateScreenInfo(window_);
1827 current_cursor_.SetDisplayInfo(display);
1828 UpdateCursorIfOverSelf();
1832 ////////////////////////////////////////////////////////////////////////////////
1833 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1835 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1836 return gfx::Size();
1839 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
1840 return gfx::Size();
1843 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1844 const gfx::Rect& new_bounds) {
1845 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
1846 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1847 // WebContentsViewAura since changes to the Window's bounds need to be
1848 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1849 // SetBounds() itself. No matter how we got here, any redundant calls are
1850 // harmless.
1851 SetSize(new_bounds.size());
1853 if (GetInputMethod())
1854 GetInputMethod()->OnCaretBoundsChanged(this);
1857 ui::TextInputClient* RenderWidgetHostViewAura::GetFocusedTextInputClient() {
1858 return GetTextInputClient();
1861 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1862 if (mouse_locked_)
1863 return ui::kCursorNone;
1864 return current_cursor_.GetNativeCursor();
1867 int RenderWidgetHostViewAura::GetNonClientComponent(
1868 const gfx::Point& point) const {
1869 return HTCLIENT;
1872 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1873 aura::Window* child,
1874 const gfx::Point& location) {
1875 return true;
1878 bool RenderWidgetHostViewAura::CanFocus() {
1879 return popup_type_ == blink::WebPopupTypeNone;
1882 void RenderWidgetHostViewAura::OnCaptureLost() {
1883 host_->LostCapture();
1884 if (touch_editing_client_)
1885 touch_editing_client_->EndTouchEditing(false);
1888 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
1889 NOTREACHED();
1892 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1893 float device_scale_factor) {
1894 if (!host_ || !window_->GetRootWindow())
1895 return;
1897 UpdateScreenInfo(window_);
1899 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1900 GetDisplayNearestWindow(window_);
1901 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
1902 current_cursor_.SetDisplayInfo(display);
1903 SnapToPhysicalPixelBoundary();
1906 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
1907 #if defined(OS_WIN)
1908 HWND parent = NULL;
1909 // If the tab was hidden and it's closed, host_->is_hidden would have been
1910 // reset to false in RenderWidgetHostImpl::RendererExited.
1911 if (!window_->GetRootWindow() || host_->is_hidden()) {
1912 parent = ui::GetHiddenWindow();
1913 } else {
1914 parent = window_->GetHost()->GetAcceleratedWidget();
1916 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1917 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
1919 // The LegacyRenderWidgetHostHWND instance is destroyed when its window is
1920 // destroyed. Normally we control when that happens via the Destroy call
1921 // in the dtor. However there may be cases where the window is destroyed
1922 // by Windows, i.e. the parent window is destroyed before the
1923 // RenderWidgetHostViewAura instance goes away etc. To avoid that we
1924 // destroy the LegacyRenderWidgetHostHWND instance here.
1925 if (legacy_render_widget_host_HWND_) {
1926 legacy_render_widget_host_HWND_->set_host(NULL);
1927 legacy_render_widget_host_HWND_->Destroy();
1928 // The Destroy call above will delete the LegacyRenderWidgetHostHWND
1929 // instance.
1930 legacy_render_widget_host_HWND_ = NULL;
1932 #endif
1934 // Make sure that the input method no longer references to this object before
1935 // this object is removed from the root window (i.e. this object loses access
1936 // to the input method).
1937 ui::InputMethod* input_method = GetInputMethod();
1938 if (input_method)
1939 input_method->DetachTextInputClient(this);
1941 if (overscroll_controller_)
1942 overscroll_controller_->Reset();
1945 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1946 // Ask the RWH to drop reference to us.
1947 if (!is_guest_view_hack_)
1948 host_->ViewDestroyed();
1950 delete this;
1953 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1956 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1957 return false;
1960 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1963 ////////////////////////////////////////////////////////////////////////////////
1964 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1966 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1967 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1968 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1969 return;
1971 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1972 popup_child_host_view_->OnKeyEvent(event);
1973 if (event->handled())
1974 return;
1977 // We need to handle the Escape key for Pepper Flash.
1978 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
1979 // Focus the window we were created from.
1980 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
1981 aura::Window* host = *(host_tracker_->windows().begin());
1982 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
1983 if (client) {
1984 // Calling host->Focus() may delete |this|. We create a local observer
1985 // for that. In that case we exit without further access to any members.
1986 aura::WindowTracker tracker;
1987 aura::Window* window = window_;
1988 tracker.Add(window);
1989 host->Focus();
1990 if (!tracker.Contains(window)) {
1991 event->SetHandled();
1992 return;
1996 Shutdown();
1997 } else {
1998 if (event->key_code() == ui::VKEY_RETURN) {
1999 // Do not forward return key release events if no press event was handled.
2000 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
2001 return;
2002 // Accept return key character events between press and release events.
2003 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
2006 // We don't have to communicate with an input method here.
2007 NativeWebKeyboardEvent webkit_event(*event);
2008 ForwardKeyboardEvent(webkit_event);
2010 event->SetHandled();
2013 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
2014 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
2016 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2017 return;
2019 if (mouse_locked_) {
2020 aura::client::CursorClient* cursor_client =
2021 aura::client::GetCursorClient(window_->GetRootWindow());
2022 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
2024 if (event->type() == ui::ET_MOUSEWHEEL) {
2025 blink::WebMouseWheelEvent mouse_wheel_event =
2026 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2027 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2028 host_->ForwardWheelEvent(mouse_wheel_event);
2029 return;
2032 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
2034 // If we receive non client mouse messages while we are in the locked state
2035 // it probably means that the mouse left the borders of our window and
2036 // needs to be moved back to the center.
2037 if (event->flags() & ui::EF_IS_NON_CLIENT) {
2038 synthetic_move_sent_ = true;
2039 window_->MoveCursorTo(center);
2040 return;
2043 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2045 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
2046 event->type() == ui::ET_MOUSE_DRAGGED) &&
2047 mouse_event.x == center.x() && mouse_event.y == center.y();
2049 // For fractional scale factors, the conversion from pixels to dip and
2050 // vice versa could result in off by 1 or 2 errors which hurts us because
2051 // we want to avoid sending the artificial move to center event to the
2052 // renderer. Sending the move to center to the renderer cause the cursor
2053 // to bounce around the center of the screen leading to the lock operation
2054 // not working correctly.
2055 // Workaround is to treat a mouse move or drag event off by at most 2 px
2056 // from the center as a move to center event.
2057 if (synthetic_move_sent_ &&
2058 IsFractionalScaleFactor(current_device_scale_factor_)) {
2059 if (event->type() == ui::ET_MOUSE_MOVED ||
2060 event->type() == ui::ET_MOUSE_DRAGGED) {
2061 if ((abs(mouse_event.x - center.x()) <= 2) &&
2062 (abs(mouse_event.y - center.y()) <= 2)) {
2063 is_move_to_center_event = true;
2068 ModifyEventMovementAndCoords(&mouse_event);
2070 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
2071 if (should_not_forward) {
2072 synthetic_move_sent_ = false;
2073 } else {
2074 // Check if the mouse has reached the border and needs to be centered.
2075 if (ShouldMoveToCenter()) {
2076 synthetic_move_sent_ = true;
2077 window_->MoveCursorTo(center);
2079 bool is_selection_popup = popup_child_host_view_ &&
2080 popup_child_host_view_->NeedsInputGrab();
2081 // Forward event to renderer.
2082 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2083 !(event->flags() & ui::EF_FROM_TOUCH)) {
2084 host_->ForwardMouseEvent(mouse_event);
2085 // Ensure that we get keyboard focus on mouse down as a plugin window
2086 // may have grabbed keyboard focus.
2087 if (event->type() == ui::ET_MOUSE_PRESSED)
2088 SetKeyboardFocus();
2091 return;
2094 // As the overscroll is handled during scroll events from the trackpad, the
2095 // RWHVA window is transformed by the overscroll controller. This transform
2096 // triggers a synthetic mouse-move event to be generated (by the aura
2097 // RootWindow). But this event interferes with the overscroll gesture. So,
2098 // ignore such synthetic mouse-move events if an overscroll gesture is in
2099 // progress.
2100 if (overscroll_controller_ &&
2101 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE &&
2102 event->flags() & ui::EF_IS_SYNTHESIZED &&
2103 (event->type() == ui::ET_MOUSE_ENTERED ||
2104 event->type() == ui::ET_MOUSE_EXITED ||
2105 event->type() == ui::ET_MOUSE_MOVED)) {
2106 event->StopPropagation();
2107 return;
2110 if (event->type() == ui::ET_MOUSEWHEEL) {
2111 #if defined(OS_WIN)
2112 // We get mouse wheel/scroll messages even if we are not in the foreground.
2113 // So here we check if we have any owned popup windows in the foreground and
2114 // dismiss them.
2115 aura::WindowTreeHost* host = window_->GetHost();
2116 if (host) {
2117 HWND parent = host->GetAcceleratedWidget();
2118 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2119 EnumThreadWindows(GetCurrentThreadId(),
2120 DismissOwnedPopups,
2121 reinterpret_cast<LPARAM>(toplevel_hwnd));
2123 #endif
2124 // The Disambiguation popup does not parent itself from this window, so we
2125 // manually dismiss it.
2126 HideDisambiguationPopup();
2128 blink::WebMouseWheelEvent mouse_wheel_event =
2129 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2130 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2131 host_->ForwardWheelEvent(mouse_wheel_event);
2132 } else {
2133 bool is_selection_popup = popup_child_host_view_ &&
2134 popup_child_host_view_->NeedsInputGrab();
2135 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2136 !(event->flags() & ui::EF_FROM_TOUCH)) {
2137 // Confirm existing composition text on mouse press, to make sure
2138 // the input caret won't be moved with an ongoing composition text.
2139 if (event->type() == ui::ET_MOUSE_PRESSED)
2140 FinishImeCompositionSession();
2142 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2143 ModifyEventMovementAndCoords(&mouse_event);
2144 host_->ForwardMouseEvent(mouse_event);
2145 // Ensure that we get keyboard focus on mouse down as a plugin window may
2146 // have grabbed keyboard focus.
2147 if (event->type() == ui::ET_MOUSE_PRESSED)
2148 SetKeyboardFocus();
2152 switch (event->type()) {
2153 case ui::ET_MOUSE_PRESSED:
2154 window_->SetCapture();
2155 break;
2156 case ui::ET_MOUSE_RELEASED:
2157 if (!NeedsMouseCapture())
2158 window_->ReleaseCapture();
2159 break;
2160 default:
2161 break;
2164 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2165 // note that it might be something other than a WebContentsViewAura instance.
2166 // TODO(pkotwicz): Find a better way of doing this.
2167 // In fullscreen mode which is typically used by flash, don't forward
2168 // the mouse events to the parent. The renderer and the plugin process
2169 // handle these events.
2170 if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
2171 !(event->flags() & ui::EF_FROM_TOUCH)) {
2172 event->ConvertLocationToTarget(window_, window_->parent());
2173 window_->parent()->delegate()->OnMouseEvent(event);
2176 if (!IsXButtonUpEvent(event))
2177 event->SetHandled();
2180 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2181 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2182 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2183 return;
2185 if (event->type() == ui::ET_SCROLL) {
2186 #if !defined(OS_WIN)
2187 // TODO(ananta)
2188 // Investigate if this is true for Windows 8 Metro ASH as well.
2189 if (event->finger_count() != 2)
2190 return;
2191 #endif
2192 blink::WebGestureEvent gesture_event =
2193 MakeWebGestureEventFlingCancel();
2194 host_->ForwardGestureEvent(gesture_event);
2195 blink::WebMouseWheelEvent mouse_wheel_event =
2196 MakeWebMouseWheelEvent(*event);
2197 host_->ForwardWheelEvent(mouse_wheel_event);
2198 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2199 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2200 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2201 blink::WebGestureEvent gesture_event = MakeWebGestureEvent(*event);
2202 host_->ForwardGestureEvent(gesture_event);
2203 if (event->type() == ui::ET_SCROLL_FLING_START)
2204 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2207 event->SetHandled();
2210 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2211 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2212 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2213 return;
2215 // Update the touch event first.
2216 if (!pointer_state_.OnTouch(*event)) {
2217 event->StopPropagation();
2218 return;
2221 blink::WebTouchEvent touch_event = ui::CreateWebTouchEventFromMotionEvent(
2222 pointer_state_, event->may_cause_scrolling());
2223 pointer_state_.CleanupRemovedTouchPoints(*event);
2225 // It is important to always mark events as being handled asynchronously when
2226 // they are forwarded. This ensures that the current event does not get
2227 // processed by the gesture recognizer before events currently awaiting
2228 // dispatch in the touch queue.
2229 event->DisableSynchronousHandling();
2231 // Set unchanged touch point to StateStationary for touchmove and
2232 // touchcancel to make sure only send one ack per WebTouchEvent.
2233 MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id());
2234 host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency());
2237 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2238 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2239 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2240 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2241 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
2242 event->SetHandled();
2243 return;
2246 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2247 return;
2249 // Confirm existing composition text on TAP gesture, to make sure the input
2250 // caret won't be moved with an ongoing composition text.
2251 if (event->type() == ui::ET_GESTURE_TAP)
2252 FinishImeCompositionSession();
2254 blink::WebGestureEvent gesture = MakeWebGestureEvent(*event);
2255 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
2256 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2257 // event to stop any in-progress flings.
2258 blink::WebGestureEvent fling_cancel = gesture;
2259 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
2260 fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
2261 host_->ForwardGestureEvent(fling_cancel);
2264 if (gesture.type != blink::WebInputEvent::Undefined) {
2265 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
2267 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
2268 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
2269 event->type() == ui::ET_GESTURE_SCROLL_END) {
2270 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
2271 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
2272 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
2276 // If a gesture is not processed by the webpage, then WebKit processes it
2277 // (e.g. generates synthetic mouse events).
2278 event->SetHandled();
2281 ////////////////////////////////////////////////////////////////////////////////
2282 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2284 bool RenderWidgetHostViewAura::ShouldActivate() const {
2285 aura::WindowTreeHost* host = window_->GetHost();
2286 if (!host)
2287 return true;
2288 const ui::Event* event = host->dispatcher()->current_event();
2289 if (!event)
2290 return true;
2291 return is_fullscreen_;
2294 ////////////////////////////////////////////////////////////////////////////////
2295 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2297 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2298 NotifyRendererOfCursorVisibilityState(is_visible);
2301 ////////////////////////////////////////////////////////////////////////////////
2302 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2304 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2305 aura::Window* lost_focus) {
2306 DCHECK(window_ == gained_focus || window_ == lost_focus);
2307 if (window_ == gained_focus) {
2308 // We need to honor input bypass if the associated tab is does not want
2309 // input. This gives the current focused window a chance to be the text
2310 // input client and handle events.
2311 if (host_->ignore_input_events())
2312 return;
2314 host_->GotFocus();
2315 host_->SetActive(true);
2317 ui::InputMethod* input_method = GetInputMethod();
2318 if (input_method) {
2319 // Ask the system-wide IME to send all TextInputClient messages to |this|
2320 // object.
2321 input_method->SetFocusedTextInputClient(this);
2322 host_->SetInputMethodActive(input_method->IsActive());
2324 // Often the application can set focus to the view in response to a key
2325 // down. However the following char event shouldn't be sent to the web
2326 // page.
2327 host_->SuppressNextCharEvents();
2328 } else {
2329 host_->SetInputMethodActive(false);
2332 BrowserAccessibilityManager* manager =
2333 host_->GetRootBrowserAccessibilityManager();
2334 if (manager)
2335 manager->OnWindowFocused();
2336 } else if (window_ == lost_focus) {
2337 host_->SetActive(false);
2338 host_->Blur();
2340 DetachFromInputMethod();
2341 host_->SetInputMethodActive(false);
2343 if (touch_editing_client_)
2344 touch_editing_client_->EndTouchEditing(false);
2346 if (overscroll_controller_)
2347 overscroll_controller_->Cancel();
2349 BrowserAccessibilityManager* manager =
2350 host_->GetRootBrowserAccessibilityManager();
2351 if (manager)
2352 manager->OnWindowBlurred();
2354 // If we lose the focus while fullscreen, close the window; Pepper Flash
2355 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2356 // window if we lose the focus to a window on another display.
2357 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2358 bool focusing_other_display =
2359 gained_focus && screen->GetNumDisplays() > 1 &&
2360 (screen->GetDisplayNearestWindow(window_).id() !=
2361 screen->GetDisplayNearestWindow(gained_focus).id());
2362 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
2363 #if defined(OS_WIN)
2364 // On Windows, if we are switching to a non Aura Window on a different
2365 // screen we should not close the fullscreen window.
2366 if (!gained_focus) {
2367 POINT point = {0};
2368 ::GetCursorPos(&point);
2369 if (screen->GetDisplayNearestWindow(window_).id() !=
2370 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2371 return;
2373 #endif
2374 Shutdown();
2375 return;
2378 // Close the child popup window if we lose focus (e.g. due to a JS alert or
2379 // system modal dialog). This is particularly important if
2380 // |popup_child_host_view_| has mouse capture.
2381 if (popup_child_host_view_)
2382 popup_child_host_view_->Shutdown();
2386 ////////////////////////////////////////////////////////////////////////////////
2387 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2389 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
2390 const gfx::Point& new_origin) {
2391 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2392 "new_origin", new_origin.ToString());
2394 UpdateScreenInfo(window_);
2397 ////////////////////////////////////////////////////////////////////////////////
2398 // RenderWidgetHostViewAura, private:
2400 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2401 if (touch_editing_client_)
2402 touch_editing_client_->OnViewDestroyed();
2404 delegated_frame_host_.reset();
2405 window_observer_.reset();
2406 if (window_->GetHost())
2407 window_->GetHost()->RemoveObserver(this);
2408 UnlockMouse();
2409 if (popup_parent_host_view_) {
2410 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
2411 popup_parent_host_view_->popup_child_host_view_ == this);
2412 popup_parent_host_view_->popup_child_host_view_ = NULL;
2414 if (popup_child_host_view_) {
2415 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
2416 popup_child_host_view_->popup_parent_host_view_ == this);
2417 popup_child_host_view_->popup_parent_host_view_ = NULL;
2419 event_filter_for_popup_exit_.reset();
2420 aura::client::SetTooltipText(window_, NULL);
2421 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
2423 // This call is usually no-op since |this| object is already removed from the
2424 // Aura root window and we don't have a way to get an input method object
2425 // associated with the window, but just in case.
2426 DetachFromInputMethod();
2428 #if defined(OS_WIN)
2429 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2430 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2431 // be set to NULL.
2432 DCHECK(!legacy_render_widget_host_HWND_);
2433 #endif
2436 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2437 const gfx::Point screen_point =
2438 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2439 aura::Window* root_window = window_->GetRootWindow();
2440 if (!root_window)
2441 return;
2443 gfx::Point root_window_point = screen_point;
2444 aura::client::ScreenPositionClient* screen_position_client =
2445 aura::client::GetScreenPositionClient(root_window);
2446 if (screen_position_client) {
2447 screen_position_client->ConvertPointFromScreen(
2448 root_window, &root_window_point);
2451 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
2452 return;
2454 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
2455 // Do not show loading cursor when the cursor is currently hidden.
2456 if (is_loading_ && cursor != ui::kCursorNone)
2457 cursor = ui::kCursorPointer;
2459 aura::client::CursorClient* cursor_client =
2460 aura::client::GetCursorClient(root_window);
2461 if (cursor_client) {
2462 cursor_client->SetCursor(cursor);
2466 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2467 aura::Window* root_window = window_->GetRootWindow();
2468 if (!root_window)
2469 return NULL;
2470 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
2473 void RenderWidgetHostViewAura::Shutdown() {
2474 if (!in_shutdown_) {
2475 in_shutdown_ = true;
2476 host_->Shutdown();
2480 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2481 return popup_type_ == blink::WebPopupTypeSelect ||
2482 popup_type_ == blink::WebPopupTypePage;
2485 bool RenderWidgetHostViewAura::NeedsMouseCapture() {
2486 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2487 return NeedsInputGrab();
2488 #endif
2489 return false;
2492 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2493 if (!has_composition_text_)
2494 return;
2495 if (host_) {
2496 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2497 false);
2499 ImeCancelComposition();
2502 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2503 blink::WebMouseEvent* event) {
2504 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2505 // reset any global_mouse_position set previously.
2506 if (event->type == blink::WebInputEvent::MouseEnter ||
2507 event->type == blink::WebInputEvent::MouseLeave)
2508 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2510 // Movement is computed by taking the difference of the new cursor position
2511 // and the previous. Under mouse lock the cursor will be warped back to the
2512 // center so that we are not limited by clipping boundaries.
2513 // We do not measure movement as the delta from cursor to center because
2514 // we may receive more mouse movement events before our warp has taken
2515 // effect.
2516 event->movementX = event->globalX - global_mouse_position_.x();
2517 event->movementY = event->globalY - global_mouse_position_.y();
2519 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2521 // Under mouse lock, coordinates of mouse are locked to what they were when
2522 // mouse lock was entered.
2523 if (mouse_locked_) {
2524 event->x = unlocked_mouse_position_.x();
2525 event->y = unlocked_mouse_position_.y();
2526 event->windowX = unlocked_mouse_position_.x();
2527 event->windowY = unlocked_mouse_position_.y();
2528 event->globalX = unlocked_global_mouse_position_.x();
2529 event->globalY = unlocked_global_mouse_position_.y();
2530 } else {
2531 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
2532 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2536 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2537 bool is_visible) {
2538 if (host_->is_hidden() ||
2539 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2540 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2541 return;
2543 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2544 host_->SendCursorVisibilityState(is_visible);
2547 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
2548 if (!enabled)
2549 overscroll_controller_.reset();
2550 else if (!overscroll_controller_)
2551 overscroll_controller_.reset(new OverscrollController());
2554 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
2555 // The top left corner of our view in window coordinates might not land on a
2556 // device pixel boundary if we have a non-integer device scale. In that case,
2557 // to avoid the web contents area looking blurry we translate the web contents
2558 // in the +x, +y direction to land on the nearest pixel boundary. This may
2559 // cause the bottom and right edges to be clipped slightly, but that's ok.
2560 aura::Window* snapped = NULL;
2561 // On desktop, use the root window. On alternative environment (ash),
2562 // use the toplevel window which must be already snapped.
2563 if (gfx::Screen::GetScreenFor(window_) !=
2564 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
2565 snapped = window_->GetRootWindow();
2566 } else {
2567 snapped = window_->GetToplevelWindow();
2569 if (snapped && snapped != window_)
2570 ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
2572 has_snapped_to_boundary_ = true;
2575 void RenderWidgetHostViewAura::OnShowContextMenu() {
2576 #if defined(OS_WIN)
2577 showing_context_menu_ = true;
2578 #endif
2581 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
2582 SnapToPhysicalPixelBoundary();
2583 // Don't recursively call SetBounds if this bounds update is the result of
2584 // a Window::SetBoundsInternal call.
2585 if (!in_bounds_changed_)
2586 window_->SetBounds(rect);
2587 host_->WasResized();
2588 delegated_frame_host_->WasResized();
2589 if (touch_editing_client_) {
2590 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_,
2591 selection_focus_);
2593 #if defined(OS_WIN)
2594 // Create the legacy dummy window which corresponds to the bounds of the
2595 // webcontents. This will be passed as the container window for windowless
2596 // plugins.
2597 // Plugins like Flash assume the container window which is returned via the
2598 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
2599 // This is not true in Aura where we have only HWND which is the main Aura
2600 // window. If we return this window to plugins like Flash then it causes the
2601 // coordinate translations done by these plugins to break.
2602 // Additonally the legacy dummy window is needed for accessibility and for
2603 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
2604 if (!legacy_window_destroyed_ && GetNativeViewId()) {
2605 if (!legacy_render_widget_host_HWND_) {
2606 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
2607 reinterpret_cast<HWND>(GetNativeViewId()));
2609 if (legacy_render_widget_host_HWND_) {
2610 legacy_render_widget_host_HWND_->set_host(this);
2611 legacy_render_widget_host_HWND_->SetBounds(
2612 window_->GetBoundsInRootWindow());
2613 // There are cases where the parent window is created, made visible and
2614 // the associated RenderWidget is also visible before the
2615 // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
2616 // here.
2617 if (!host_->is_hidden())
2618 legacy_render_widget_host_HWND_->Show();
2622 if (mouse_locked_)
2623 UpdateMouseLockRegion();
2624 #endif
2627 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2628 const gfx::Rect& rect,
2629 const gfx::Rect& clip) {
2630 if (!clip.IsEmpty()) {
2631 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
2632 if (!to_paint.IsEmpty())
2633 window_->SchedulePaintInRect(to_paint);
2634 } else {
2635 window_->SchedulePaintInRect(rect);
2639 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2640 gfx::Rect rect = window_->bounds();
2641 rect = ConvertRectToScreen(rect);
2642 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
2643 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
2645 return global_mouse_position_.x() < rect.x() + border_x ||
2646 global_mouse_position_.x() > rect.right() - border_x ||
2647 global_mouse_position_.y() < rect.y() + border_y ||
2648 global_mouse_position_.y() > rect.bottom() - border_y;
2651 void RenderWidgetHostViewAura::AddedToRootWindow() {
2652 window_->GetHost()->AddObserver(this);
2653 UpdateScreenInfo(window_);
2655 aura::client::CursorClient* cursor_client =
2656 aura::client::GetCursorClient(window_->GetRootWindow());
2657 if (cursor_client) {
2658 cursor_client->AddObserver(this);
2659 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
2661 if (HasFocus()) {
2662 ui::InputMethod* input_method = GetInputMethod();
2663 if (input_method)
2664 input_method->SetFocusedTextInputClient(this);
2667 #if defined(OS_WIN)
2668 // The parent may have changed here. Ensure that the legacy window is
2669 // reparented accordingly.
2670 if (legacy_render_widget_host_HWND_)
2671 legacy_render_widget_host_HWND_->UpdateParent(
2672 reinterpret_cast<HWND>(GetNativeViewId()));
2673 #endif
2675 delegated_frame_host_->SetCompositor(window_->GetHost()->compositor());
2676 if (window_->GetHost()->compositor())
2677 begin_frame_observer_proxy_.SetCompositor(window_->GetHost()->compositor());
2680 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2681 aura::client::CursorClient* cursor_client =
2682 aura::client::GetCursorClient(window_->GetRootWindow());
2683 if (cursor_client)
2684 cursor_client->RemoveObserver(this);
2686 DetachFromInputMethod();
2688 window_->GetHost()->RemoveObserver(this);
2689 delegated_frame_host_->ResetCompositor();
2690 begin_frame_observer_proxy_.ResetCompositor();
2692 #if defined(OS_WIN)
2693 // Update the legacy window's parent temporarily to the desktop window. It
2694 // will eventually get reparented to the right root.
2695 if (legacy_render_widget_host_HWND_)
2696 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
2697 #endif
2700 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2701 ui::InputMethod* input_method = GetInputMethod();
2702 if (input_method && input_method->GetTextInputClient() == this)
2703 input_method->SetFocusedTextInputClient(NULL);
2706 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2707 const NativeWebKeyboardEvent& event) {
2708 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2709 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
2710 ui::GetTextEditKeyBindingsDelegate();
2711 std::vector<ui::TextEditCommandAuraLinux> commands;
2712 if (!event.skip_in_browser &&
2713 keybinding_delegate &&
2714 event.os_event &&
2715 keybinding_delegate->MatchEvent(*event.os_event, &commands)) {
2716 // Transform from ui/ types to content/ types.
2717 EditCommands edit_commands;
2718 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it =
2719 commands.begin(); it != commands.end(); ++it) {
2720 edit_commands.push_back(EditCommand(it->GetCommandString(),
2721 it->argument()));
2723 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2724 host_->GetRoutingID(), edit_commands));
2725 NativeWebKeyboardEvent copy_event(event);
2726 copy_event.match_edit_command = true;
2727 host_->ForwardKeyboardEvent(copy_event);
2728 return;
2730 #endif
2732 host_->ForwardKeyboardEvent(event);
2735 ////////////////////////////////////////////////////////////////////////////////
2736 // DelegatedFrameHost, public:
2738 ui::Layer* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const {
2739 return window_->layer();
2742 bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const {
2743 return !host_->is_hidden();
2746 gfx::Size RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const {
2747 return window_->bounds().size();
2750 bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const {
2751 #if !defined(OS_CHROMEOS)
2752 // On Windows and Linux, holding pointer moves will not help throttling
2753 // resizes.
2754 // TODO(piman): on Windows we need to block (nested message loop?) the
2755 // WM_SIZE event. On Linux we need to throttle at the WM level using
2756 // _NET_WM_SYNC_REQUEST.
2757 return false;
2758 #else
2759 if (host_->auto_resize_enabled())
2760 return false;
2761 return true;
2762 #endif
2765 scoped_ptr<ResizeLock>
2766 RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock(
2767 bool defer_compositor_lock) {
2768 gfx::Size desired_size = window_->bounds().size();
2769 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
2770 window_->GetHost(),
2771 desired_size,
2772 defer_compositor_lock,
2773 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2776 void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() {
2777 host_->WasResized();
2780 void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck(
2781 int output_surface_id,
2782 const cc::CompositorFrameAck& ack) {
2783 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
2784 output_surface_id, ack));
2787 void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
2788 int output_surface_id,
2789 const cc::CompositorFrameAck& ack) {
2790 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
2791 output_surface_id, ack));
2794 void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
2795 host_->ScheduleComposite();
2798 void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters(
2799 const base::TimeTicks& timebase,
2800 const base::TimeDelta& interval) {
2801 host_->UpdateVSyncParameters(timebase, interval);
2804 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
2805 ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
2808 uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
2809 return delegated_frame_host_->GetSurfaceIdNamespace();
2812 ////////////////////////////////////////////////////////////////////////////////
2813 // RenderWidgetHostViewBase, public:
2815 // static
2816 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2817 GetScreenInfoForWindow(results, NULL);
2820 } // namespace content