Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / renderer_host / render_widget_host_view_aura.cc
blob146355707f08f247446929d5c6c0d22d7b5e11e2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/trace_event/trace_event.h"
16 #include "cc/layers/layer.h"
17 #include "cc/output/copy_output_request.h"
18 #include "cc/output/copy_output_result.h"
19 #include "cc/resources/texture_mailbox.h"
20 #include "cc/trees/layer_tree_settings.h"
21 #include "content/browser/accessibility/browser_accessibility_manager.h"
22 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
23 #include "content/browser/bad_message.h"
24 #include "content/browser/frame_host/frame_tree.h"
25 #include "content/browser/frame_host/frame_tree_node.h"
26 #include "content/browser/frame_host/render_frame_host_impl.h"
27 #include "content/browser/gpu/compositor_util.h"
28 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
29 #include "content/browser/renderer_host/dip_util.h"
30 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
31 #include "content/browser/renderer_host/input/web_input_event_util.h"
32 #include "content/browser/renderer_host/overscroll_controller.h"
33 #include "content/browser/renderer_host/render_view_host_delegate.h"
34 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
35 #include "content/browser/renderer_host/render_view_host_impl.h"
36 #include "content/browser/renderer_host/render_widget_host_impl.h"
37 #include "content/browser/renderer_host/ui_events_helper.h"
38 #include "content/browser/renderer_host/web_input_event_aura.h"
39 #include "content/common/gpu/client/gl_helper.h"
40 #include "content/common/gpu/gpu_messages.h"
41 #include "content/common/view_messages.h"
42 #include "content/public/browser/content_browser_client.h"
43 #include "content/public/browser/overscroll_configuration.h"
44 #include "content/public/browser/render_view_host.h"
45 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
46 #include "content/public/browser/user_metrics.h"
47 #include "content/public/common/content_switches.h"
48 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
49 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
50 #include "third_party/WebKit/public/web/WebInputEvent.h"
51 #include "ui/aura/client/aura_constants.h"
52 #include "ui/aura/client/cursor_client.h"
53 #include "ui/aura/client/cursor_client_observer.h"
54 #include "ui/aura/client/focus_client.h"
55 #include "ui/aura/client/screen_position_client.h"
56 #include "ui/aura/client/window_tree_client.h"
57 #include "ui/aura/env.h"
58 #include "ui/aura/window.h"
59 #include "ui/aura/window_event_dispatcher.h"
60 #include "ui/aura/window_observer.h"
61 #include "ui/aura/window_tracker.h"
62 #include "ui/aura/window_tree_host.h"
63 #include "ui/base/clipboard/scoped_clipboard_writer.h"
64 #include "ui/base/hit_test.h"
65 #include "ui/base/ime/input_method.h"
66 #include "ui/base/ui_base_types.h"
67 #include "ui/compositor/compositor_vsync_manager.h"
68 #include "ui/compositor/dip_util.h"
69 #include "ui/events/blink/blink_event_util.h"
70 #include "ui/events/event.h"
71 #include "ui/events/event_utils.h"
72 #include "ui/events/gestures/gesture_recognizer.h"
73 #include "ui/gfx/canvas.h"
74 #include "ui/gfx/display.h"
75 #include "ui/gfx/geometry/rect_conversions.h"
76 #include "ui/gfx/geometry/size_conversions.h"
77 #include "ui/gfx/screen.h"
78 #include "ui/gfx/skia_util.h"
79 #include "ui/wm/public/activation_client.h"
80 #include "ui/wm/public/scoped_tooltip_disabler.h"
81 #include "ui/wm/public/tooltip_client.h"
82 #include "ui/wm/public/transient_window_client.h"
83 #include "ui/wm/public/window_types.h"
85 #if defined(OS_WIN)
86 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
87 #include "content/browser/accessibility/browser_accessibility_win.h"
88 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
89 #include "content/common/plugin_constants_win.h"
90 #include "ui/base/win/hidden_window.h"
91 #include "ui/gfx/gdi_util.h"
92 #include "ui/gfx/win/dpi.h"
93 #endif
95 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
96 #include "content/common/input_messages.h"
97 #include "ui/events/linux/text_edit_command_auralinux.h"
98 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
99 #endif
101 using gfx::RectToSkIRect;
102 using gfx::SkIRectToRect;
104 using blink::WebScreenInfo;
105 using blink::WebInputEvent;
106 using blink::WebGestureEvent;
107 using blink::WebTouchEvent;
109 namespace content {
111 namespace {
113 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
114 // the border of the view, in order to get valid movement information. However,
115 // forcing the cursor back to the center of the view after each mouse move
116 // doesn't work well. It reduces the frequency of useful mouse move messages
117 // significantly. Therefore, we move the cursor to the center of the view only
118 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
119 // of the border area, in percentage of the corresponding dimension.
120 const int kMouseLockBorderPercentage = 15;
122 // When accelerated compositing is enabled and a widget resize is pending,
123 // we delay further resizes of the UI. The following constant is the maximum
124 // length of time that we should delay further UI resizes while waiting for a
125 // resized frame from a renderer.
126 const int kResizeLockTimeoutMs = 67;
128 #if defined(OS_WIN)
129 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
130 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
132 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
133 RenderWidgetHostViewAura* widget =
134 reinterpret_cast<RenderWidgetHostViewAura*>(param);
135 if (GetProp(window, kWidgetOwnerProperty) == widget) {
136 // Properties set on HWNDs must be removed to avoid leaks.
137 RemoveProp(window, kWidgetOwnerProperty);
138 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
140 return TRUE;
143 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
144 RenderWidgetHostViewAura* widget =
145 reinterpret_cast<RenderWidgetHostViewAura*>(param);
146 if (GetProp(window, kWidgetOwnerProperty) == widget)
147 SetParent(window, ui::GetHiddenWindow());
148 return TRUE;
151 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
152 RenderWidgetHostViewAura* widget =
153 reinterpret_cast<RenderWidgetHostViewAura*>(param);
155 if (GetProp(window, kWidgetOwnerProperty) == widget &&
156 widget->GetNativeView()->GetHost()) {
157 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
158 SetParent(window, parent);
160 return TRUE;
163 struct CutoutRectsParams {
164 RenderWidgetHostViewAura* widget;
165 std::vector<gfx::Rect> cutout_rects;
166 std::map<HWND, WebPluginGeometry>* geometry;
169 // Used to update the region for the windowed plugin to draw in. We start with
170 // the clip rect from the renderer, then remove the cutout rects from the
171 // renderer, and then remove the transient windows from the root window and the
172 // constrained windows from the parent window.
173 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
174 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
176 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
177 // First calculate the offset of this plugin from the root window, since
178 // the cutouts are relative to the root window.
179 HWND parent =
180 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
181 POINT offset;
182 offset.x = offset.y = 0;
183 MapWindowPoints(window, parent, &offset, 1);
185 // Now get the cached clip rect and cutouts for this plugin window that came
186 // from the renderer.
187 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
188 while (i != params->geometry->end() &&
189 i->second.window != window &&
190 GetParent(i->second.window) != window) {
191 ++i;
194 if (i == params->geometry->end()) {
195 NOTREACHED();
196 return TRUE;
199 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
200 i->second.clip_rect.y(),
201 i->second.clip_rect.right(),
202 i->second.clip_rect.bottom());
203 // We start with the cutout rects that came from the renderer, then add the
204 // ones that came from transient and constrained windows.
205 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
206 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
207 gfx::Rect offset_cutout = params->cutout_rects[i];
208 offset_cutout.Offset(-offset.x, -offset.y);
209 cutout_rects.push_back(offset_cutout);
211 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
212 // If we don't have any cutout rects then no point in messing with the
213 // window region.
214 if (cutout_rects.size())
215 SetWindowRgn(window, hrgn, TRUE);
217 return TRUE;
220 // A callback function for EnumThreadWindows to enumerate and dismiss
221 // any owned popup windows.
222 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
223 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
225 if (::IsWindowVisible(window)) {
226 const HWND owner = ::GetWindow(window, GW_OWNER);
227 if (toplevel_hwnd == owner) {
228 ::PostMessage(window, WM_CANCELMODE, 0, 0);
232 return TRUE;
234 #endif
236 // We don't mark these as handled so that they're sent back to the
237 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
238 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
239 #if defined(OS_WIN)
240 switch (event->native_event().message) {
241 case WM_XBUTTONUP:
242 case WM_NCXBUTTONUP:
243 return true;
245 #endif
246 return false;
249 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
250 const gfx::Display display = window ?
251 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
252 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
253 results->rect = display.bounds();
254 results->availableRect = display.work_area();
255 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
256 results->depth = 24;
257 results->depthPerComponent = 8;
258 results->deviceScaleFactor = display.device_scale_factor();
260 // The Display rotation and the WebScreenInfo orientation are not the same
261 // angle. The former is the physical display rotation while the later is the
262 // rotation required by the content to be shown properly on the screen, in
263 // other words, relative to the physical display.
264 results->orientationAngle = display.RotationAsDegree();
265 if (results->orientationAngle == 90)
266 results->orientationAngle = 270;
267 else if (results->orientationAngle == 270)
268 results->orientationAngle = 90;
270 results->orientationType =
271 RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
274 bool IsFractionalScaleFactor(float scale_factor) {
275 return (scale_factor - static_cast<int>(scale_factor)) > 0;
278 } // namespace
280 // We need to watch for mouse events outside a Web Popup or its parent
281 // and dismiss the popup for certain events.
282 class RenderWidgetHostViewAura::EventFilterForPopupExit
283 : public ui::EventHandler {
284 public:
285 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
286 : rwhva_(rwhva) {
287 DCHECK(rwhva_);
288 aura::Env::GetInstance()->AddPreTargetHandler(this);
291 ~EventFilterForPopupExit() override {
292 aura::Env::GetInstance()->RemovePreTargetHandler(this);
295 // Overridden from ui::EventHandler
296 void OnMouseEvent(ui::MouseEvent* event) override {
297 rwhva_->ApplyEventFilterForPopupExit(event);
300 void OnTouchEvent(ui::TouchEvent* event) override {
301 rwhva_->ApplyEventFilterForPopupExit(event);
304 private:
305 RenderWidgetHostViewAura* rwhva_;
307 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
310 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
311 ui::LocatedEvent* event) {
312 if (in_shutdown_ || is_fullscreen_ || !event->target())
313 return;
315 if (event->type() != ui::ET_MOUSE_PRESSED &&
316 event->type() != ui::ET_TOUCH_PRESSED) {
317 return;
320 aura::Window* target = static_cast<aura::Window*>(event->target());
321 if (target != window_ &&
322 (!popup_parent_host_view_ ||
323 target != popup_parent_host_view_->window_)) {
324 // Note: popup_parent_host_view_ may be NULL when there are multiple
325 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
326 Shutdown();
330 // We have to implement the WindowObserver interface on a separate object
331 // because clang doesn't like implementing multiple interfaces that have
332 // methods with the same name. This object is owned by the
333 // RenderWidgetHostViewAura.
334 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
335 public:
336 explicit WindowObserver(RenderWidgetHostViewAura* view)
337 : view_(view) {
338 view_->window_->AddObserver(this);
341 ~WindowObserver() override { view_->window_->RemoveObserver(this); }
343 // Overridden from aura::WindowObserver:
344 void OnWindowAddedToRootWindow(aura::Window* window) override {
345 if (window == view_->window_)
346 view_->AddedToRootWindow();
349 void OnWindowRemovingFromRootWindow(aura::Window* window,
350 aura::Window* new_root) override {
351 if (window == view_->window_)
352 view_->RemovingFromRootWindow();
355 private:
356 RenderWidgetHostViewAura* view_;
358 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
361 ////////////////////////////////////////////////////////////////////////////////
362 // RenderWidgetHostViewAura, public:
364 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
365 bool is_guest_view_hack)
366 : host_(RenderWidgetHostImpl::From(host)),
367 window_(new aura::Window(this)),
368 delegated_frame_host_(new DelegatedFrameHost(this)),
369 in_shutdown_(false),
370 in_bounds_changed_(false),
371 is_fullscreen_(false),
372 popup_parent_host_view_(NULL),
373 popup_child_host_view_(NULL),
374 is_loading_(false),
375 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
376 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
377 text_input_flags_(0),
378 can_compose_inline_(true),
379 has_composition_text_(false),
380 accept_return_character_(false),
381 last_swapped_software_frame_scale_factor_(1.f),
382 paint_canvas_(NULL),
383 synthetic_move_sent_(false),
384 cursor_visibility_state_in_renderer_(UNKNOWN),
385 #if defined(OS_WIN)
386 legacy_render_widget_host_HWND_(NULL),
387 legacy_window_destroyed_(false),
388 showing_context_menu_(false),
389 #endif
390 has_snapped_to_boundary_(false),
391 touch_editing_client_(NULL),
392 is_guest_view_hack_(is_guest_view_hack),
393 weak_ptr_factory_(this) {
394 if (!is_guest_view_hack_)
395 host_->SetView(this);
397 window_observer_.reset(new WindowObserver(this));
398 aura::client::SetTooltipText(window_, &tooltip_);
399 aura::client::SetActivationDelegate(window_, this);
400 aura::client::SetFocusChangeObserver(window_, this);
401 window_->set_layer_owner_delegate(delegated_frame_host_.get());
402 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
404 bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
405 GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
406 SetOverscrollControllerEnabled(overscroll_enabled);
409 ////////////////////////////////////////////////////////////////////////////////
410 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
412 bool RenderWidgetHostViewAura::OnMessageReceived(
413 const IPC::Message& message) {
414 bool handled = true;
415 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
416 // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
417 // messages for TextInput<State|Type>Changed. Corresponding code in
418 // RenderWidgetHostViewAndroid should also be moved at the same time.
419 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
420 OnTextInputStateChanged)
421 IPC_MESSAGE_UNHANDLED(handled = false)
422 IPC_END_MESSAGE_MAP()
423 return handled;
426 void RenderWidgetHostViewAura::InitAsChild(
427 gfx::NativeView parent_view) {
428 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
429 window_->Init(ui::LAYER_SOLID_COLOR);
430 window_->SetName("RenderWidgetHostViewAura");
431 window_->layer()->SetColor(background_color_);
434 void RenderWidgetHostViewAura::InitAsPopup(
435 RenderWidgetHostView* parent_host_view,
436 const gfx::Rect& bounds_in_screen) {
437 popup_parent_host_view_ =
438 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
440 // TransientWindowClient may be NULL during tests.
441 aura::client::TransientWindowClient* transient_window_client =
442 aura::client::GetTransientWindowClient();
443 RenderWidgetHostViewAura* old_child =
444 popup_parent_host_view_->popup_child_host_view_;
445 if (old_child) {
446 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
447 // similar mechanism to ensure a second popup doesn't cause the first one
448 // to never get a chance to filter events. See crbug.com/160589.
449 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
450 if (transient_window_client) {
451 transient_window_client->RemoveTransientChild(
452 popup_parent_host_view_->window_, old_child->window_);
454 old_child->popup_parent_host_view_ = NULL;
456 popup_parent_host_view_->popup_child_host_view_ = this;
457 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
458 window_->Init(ui::LAYER_SOLID_COLOR);
459 window_->SetName("RenderWidgetHostViewAura");
460 window_->layer()->SetColor(background_color_);
462 // Setting the transient child allows for the popup to get mouse events when
463 // in a system modal dialog. Do this before calling ParentWindowWithContext
464 // below so that the transient parent is visible to WindowTreeClient.
465 // This fixes crbug.com/328593.
466 if (transient_window_client) {
467 transient_window_client->AddTransientChild(
468 popup_parent_host_view_->window_, window_);
471 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
472 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
474 SetBounds(bounds_in_screen);
475 Show();
476 if (NeedsMouseCapture())
477 window_->SetCapture();
479 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
482 void RenderWidgetHostViewAura::InitAsFullscreen(
483 RenderWidgetHostView* reference_host_view) {
484 is_fullscreen_ = true;
485 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
486 window_->Init(ui::LAYER_SOLID_COLOR);
487 window_->SetName("RenderWidgetHostViewAura");
488 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
489 window_->layer()->SetColor(background_color_);
491 aura::Window* parent = NULL;
492 gfx::Rect bounds;
493 if (reference_host_view) {
494 aura::Window* reference_window =
495 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
496 if (reference_window) {
497 host_tracker_.reset(new aura::WindowTracker);
498 host_tracker_->Add(reference_window);
500 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
501 GetDisplayNearestWindow(reference_window);
502 parent = reference_window->GetRootWindow();
503 bounds = display.bounds();
505 aura::client::ParentWindowWithContext(window_, parent, bounds);
506 Show();
507 Focus();
510 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
511 return host_;
514 void RenderWidgetHostViewAura::Show() {
515 window_->Show();
517 DCHECK(host_);
518 if (!host_->is_hidden())
519 return;
521 bool has_saved_frame = delegated_frame_host_->HasSavedFrame();
522 ui::LatencyInfo renderer_latency_info, browser_latency_info;
523 if (has_saved_frame) {
524 browser_latency_info.AddLatencyNumber(
525 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
526 } else {
527 renderer_latency_info.AddLatencyNumber(
528 ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
530 host_->WasShown(renderer_latency_info);
532 aura::Window* root = window_->GetRootWindow();
533 if (root) {
534 aura::client::CursorClient* cursor_client =
535 aura::client::GetCursorClient(root);
536 if (cursor_client)
537 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
540 delegated_frame_host_->WasShown(browser_latency_info);
542 #if defined(OS_WIN)
543 if (legacy_render_widget_host_HWND_) {
544 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
545 // window before reparenting any plugins. This ensures that the plugin
546 // windows stay on top of the child Zorder in the parent and receive
547 // mouse events, etc.
548 legacy_render_widget_host_HWND_->UpdateParent(
549 GetNativeView()->GetHost()->GetAcceleratedWidget());
550 legacy_render_widget_host_HWND_->SetBounds(
551 window_->GetBoundsInRootWindow());
553 LPARAM lparam = reinterpret_cast<LPARAM>(this);
554 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
556 if (legacy_render_widget_host_HWND_)
557 legacy_render_widget_host_HWND_->Show();
558 #endif
561 void RenderWidgetHostViewAura::Hide() {
562 window_->Hide();
564 if (host_ && !host_->is_hidden()) {
565 host_->WasHidden();
566 delegated_frame_host_->WasHidden();
568 #if defined(OS_WIN)
569 constrained_rects_.clear();
570 aura::WindowTreeHost* host = window_->GetHost();
571 if (host) {
572 HWND parent = host->GetAcceleratedWidget();
573 LPARAM lparam = reinterpret_cast<LPARAM>(this);
574 EnumChildWindows(parent, HideWindowsCallback, lparam);
575 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
576 // hidden window on the same lines as Windowed plugin windows.
577 if (legacy_render_widget_host_HWND_)
578 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
580 #endif
583 #if defined(OS_WIN)
584 if (legacy_render_widget_host_HWND_)
585 legacy_render_widget_host_HWND_->Hide();
586 #endif
589 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
590 // For a SetSize operation, we don't care what coordinate system the origin
591 // of the window is in, it's only important to make sure that the origin
592 // remains constant after the operation.
593 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
596 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
597 gfx::Point relative_origin(rect.origin());
599 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
600 // Window::SetBounds() takes parent coordinates, so do the conversion here.
601 aura::Window* root = window_->GetRootWindow();
602 if (root) {
603 aura::client::ScreenPositionClient* screen_position_client =
604 aura::client::GetScreenPositionClient(root);
605 if (screen_position_client) {
606 screen_position_client->ConvertPointFromScreen(
607 window_->parent(), &relative_origin);
611 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
614 gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
615 return last_scroll_offset_;
618 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
619 return window_;
622 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
623 #if defined(OS_WIN)
624 aura::WindowTreeHost* host = window_->GetHost();
625 if (host)
626 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
627 #endif
628 return static_cast<gfx::NativeViewId>(NULL);
631 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
632 #if defined(OS_WIN)
633 aura::WindowTreeHost* host = window_->GetHost();
634 if (!host)
635 return static_cast<gfx::NativeViewAccessible>(NULL);
636 BrowserAccessibilityManager* manager =
637 host_->GetOrCreateRootBrowserAccessibilityManager();
638 if (manager)
639 return manager->GetRoot()->ToBrowserAccessibilityWin();
640 #endif
642 NOTIMPLEMENTED();
643 return static_cast<gfx::NativeViewAccessible>(NULL);
646 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
647 return this;
650 void RenderWidgetHostViewAura::SetKeyboardFocus() {
651 #if defined(OS_WIN)
652 if (CanFocus()) {
653 aura::WindowTreeHost* host = window_->GetHost();
654 if (host)
655 ::SetFocus(host->GetAcceleratedWidget());
657 #endif
660 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
661 if (!host_->IsRenderView())
662 return NULL;
663 RenderViewHost* rvh = RenderViewHost::From(host_);
664 FrameTreeNode* focused_frame =
665 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
666 if (!focused_frame)
667 return NULL;
669 return focused_frame->current_frame_host();
672 bool RenderWidgetHostViewAura::CanRendererHandleEvent(
673 const ui::MouseEvent* event,
674 bool mouse_locked,
675 bool selection_popup) {
676 #if defined(OS_WIN)
677 bool showing_context_menu = showing_context_menu_;
678 showing_context_menu_ = false;
679 #endif
681 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
682 return false;
684 if ((mouse_locked || selection_popup) &&
685 (event->type() == ui::ET_MOUSE_EXITED))
686 return false;
688 #if defined(OS_WIN)
689 // Don't forward the mouse leave message which is received when the context
690 // menu is displayed by the page. This confuses the page and causes state
691 // changes.
692 if (showing_context_menu) {
693 if (event->type() == ui::ET_MOUSE_EXITED)
694 return false;
696 // Renderer cannot handle WM_XBUTTON or NC events.
697 switch (event->native_event().message) {
698 case WM_XBUTTONDOWN:
699 case WM_XBUTTONUP:
700 case WM_XBUTTONDBLCLK:
701 case WM_NCMOUSELEAVE:
702 case WM_NCMOUSEMOVE:
703 case WM_NCLBUTTONDOWN:
704 case WM_NCLBUTTONUP:
705 case WM_NCLBUTTONDBLCLK:
706 case WM_NCRBUTTONDOWN:
707 case WM_NCRBUTTONUP:
708 case WM_NCRBUTTONDBLCLK:
709 case WM_NCMBUTTONDOWN:
710 case WM_NCMBUTTONUP:
711 case WM_NCMBUTTONDBLCLK:
712 case WM_NCXBUTTONDOWN:
713 case WM_NCXBUTTONUP:
714 case WM_NCXBUTTONDBLCLK:
715 return false;
716 default:
717 break;
719 #elif defined(USE_X11)
720 // Renderer only supports standard mouse buttons, so ignore programmable
721 // buttons.
722 switch (event->type()) {
723 case ui::ET_MOUSE_PRESSED:
724 case ui::ET_MOUSE_RELEASED: {
725 const int kAllowedButtons = ui::EF_LEFT_MOUSE_BUTTON |
726 ui::EF_MIDDLE_MOUSE_BUTTON |
727 ui::EF_RIGHT_MOUSE_BUTTON;
728 return (event->flags() & kAllowedButtons) != 0;
730 default:
731 break;
733 #endif
734 return true;
737 void RenderWidgetHostViewAura::MovePluginWindows(
738 const std::vector<WebPluginGeometry>& plugin_window_moves) {
739 #if defined(OS_WIN)
740 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
741 // over the browser UI.
742 if (!window_->GetRootWindow()) {
743 DCHECK(plugin_window_moves.empty());
744 return;
746 HWND parent = window_->GetHost()->GetAcceleratedWidget();
747 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
748 std::vector<WebPluginGeometry> moves = plugin_window_moves;
750 gfx::Rect view_port(view_bounds.size());
752 for (size_t i = 0; i < moves.size(); ++i) {
753 gfx::Rect clip(moves[i].clip_rect);
754 gfx::Vector2d view_port_offset(
755 moves[i].window_rect.OffsetFromOrigin());
756 clip.Offset(view_port_offset);
757 clip.Intersect(view_port);
758 clip.Offset(-view_port_offset);
759 moves[i].clip_rect = clip;
761 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
763 plugin_window_moves_[moves[i].window] = moves[i];
765 // constrained_rects_ are relative to the root window. We want to convert
766 // them to be relative to the plugin window.
767 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
768 gfx::Rect offset_cutout = constrained_rects_[j];
769 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
770 moves[i].cutout_rects.push_back(offset_cutout);
774 MovePluginWindowsHelper(parent, moves);
776 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
777 // |this|.
778 for (size_t i = 0; i < moves.size(); ++i) {
779 HWND window = moves[i].window;
780 if (GetParent(window) != parent) {
781 window = GetParent(window);
783 if (!GetProp(window, kWidgetOwnerProperty))
784 SetProp(window, kWidgetOwnerProperty, this);
786 #endif // defined(OS_WIN)
789 void RenderWidgetHostViewAura::Focus() {
790 // Make sure we have a FocusClient before attempting to Focus(). In some
791 // situations we may not yet be in a valid Window hierarchy (such as reloading
792 // after out of memory discarded the tab).
793 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
794 if (client)
795 window_->Focus();
798 void RenderWidgetHostViewAura::Blur() {
799 window_->Blur();
802 bool RenderWidgetHostViewAura::HasFocus() const {
803 return window_->HasFocus();
806 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
807 return delegated_frame_host_->CanCopyToBitmap();
810 bool RenderWidgetHostViewAura::IsShowing() {
811 return window_->IsVisible();
814 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
815 return window_->GetBoundsInScreen();
818 void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
819 RenderWidgetHostViewBase::SetBackgroundColor(color);
820 bool opaque = GetBackgroundOpaque();
821 host_->SetBackgroundOpaque(opaque);
822 window_->layer()->SetFillsBoundsOpaquely(opaque);
823 window_->layer()->SetColor(color);
826 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
827 gfx::Rect requested_rect(GetRequestedRendererSize());
828 requested_rect.Inset(insets_);
829 return requested_rect.size();
832 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
833 if (insets != insets_) {
834 insets_ = insets;
835 host_->WasResized();
839 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
840 current_cursor_ = cursor;
841 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
842 GetDisplayNearestWindow(window_);
843 current_cursor_.SetDisplayInfo(display);
844 UpdateCursorIfOverSelf();
847 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
848 is_loading_ = is_loading;
849 UpdateCursorIfOverSelf();
852 void RenderWidgetHostViewAura::TextInputTypeChanged(
853 ui::TextInputType type,
854 ui::TextInputMode input_mode,
855 bool can_compose_inline,
856 int flags) {
857 if (text_input_type_ != type ||
858 text_input_mode_ != input_mode ||
859 can_compose_inline_ != can_compose_inline ||
860 text_input_flags_ != flags) {
861 text_input_type_ = type;
862 text_input_mode_ = input_mode;
863 can_compose_inline_ = can_compose_inline;
864 text_input_flags_ = flags;
865 if (GetInputMethod())
866 GetInputMethod()->OnTextInputTypeChanged(this);
867 if (touch_editing_client_)
868 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
872 void RenderWidgetHostViewAura::OnTextInputStateChanged(
873 const ViewHostMsg_TextInputState_Params& params) {
874 text_input_flags_ = params.flags;
875 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
876 if (GetInputMethod())
877 GetInputMethod()->ShowImeIfNeeded();
881 void RenderWidgetHostViewAura::ImeCancelComposition() {
882 if (GetInputMethod())
883 GetInputMethod()->CancelComposition(this);
884 has_composition_text_ = false;
887 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
888 const gfx::Range& range,
889 const std::vector<gfx::Rect>& character_bounds) {
890 composition_character_bounds_ = character_bounds;
893 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
894 int error_code) {
895 UpdateCursorIfOverSelf();
896 Destroy();
899 void RenderWidgetHostViewAura::Destroy() {
900 // Beware, this function is not called on all destruction paths. It will
901 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
902 // destruction/cleanup code should happen there, not here.
903 in_shutdown_ = true;
904 delete window_;
907 void RenderWidgetHostViewAura::SetTooltipText(
908 const base::string16& tooltip_text) {
909 tooltip_ = tooltip_text;
910 aura::Window* root_window = window_->GetRootWindow();
911 aura::client::TooltipClient* tooltip_client =
912 aura::client::GetTooltipClient(root_window);
913 if (tooltip_client) {
914 tooltip_client->UpdateTooltip(window_);
915 // Content tooltips should be visible indefinitely.
916 tooltip_client->SetTooltipShownTimeout(window_, 0);
920 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
921 size_t offset,
922 const gfx::Range& range) {
923 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
925 #if defined(USE_X11) && !defined(OS_CHROMEOS)
926 if (text.empty() || range.is_empty())
927 return;
928 size_t pos = range.GetMin() - offset;
929 size_t n = range.length();
931 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
932 if (pos >= text.length()) {
933 NOTREACHED() << "The text can not cover range.";
934 return;
937 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
938 ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
939 clipboard_writer.WriteText(text.substr(pos, n));
940 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
943 gfx::Size RenderWidgetHostViewAura::GetRequestedRendererSize() const {
944 return delegated_frame_host_->GetRequestedRendererSize();
947 void RenderWidgetHostViewAura::SelectionBoundsChanged(
948 const ViewHostMsg_SelectionBounds_Params& params) {
949 ui::SelectionBound anchor_bound, focus_bound;
950 anchor_bound.SetEdge(params.anchor_rect.origin(),
951 params.anchor_rect.bottom_left());
952 focus_bound.SetEdge(params.focus_rect.origin(),
953 params.focus_rect.bottom_left());
955 if (params.anchor_rect == params.focus_rect) {
956 anchor_bound.set_type(ui::SelectionBound::CENTER);
957 focus_bound.set_type(ui::SelectionBound::CENTER);
958 } else {
959 // Whether text is LTR at the anchor handle.
960 bool anchor_LTR = params.anchor_dir == blink::WebTextDirectionLeftToRight;
961 // Whether text is LTR at the focus handle.
962 bool focus_LTR = params.focus_dir == blink::WebTextDirectionLeftToRight;
964 if ((params.is_anchor_first && anchor_LTR) ||
965 (!params.is_anchor_first && !anchor_LTR)) {
966 anchor_bound.set_type(ui::SelectionBound::LEFT);
967 } else {
968 anchor_bound.set_type(ui::SelectionBound::RIGHT);
970 if ((params.is_anchor_first && focus_LTR) ||
971 (!params.is_anchor_first && !focus_LTR)) {
972 focus_bound.set_type(ui::SelectionBound::RIGHT);
973 } else {
974 focus_bound.set_type(ui::SelectionBound::LEFT);
978 if (anchor_bound == selection_anchor_ && focus_bound == selection_focus_)
979 return;
981 selection_anchor_ = anchor_bound;
982 selection_focus_ = focus_bound;
983 if (GetInputMethod())
984 GetInputMethod()->OnCaretBoundsChanged(this);
986 if (touch_editing_client_) {
987 touch_editing_client_->OnSelectionOrCursorChanged(
988 anchor_bound, focus_bound);
992 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
993 const gfx::Rect& src_subrect,
994 const gfx::Size& dst_size,
995 ReadbackRequestCallback& callback,
996 const SkColorType color_type) {
997 delegated_frame_host_->CopyFromCompositingSurface(
998 src_subrect, dst_size, callback, color_type);
1001 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1002 const gfx::Rect& src_subrect,
1003 const scoped_refptr<media::VideoFrame>& target,
1004 const base::Callback<void(bool)>& callback) {
1005 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
1006 src_subrect, target, callback);
1009 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1010 return delegated_frame_host_->CanCopyToVideoFrame();
1013 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1014 return delegated_frame_host_->CanSubscribeFrame();
1017 void RenderWidgetHostViewAura::BeginFrameSubscription(
1018 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1019 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
1022 void RenderWidgetHostViewAura::EndFrameSubscription() {
1023 delegated_frame_host_->EndFrameSubscription();
1026 #if defined(OS_WIN)
1027 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1028 return (legacy_render_widget_host_HWND_ != NULL);
1031 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1032 const std::vector<gfx::Rect>& rects) {
1033 // Check this before setting constrained_rects_, so that next time they're set
1034 // and we have a root window we don't early return.
1035 if (!window_->GetHost())
1036 return;
1038 if (rects == constrained_rects_)
1039 return;
1041 constrained_rects_ = rects;
1043 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1044 CutoutRectsParams params;
1045 params.widget = this;
1046 params.cutout_rects = constrained_rects_;
1047 params.geometry = &plugin_window_moves_;
1048 LPARAM lparam = reinterpret_cast<LPARAM>(&params);
1049 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1052 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1053 // Clip the cursor if chrome is running on regular desktop.
1054 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1055 RECT window_rect =
1056 gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
1057 ::ClipCursor(&window_rect);
1061 void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
1062 legacy_render_widget_host_HWND_ = NULL;
1063 legacy_window_destroyed_ = true;
1065 #endif
1067 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1068 uint32 output_surface_id,
1069 scoped_ptr<cc::CompositorFrame> frame) {
1070 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1072 last_scroll_offset_ = frame->metadata.root_scroll_offset;
1073 if (frame->delegated_frame_data) {
1074 delegated_frame_host_->SwapDelegatedFrame(
1075 output_surface_id,
1076 frame->delegated_frame_data.Pass(),
1077 frame->metadata.device_scale_factor,
1078 frame->metadata.latency_info);
1079 return;
1082 if (frame->software_frame_data) {
1083 DLOG(ERROR) << "Unable to use software frame in aura";
1084 bad_message::ReceivedBadMessage(host_->GetProcess(),
1085 bad_message::RWHVA_SHARED_MEMORY);
1086 return;
1090 void RenderWidgetHostViewAura::DidStopFlinging() {
1091 if (touch_editing_client_)
1092 touch_editing_client_->DidStopFlinging();
1095 #if defined(OS_WIN)
1096 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1097 gfx::NativeViewAccessible accessible_parent) {
1100 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1101 const {
1102 if (legacy_render_widget_host_HWND_) {
1103 return reinterpret_cast<gfx::NativeViewId>(
1104 legacy_render_widget_host_HWND_->hwnd());
1106 return NULL;
1108 #endif
1110 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1111 const gfx::Size& desired_size) {
1112 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1113 // matter what is returned here as GetBackingStore is the only caller of this
1114 // method. TODO(jbates) implement this if other Aura code needs it.
1115 return false;
1118 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1119 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1122 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1123 aura::Window* top_level = window_->GetToplevelWindow();
1124 gfx::Rect bounds(top_level->GetBoundsInScreen());
1126 #if defined(OS_WIN)
1127 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1128 // remove the legacy hwnd, so a better fix will need to be decided when that
1129 // happens.
1130 if (UsesNativeWindowFrame()) {
1131 // aura::Window doesn't take into account non-client area of native windows
1132 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1133 aura::WindowTreeHost* host = top_level->GetHost();
1134 if (!host)
1135 return top_level->GetBoundsInScreen();
1136 RECT window_rect = {0};
1137 HWND hwnd = host->GetAcceleratedWidget();
1138 ::GetWindowRect(hwnd, &window_rect);
1139 bounds = gfx::Rect(window_rect);
1141 // Maximized windows are outdented from the work area by the frame thickness
1142 // even though this "frame" is not painted. This confuses code (and people)
1143 // that think of a maximized window as corresponding exactly to the work
1144 // area. Correct for this by subtracting the frame thickness back off.
1145 if (::IsZoomed(hwnd)) {
1146 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
1147 GetSystemMetrics(SM_CYSIZEFRAME));
1149 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1150 GetSystemMetrics(SM_CXPADDEDBORDER));
1154 bounds = gfx::win::ScreenToDIPRect(bounds);
1155 #endif
1157 return bounds;
1160 void RenderWidgetHostViewAura::WheelEventAck(
1161 const blink::WebMouseWheelEvent& event,
1162 InputEventAckState ack_result) {
1163 if (overscroll_controller_) {
1164 overscroll_controller_->ReceivedEventACK(
1165 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1169 void RenderWidgetHostViewAura::GestureEventAck(
1170 const blink::WebGestureEvent& event,
1171 InputEventAckState ack_result) {
1172 if (touch_editing_client_)
1173 touch_editing_client_->GestureEventAck(event.type);
1175 if (overscroll_controller_) {
1176 overscroll_controller_->ReceivedEventACK(
1177 event, (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result));
1181 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1182 const TouchEventWithLatencyInfo& touch,
1183 InputEventAckState ack_result) {
1184 ScopedVector<ui::TouchEvent> events;
1185 aura::WindowTreeHost* host = window_->GetHost();
1186 // |host| is NULL during tests.
1187 if (!host)
1188 return;
1190 ui::EventResult result = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
1191 ? ui::ER_HANDLED
1192 : ui::ER_UNHANDLED;
1194 blink::WebTouchPoint::State required_state;
1195 switch (touch.event.type) {
1196 case blink::WebInputEvent::TouchStart:
1197 required_state = blink::WebTouchPoint::StatePressed;
1198 break;
1199 case blink::WebInputEvent::TouchEnd:
1200 required_state = blink::WebTouchPoint::StateReleased;
1201 break;
1202 case blink::WebInputEvent::TouchMove:
1203 required_state = blink::WebTouchPoint::StateMoved;
1204 break;
1205 case blink::WebInputEvent::TouchCancel:
1206 required_state = blink::WebTouchPoint::StateCancelled;
1207 break;
1208 default:
1209 required_state = blink::WebTouchPoint::StateUndefined;
1210 NOTREACHED();
1211 break;
1214 // Only send acks for changed touches.
1215 for (size_t i = 0; i < touch.event.touchesLength; ++i) {
1216 if (touch.event.touches[i].state == required_state)
1217 host->dispatcher()->ProcessedTouchEvent(window_, result);
1221 scoped_ptr<SyntheticGestureTarget>
1222 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1223 return scoped_ptr<SyntheticGestureTarget>(
1224 new SyntheticGestureTargetAura(host_));
1227 InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
1228 const blink::WebInputEvent& input_event) {
1229 bool consumed = false;
1230 if (input_event.type == WebInputEvent::GestureFlingStart) {
1231 const WebGestureEvent& gesture_event =
1232 static_cast<const WebGestureEvent&>(input_event);
1233 // Zero-velocity touchpad flings are an Aura-specific signal that the
1234 // touchpad scroll has ended, and should not be forwarded to the renderer.
1235 if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
1236 !gesture_event.data.flingStart.velocityX &&
1237 !gesture_event.data.flingStart.velocityY) {
1238 consumed = true;
1242 if (overscroll_controller_)
1243 consumed |= overscroll_controller_->WillHandleEvent(input_event);
1245 return consumed && !WebTouchEvent::isTouchEventType(input_event.type)
1246 ? INPUT_EVENT_ACK_STATE_CONSUMED
1247 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
1250 BrowserAccessibilityManager*
1251 RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
1252 BrowserAccessibilityDelegate* delegate) {
1253 BrowserAccessibilityManager* manager = NULL;
1254 #if defined(OS_WIN)
1255 manager = new BrowserAccessibilityManagerWin(
1256 BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
1257 #else
1258 manager = BrowserAccessibilityManager::Create(
1259 BrowserAccessibilityManager::GetEmptyDocument(), delegate);
1260 #endif
1261 return manager;
1264 gfx::AcceleratedWidget
1265 RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
1266 #if defined(OS_WIN)
1267 if (legacy_render_widget_host_HWND_)
1268 return legacy_render_widget_host_HWND_->hwnd();
1269 #endif
1270 return gfx::kNullAcceleratedWidget;
1273 gfx::NativeViewAccessible
1274 RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
1275 #if defined(OS_WIN)
1276 if (legacy_render_widget_host_HWND_)
1277 return legacy_render_widget_host_HWND_->window_accessible();
1278 #endif
1279 return NULL;
1283 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1284 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1287 void RenderWidgetHostViewAura::ShowDisambiguationPopup(
1288 const gfx::Rect& rect_pixels,
1289 const SkBitmap& zoomed_bitmap) {
1290 RenderViewHostDelegate* delegate = NULL;
1291 if (host_->IsRenderView())
1292 delegate = RenderViewHost::From(host_)->GetDelegate();
1293 // Suppress the link disambiguation popup if the virtual keyboard is currently
1294 // requested, as it doesn't interact well with the keyboard.
1295 if (delegate && delegate->IsVirtualKeyboardRequested())
1296 return;
1298 // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
1299 // by scaling it by the inverse of the device scale factor.
1300 gfx::RectF screen_target_rect_f(rect_pixels);
1301 screen_target_rect_f.Scale(1.0f / current_device_scale_factor_);
1302 disambiguation_target_rect_ = gfx::ToEnclosingRect(screen_target_rect_f);
1304 float scale = static_cast<float>(zoomed_bitmap.width()) /
1305 static_cast<float>(rect_pixels.width());
1306 gfx::Size zoomed_size(gfx::ToCeiledSize(
1307 gfx::ScaleSize(disambiguation_target_rect_.size(), scale)));
1309 // Save of a copy of the |last_scroll_offset_| for comparison when the copy
1310 // callback fires, to ensure that we haven't scrolled.
1311 disambiguation_scroll_offset_ = last_scroll_offset_;
1313 CopyFromCompositingSurface(
1314 disambiguation_target_rect_,
1315 zoomed_size,
1316 base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
1317 weak_ptr_factory_.GetWeakPtr()),
1318 kN32_SkColorType);
1321 void RenderWidgetHostViewAura::DisambiguationPopupRendered(
1322 const SkBitmap& result,
1323 ReadbackResponse response) {
1324 if ((response != READBACK_SUCCESS) ||
1325 disambiguation_scroll_offset_ != last_scroll_offset_)
1326 return;
1328 // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
1329 // actually show the disambiguation popup.
1330 RenderViewHostDelegate* delegate = NULL;
1331 if (host_->IsRenderView())
1332 delegate = RenderViewHost::From(host_)->GetDelegate();
1333 RenderViewHostDelegateView* delegate_view = NULL;
1334 if (delegate) {
1335 delegate_view = delegate->GetDelegateView();
1336 if (delegate->IsVirtualKeyboardRequested())
1337 return;
1339 if (delegate_view) {
1340 delegate_view->ShowDisambiguationPopup(
1341 disambiguation_target_rect_,
1342 result,
1343 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture,
1344 weak_ptr_factory_.GetWeakPtr()),
1345 base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse,
1346 weak_ptr_factory_.GetWeakPtr()));
1350 void RenderWidgetHostViewAura::HideDisambiguationPopup() {
1351 RenderViewHostDelegate* delegate = NULL;
1352 if (host_->IsRenderView())
1353 delegate = RenderViewHost::From(host_)->GetDelegate();
1354 RenderViewHostDelegateView* delegate_view = NULL;
1355 if (delegate)
1356 delegate_view = delegate->GetDelegateView();
1357 if (delegate_view)
1358 delegate_view->HideDisambiguationPopup();
1361 void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
1362 ui::GestureEvent* event) {
1363 blink::WebGestureEvent web_gesture = content::MakeWebGestureEvent(*event);
1364 // If we fail to make a WebGestureEvent that is a Tap from the provided event,
1365 // don't forward it to Blink.
1366 if (web_gesture.type < blink::WebInputEvent::Type::GestureTap ||
1367 web_gesture.type > blink::WebInputEvent::Type::GestureTapCancel)
1368 return;
1370 host_->ForwardGestureEvent(web_gesture);
1373 void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
1374 ui::MouseEvent* event) {
1375 blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(*event);
1376 host_->ForwardMouseEvent(web_mouse);
1379 bool RenderWidgetHostViewAura::LockMouse() {
1380 aura::Window* root_window = window_->GetRootWindow();
1381 if (!root_window)
1382 return false;
1384 if (mouse_locked_)
1385 return true;
1387 mouse_locked_ = true;
1388 #if !defined(OS_WIN)
1389 window_->SetCapture();
1390 #else
1391 UpdateMouseLockRegion();
1392 #endif
1393 aura::client::CursorClient* cursor_client =
1394 aura::client::GetCursorClient(root_window);
1395 if (cursor_client) {
1396 cursor_client->HideCursor();
1397 cursor_client->LockCursor();
1400 if (ShouldMoveToCenter()) {
1401 synthetic_move_sent_ = true;
1402 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1404 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1405 return true;
1408 void RenderWidgetHostViewAura::UnlockMouse() {
1409 tooltip_disabler_.reset();
1411 aura::Window* root_window = window_->GetRootWindow();
1412 if (!mouse_locked_ || !root_window)
1413 return;
1415 mouse_locked_ = false;
1417 #if !defined(OS_WIN)
1418 window_->ReleaseCapture();
1419 #else
1420 ::ClipCursor(NULL);
1421 #endif
1422 window_->MoveCursorTo(unlocked_mouse_position_);
1423 aura::client::CursorClient* cursor_client =
1424 aura::client::GetCursorClient(root_window);
1425 if (cursor_client) {
1426 cursor_client->UnlockCursor();
1427 cursor_client->ShowCursor();
1430 host_->LostMouseLock();
1433 ////////////////////////////////////////////////////////////////////////////////
1434 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1435 void RenderWidgetHostViewAura::SetCompositionText(
1436 const ui::CompositionText& composition) {
1437 if (!host_)
1438 return;
1440 // TODO(suzhe): convert both renderer_host and renderer to use
1441 // ui::CompositionText.
1442 std::vector<blink::WebCompositionUnderline> underlines;
1443 underlines.reserve(composition.underlines.size());
1444 for (std::vector<ui::CompositionUnderline>::const_iterator it =
1445 composition.underlines.begin();
1446 it != composition.underlines.end(); ++it) {
1447 underlines.push_back(
1448 blink::WebCompositionUnderline(static_cast<unsigned>(it->start_offset),
1449 static_cast<unsigned>(it->end_offset),
1450 it->color,
1451 it->thick,
1452 it->background_color));
1455 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1456 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1457 host_->ImeSetComposition(composition.text, underlines,
1458 composition.selection.end(),
1459 composition.selection.end());
1461 has_composition_text_ = !composition.text.empty();
1464 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1465 if (host_ && has_composition_text_) {
1466 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1467 false);
1469 has_composition_text_ = false;
1472 void RenderWidgetHostViewAura::ClearCompositionText() {
1473 if (host_ && has_composition_text_)
1474 host_->ImeCancelComposition();
1475 has_composition_text_ = false;
1478 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1479 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1480 if (host_)
1481 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1482 has_composition_text_ = false;
1485 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
1486 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1487 popup_child_host_view_->InsertChar(ch, flags);
1488 return;
1491 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1492 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
1493 double now = ui::EventTimeForNow().InSecondsF();
1494 // Send a blink::WebInputEvent::Char event to |host_|.
1495 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
1496 true /* is_char */,
1498 flags,
1499 now);
1500 ForwardKeyboardEvent(webkit_event);
1504 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
1505 return window_;
1508 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1509 return text_input_type_;
1512 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1513 return text_input_mode_;
1516 int RenderWidgetHostViewAura::GetTextInputFlags() const {
1517 return text_input_flags_;
1520 bool RenderWidgetHostViewAura::CanComposeInline() const {
1521 return can_compose_inline_;
1524 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
1525 const gfx::Rect& rect) const {
1526 gfx::Point origin = rect.origin();
1527 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1529 aura::Window* root_window = window_->GetRootWindow();
1530 if (!root_window)
1531 return rect;
1532 aura::client::ScreenPositionClient* screen_position_client =
1533 aura::client::GetScreenPositionClient(root_window);
1534 if (!screen_position_client)
1535 return rect;
1536 screen_position_client->ConvertPointToScreen(window_, &origin);
1537 screen_position_client->ConvertPointToScreen(window_, &end);
1538 return gfx::Rect(origin.x(),
1539 origin.y(),
1540 end.x() - origin.x(),
1541 end.y() - origin.y());
1544 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
1545 const gfx::Rect& rect) const {
1546 gfx::Point origin = rect.origin();
1547 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1549 aura::Window* root_window = window_->GetRootWindow();
1550 if (root_window) {
1551 aura::client::ScreenPositionClient* screen_position_client =
1552 aura::client::GetScreenPositionClient(root_window);
1553 screen_position_client->ConvertPointFromScreen(window_, &origin);
1554 screen_position_client->ConvertPointFromScreen(window_, &end);
1555 return gfx::Rect(origin.x(),
1556 origin.y(),
1557 end.x() - origin.x(),
1558 end.y() - origin.y());
1561 return rect;
1564 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1565 gfx::Rect rect =
1566 ui::RectBetweenSelectionBounds(selection_anchor_, selection_focus_);
1567 return ConvertRectToScreen(rect);
1570 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1571 uint32 index,
1572 gfx::Rect* rect) const {
1573 DCHECK(rect);
1574 if (index >= composition_character_bounds_.size())
1575 return false;
1576 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1577 return true;
1580 bool RenderWidgetHostViewAura::HasCompositionText() const {
1581 return has_composition_text_;
1584 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
1585 range->set_start(selection_text_offset_);
1586 range->set_end(selection_text_offset_ + selection_text_.length());
1587 return true;
1590 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1591 gfx::Range* range) const {
1592 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1593 NOTIMPLEMENTED();
1594 return false;
1597 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1598 range->set_start(selection_range_.start());
1599 range->set_end(selection_range_.end());
1600 return true;
1603 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1604 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1605 NOTIMPLEMENTED();
1606 return false;
1609 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1610 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1611 NOTIMPLEMENTED();
1612 return false;
1615 bool RenderWidgetHostViewAura::GetTextFromRange(
1616 const gfx::Range& range,
1617 base::string16* text) const {
1618 gfx::Range selection_text_range(selection_text_offset_,
1619 selection_text_offset_ + selection_text_.length());
1621 if (!selection_text_range.Contains(range)) {
1622 text->clear();
1623 return false;
1625 if (selection_text_range.EqualsIgnoringDirection(range)) {
1626 // Avoid calling substr whose performance is low.
1627 *text = selection_text_;
1628 } else {
1629 *text = selection_text_.substr(
1630 range.GetMin() - selection_text_offset_,
1631 range.length());
1633 return true;
1636 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1637 if (!host_)
1638 return;
1640 if (GetInputMethod())
1641 host_->SetInputMethodActive(GetInputMethod()->IsActive());
1643 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1644 // TextEvent.
1647 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1648 base::i18n::TextDirection direction) {
1649 if (!host_)
1650 return false;
1651 host_->UpdateTextDirection(
1652 direction == base::i18n::RIGHT_TO_LEFT ?
1653 blink::WebTextDirectionRightToLeft :
1654 blink::WebTextDirectionLeftToRight);
1655 host_->NotifyTextDirection();
1656 return true;
1659 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1660 size_t before, size_t after) {
1661 RenderFrameHostImpl* rfh = GetFocusedFrame();
1662 if (rfh)
1663 rfh->ExtendSelectionAndDelete(before, after);
1666 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1667 gfx::Rect intersected_rect(
1668 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1670 if (intersected_rect.IsEmpty())
1671 return;
1673 host_->ScrollFocusedEditableNodeIntoRect(
1674 ConvertRectFromScreen(intersected_rect));
1677 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
1678 host_->CandidateWindowShown();
1681 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
1682 host_->CandidateWindowUpdated();
1685 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
1686 host_->CandidateWindowHidden();
1689 bool RenderWidgetHostViewAura::IsEditCommandEnabled(int command_id) {
1690 return false;
1693 void RenderWidgetHostViewAura::SetEditCommandForNextKeyEvent(int command_id) {
1696 ////////////////////////////////////////////////////////////////////////////////
1697 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1699 void RenderWidgetHostViewAura::OnDisplayAdded(
1700 const gfx::Display& new_display) {
1703 void RenderWidgetHostViewAura::OnDisplayRemoved(
1704 const gfx::Display& old_display) {
1707 void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
1708 const gfx::Display& display, uint32_t metrics) {
1709 // The screen info should be updated regardless of the metric change.
1710 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
1711 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
1712 UpdateScreenInfo(window_);
1713 current_cursor_.SetDisplayInfo(display);
1714 UpdateCursorIfOverSelf();
1718 ////////////////////////////////////////////////////////////////////////////////
1719 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1721 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1722 return gfx::Size();
1725 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
1726 return gfx::Size();
1729 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1730 const gfx::Rect& new_bounds) {
1731 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
1732 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1733 // WebContentsViewAura since changes to the Window's bounds need to be
1734 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1735 // SetBounds() itself. No matter how we got here, any redundant calls are
1736 // harmless.
1737 SetSize(new_bounds.size());
1739 if (GetInputMethod())
1740 GetInputMethod()->OnCaretBoundsChanged(this);
1743 ui::TextInputClient* RenderWidgetHostViewAura::GetFocusedTextInputClient() {
1744 return GetTextInputClient();
1747 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1748 if (mouse_locked_)
1749 return ui::kCursorNone;
1750 return current_cursor_.GetNativeCursor();
1753 int RenderWidgetHostViewAura::GetNonClientComponent(
1754 const gfx::Point& point) const {
1755 return HTCLIENT;
1758 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1759 aura::Window* child,
1760 const gfx::Point& location) {
1761 return true;
1764 bool RenderWidgetHostViewAura::CanFocus() {
1765 return popup_type_ == blink::WebPopupTypeNone;
1768 void RenderWidgetHostViewAura::OnCaptureLost() {
1769 host_->LostCapture();
1770 if (touch_editing_client_)
1771 touch_editing_client_->EndTouchEditing(false);
1774 void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
1775 NOTREACHED();
1778 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1779 float device_scale_factor) {
1780 if (!host_ || !window_->GetRootWindow())
1781 return;
1783 UpdateScreenInfo(window_);
1785 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1786 GetDisplayNearestWindow(window_);
1787 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
1788 current_cursor_.SetDisplayInfo(display);
1789 SnapToPhysicalPixelBoundary();
1792 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
1793 #if defined(OS_WIN)
1794 HWND parent = NULL;
1795 // If the tab was hidden and it's closed, host_->is_hidden would have been
1796 // reset to false in RenderWidgetHostImpl::RendererExited.
1797 if (!window_->GetRootWindow() || host_->is_hidden()) {
1798 parent = ui::GetHiddenWindow();
1799 } else {
1800 parent = window_->GetHost()->GetAcceleratedWidget();
1802 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1803 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
1805 // The LegacyRenderWidgetHostHWND instance is destroyed when its window is
1806 // destroyed. Normally we control when that happens via the Destroy call
1807 // in the dtor. However there may be cases where the window is destroyed
1808 // by Windows, i.e. the parent window is destroyed before the
1809 // RenderWidgetHostViewAura instance goes away etc. To avoid that we
1810 // destroy the LegacyRenderWidgetHostHWND instance here.
1811 if (legacy_render_widget_host_HWND_) {
1812 legacy_render_widget_host_HWND_->set_host(NULL);
1813 legacy_render_widget_host_HWND_->Destroy();
1814 // The Destroy call above will delete the LegacyRenderWidgetHostHWND
1815 // instance.
1816 legacy_render_widget_host_HWND_ = NULL;
1818 #endif
1820 // Make sure that the input method no longer references to this object before
1821 // this object is removed from the root window (i.e. this object loses access
1822 // to the input method).
1823 ui::InputMethod* input_method = GetInputMethod();
1824 if (input_method)
1825 input_method->DetachTextInputClient(this);
1827 if (overscroll_controller_)
1828 overscroll_controller_->Reset();
1831 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1832 // Ask the RWH to drop reference to us.
1833 if (!is_guest_view_hack_)
1834 host_->ViewDestroyed();
1836 delete this;
1839 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1842 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1843 return false;
1846 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1849 ////////////////////////////////////////////////////////////////////////////////
1850 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1852 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1853 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1854 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1855 return;
1857 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1858 popup_child_host_view_->OnKeyEvent(event);
1859 if (event->handled())
1860 return;
1863 // We need to handle the Escape key for Pepper Flash.
1864 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
1865 // Focus the window we were created from.
1866 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
1867 aura::Window* host = *(host_tracker_->windows().begin());
1868 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
1869 if (client) {
1870 // Calling host->Focus() may delete |this|. We create a local observer
1871 // for that. In that case we exit without further access to any members.
1872 aura::WindowTracker tracker;
1873 aura::Window* window = window_;
1874 tracker.Add(window);
1875 host->Focus();
1876 if (!tracker.Contains(window)) {
1877 event->SetHandled();
1878 return;
1882 Shutdown();
1883 } else {
1884 if (event->key_code() == ui::VKEY_RETURN) {
1885 // Do not forward return key release events if no press event was handled.
1886 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
1887 return;
1888 // Accept return key character events between press and release events.
1889 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
1892 // We don't have to communicate with an input method here.
1893 NativeWebKeyboardEvent webkit_event(*event);
1894 ForwardKeyboardEvent(webkit_event);
1896 event->SetHandled();
1899 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
1900 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
1902 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1903 return;
1905 if (mouse_locked_) {
1906 aura::client::CursorClient* cursor_client =
1907 aura::client::GetCursorClient(window_->GetRootWindow());
1908 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
1910 if (event->type() == ui::ET_MOUSEWHEEL) {
1911 blink::WebMouseWheelEvent mouse_wheel_event =
1912 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
1913 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
1914 host_->ForwardWheelEvent(mouse_wheel_event);
1915 return;
1918 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
1920 // If we receive non client mouse messages while we are in the locked state
1921 // it probably means that the mouse left the borders of our window and
1922 // needs to be moved back to the center.
1923 if (event->flags() & ui::EF_IS_NON_CLIENT) {
1924 synthetic_move_sent_ = true;
1925 window_->MoveCursorTo(center);
1926 return;
1929 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
1931 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
1932 event->type() == ui::ET_MOUSE_DRAGGED) &&
1933 mouse_event.x == center.x() && mouse_event.y == center.y();
1935 // For fractional scale factors, the conversion from pixels to dip and
1936 // vice versa could result in off by 1 or 2 errors which hurts us because
1937 // we want to avoid sending the artificial move to center event to the
1938 // renderer. Sending the move to center to the renderer cause the cursor
1939 // to bounce around the center of the screen leading to the lock operation
1940 // not working correctly.
1941 // Workaround is to treat a mouse move or drag event off by at most 2 px
1942 // from the center as a move to center event.
1943 if (synthetic_move_sent_ &&
1944 IsFractionalScaleFactor(current_device_scale_factor_)) {
1945 if (event->type() == ui::ET_MOUSE_MOVED ||
1946 event->type() == ui::ET_MOUSE_DRAGGED) {
1947 if ((abs(mouse_event.x - center.x()) <= 2) &&
1948 (abs(mouse_event.y - center.y()) <= 2)) {
1949 is_move_to_center_event = true;
1954 ModifyEventMovementAndCoords(&mouse_event);
1956 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
1957 if (should_not_forward) {
1958 synthetic_move_sent_ = false;
1959 } else {
1960 // Check if the mouse has reached the border and needs to be centered.
1961 if (ShouldMoveToCenter()) {
1962 synthetic_move_sent_ = true;
1963 window_->MoveCursorTo(center);
1965 bool is_selection_popup = popup_child_host_view_ &&
1966 popup_child_host_view_->NeedsInputGrab();
1967 // Forward event to renderer.
1968 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
1969 !(event->flags() & ui::EF_FROM_TOUCH)) {
1970 host_->ForwardMouseEvent(mouse_event);
1971 // Ensure that we get keyboard focus on mouse down as a plugin window
1972 // may have grabbed keyboard focus.
1973 if (event->type() == ui::ET_MOUSE_PRESSED)
1974 SetKeyboardFocus();
1977 return;
1980 // As the overscroll is handled during scroll events from the trackpad, the
1981 // RWHVA window is transformed by the overscroll controller. This transform
1982 // triggers a synthetic mouse-move event to be generated (by the aura
1983 // RootWindow). But this event interferes with the overscroll gesture. So,
1984 // ignore such synthetic mouse-move events if an overscroll gesture is in
1985 // progress.
1986 if (overscroll_controller_ &&
1987 overscroll_controller_->overscroll_mode() != OVERSCROLL_NONE &&
1988 event->flags() & ui::EF_IS_SYNTHESIZED &&
1989 (event->type() == ui::ET_MOUSE_ENTERED ||
1990 event->type() == ui::ET_MOUSE_EXITED ||
1991 event->type() == ui::ET_MOUSE_MOVED)) {
1992 event->StopPropagation();
1993 return;
1996 if (event->type() == ui::ET_MOUSEWHEEL) {
1997 #if defined(OS_WIN)
1998 // We get mouse wheel/scroll messages even if we are not in the foreground.
1999 // So here we check if we have any owned popup windows in the foreground and
2000 // dismiss them.
2001 aura::WindowTreeHost* host = window_->GetHost();
2002 if (host) {
2003 HWND parent = host->GetAcceleratedWidget();
2004 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
2005 EnumThreadWindows(GetCurrentThreadId(),
2006 DismissOwnedPopups,
2007 reinterpret_cast<LPARAM>(toplevel_hwnd));
2009 #endif
2010 // The Disambiguation popup does not parent itself from this window, so we
2011 // manually dismiss it.
2012 HideDisambiguationPopup();
2014 blink::WebMouseWheelEvent mouse_wheel_event =
2015 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event));
2016 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
2017 host_->ForwardWheelEvent(mouse_wheel_event);
2018 } else {
2019 bool is_selection_popup = popup_child_host_view_ &&
2020 popup_child_host_view_->NeedsInputGrab();
2021 if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
2022 !(event->flags() & ui::EF_FROM_TOUCH)) {
2023 // Confirm existing composition text on mouse press, to make sure
2024 // the input caret won't be moved with an ongoing composition text.
2025 if (event->type() == ui::ET_MOUSE_PRESSED)
2026 FinishImeCompositionSession();
2028 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(*event);
2029 ModifyEventMovementAndCoords(&mouse_event);
2030 host_->ForwardMouseEvent(mouse_event);
2031 // Ensure that we get keyboard focus on mouse down as a plugin window may
2032 // have grabbed keyboard focus.
2033 if (event->type() == ui::ET_MOUSE_PRESSED)
2034 SetKeyboardFocus();
2038 switch (event->type()) {
2039 case ui::ET_MOUSE_PRESSED:
2040 window_->SetCapture();
2041 break;
2042 case ui::ET_MOUSE_RELEASED:
2043 if (!NeedsMouseCapture())
2044 window_->ReleaseCapture();
2045 break;
2046 default:
2047 break;
2050 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
2051 // note that it might be something other than a WebContentsViewAura instance.
2052 // TODO(pkotwicz): Find a better way of doing this.
2053 // In fullscreen mode which is typically used by flash, don't forward
2054 // the mouse events to the parent. The renderer and the plugin process
2055 // handle these events.
2056 if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
2057 !(event->flags() & ui::EF_FROM_TOUCH)) {
2058 event->ConvertLocationToTarget(window_, window_->parent());
2059 window_->parent()->delegate()->OnMouseEvent(event);
2062 if (!IsXButtonUpEvent(event))
2063 event->SetHandled();
2066 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
2067 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
2068 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2069 return;
2071 if (event->type() == ui::ET_SCROLL) {
2072 #if !defined(OS_WIN)
2073 // TODO(ananta)
2074 // Investigate if this is true for Windows 8 Metro ASH as well.
2075 if (event->finger_count() != 2)
2076 return;
2077 #endif
2078 blink::WebGestureEvent gesture_event =
2079 MakeWebGestureEventFlingCancel();
2080 host_->ForwardGestureEvent(gesture_event);
2081 blink::WebMouseWheelEvent mouse_wheel_event =
2082 MakeWebMouseWheelEvent(*event);
2083 host_->ForwardWheelEvent(mouse_wheel_event);
2084 RecordAction(base::UserMetricsAction("TrackpadScroll"));
2085 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
2086 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
2087 blink::WebGestureEvent gesture_event = MakeWebGestureEvent(*event);
2088 host_->ForwardGestureEvent(gesture_event);
2089 if (event->type() == ui::ET_SCROLL_FLING_START)
2090 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
2093 event->SetHandled();
2096 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
2097 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
2098 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2099 return;
2101 // Update the touch event first.
2102 if (!pointer_state_.OnTouch(*event)) {
2103 event->StopPropagation();
2104 return;
2107 blink::WebTouchEvent touch_event = ui::CreateWebTouchEventFromMotionEvent(
2108 pointer_state_, event->may_cause_scrolling());
2109 pointer_state_.CleanupRemovedTouchPoints(*event);
2111 // It is important to always mark events as being handled asynchronously when
2112 // they are forwarded. This ensures that the current event does not get
2113 // processed by the gesture recognizer before events currently awaiting
2114 // dispatch in the touch queue.
2115 event->DisableSynchronousHandling();
2116 host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency());
2119 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
2120 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
2121 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
2122 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
2123 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
2124 event->SetHandled();
2125 return;
2128 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
2129 return;
2131 // Confirm existing composition text on TAP gesture, to make sure the input
2132 // caret won't be moved with an ongoing composition text.
2133 if (event->type() == ui::ET_GESTURE_TAP)
2134 FinishImeCompositionSession();
2136 blink::WebGestureEvent gesture = MakeWebGestureEvent(*event);
2137 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
2138 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
2139 // event to stop any in-progress flings.
2140 blink::WebGestureEvent fling_cancel = gesture;
2141 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
2142 fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
2143 host_->ForwardGestureEvent(fling_cancel);
2146 if (gesture.type != blink::WebInputEvent::Undefined) {
2147 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
2149 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
2150 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
2151 event->type() == ui::ET_GESTURE_SCROLL_END) {
2152 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
2153 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
2154 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
2158 // If a gesture is not processed by the webpage, then WebKit processes it
2159 // (e.g. generates synthetic mouse events).
2160 event->SetHandled();
2163 ////////////////////////////////////////////////////////////////////////////////
2164 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
2166 bool RenderWidgetHostViewAura::ShouldActivate() const {
2167 aura::WindowTreeHost* host = window_->GetHost();
2168 if (!host)
2169 return true;
2170 const ui::Event* event = host->dispatcher()->current_event();
2171 if (!event)
2172 return true;
2173 return is_fullscreen_;
2176 ////////////////////////////////////////////////////////////////////////////////
2177 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
2179 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2180 NotifyRendererOfCursorVisibilityState(is_visible);
2183 ////////////////////////////////////////////////////////////////////////////////
2184 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2186 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2187 aura::Window* lost_focus) {
2188 DCHECK(window_ == gained_focus || window_ == lost_focus);
2189 if (window_ == gained_focus) {
2190 // We need to honor input bypass if the associated tab is does not want
2191 // input. This gives the current focused window a chance to be the text
2192 // input client and handle events.
2193 if (host_->ignore_input_events())
2194 return;
2196 host_->GotFocus();
2197 host_->SetActive(true);
2199 ui::InputMethod* input_method = GetInputMethod();
2200 if (input_method) {
2201 // Ask the system-wide IME to send all TextInputClient messages to |this|
2202 // object.
2203 input_method->SetFocusedTextInputClient(this);
2204 host_->SetInputMethodActive(input_method->IsActive());
2206 // Often the application can set focus to the view in response to a key
2207 // down. However the following char event shouldn't be sent to the web
2208 // page.
2209 host_->SuppressNextCharEvents();
2210 } else {
2211 host_->SetInputMethodActive(false);
2214 BrowserAccessibilityManager* manager =
2215 host_->GetRootBrowserAccessibilityManager();
2216 if (manager)
2217 manager->OnWindowFocused();
2218 } else if (window_ == lost_focus) {
2219 host_->SetActive(false);
2220 host_->Blur();
2222 DetachFromInputMethod();
2223 host_->SetInputMethodActive(false);
2225 if (touch_editing_client_)
2226 touch_editing_client_->EndTouchEditing(false);
2228 if (overscroll_controller_)
2229 overscroll_controller_->Cancel();
2231 BrowserAccessibilityManager* manager =
2232 host_->GetRootBrowserAccessibilityManager();
2233 if (manager)
2234 manager->OnWindowBlurred();
2236 // If we lose the focus while fullscreen, close the window; Pepper Flash
2237 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2238 // window if we lose the focus to a window on another display.
2239 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2240 bool focusing_other_display =
2241 gained_focus && screen->GetNumDisplays() > 1 &&
2242 (screen->GetDisplayNearestWindow(window_).id() !=
2243 screen->GetDisplayNearestWindow(gained_focus).id());
2244 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
2245 #if defined(OS_WIN)
2246 // On Windows, if we are switching to a non Aura Window on a different
2247 // screen we should not close the fullscreen window.
2248 if (!gained_focus) {
2249 POINT point = {0};
2250 ::GetCursorPos(&point);
2251 if (screen->GetDisplayNearestWindow(window_).id() !=
2252 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2253 return;
2255 #endif
2256 Shutdown();
2257 return;
2260 // Close the child popup window if we lose focus (e.g. due to a JS alert or
2261 // system modal dialog). This is particularly important if
2262 // |popup_child_host_view_| has mouse capture.
2263 if (popup_child_host_view_)
2264 popup_child_host_view_->Shutdown();
2268 ////////////////////////////////////////////////////////////////////////////////
2269 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2271 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
2272 const gfx::Point& new_origin) {
2273 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2274 "new_origin", new_origin.ToString());
2276 UpdateScreenInfo(window_);
2279 ////////////////////////////////////////////////////////////////////////////////
2280 // RenderWidgetHostViewAura, private:
2282 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2283 if (touch_editing_client_)
2284 touch_editing_client_->OnViewDestroyed();
2286 delegated_frame_host_.reset();
2287 window_observer_.reset();
2288 if (window_->GetHost())
2289 window_->GetHost()->RemoveObserver(this);
2290 UnlockMouse();
2291 if (popup_parent_host_view_) {
2292 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
2293 popup_parent_host_view_->popup_child_host_view_ == this);
2294 popup_parent_host_view_->popup_child_host_view_ = NULL;
2296 if (popup_child_host_view_) {
2297 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
2298 popup_child_host_view_->popup_parent_host_view_ == this);
2299 popup_child_host_view_->popup_parent_host_view_ = NULL;
2301 event_filter_for_popup_exit_.reset();
2302 aura::client::SetTooltipText(window_, NULL);
2303 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
2305 // This call is usually no-op since |this| object is already removed from the
2306 // Aura root window and we don't have a way to get an input method object
2307 // associated with the window, but just in case.
2308 DetachFromInputMethod();
2310 #if defined(OS_WIN)
2311 // The LegacyRenderWidgetHostHWND window should have been destroyed in
2312 // RenderWidgetHostViewAura::OnWindowDestroying and the pointer should
2313 // be set to NULL.
2314 DCHECK(!legacy_render_widget_host_HWND_);
2315 #endif
2318 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2319 const gfx::Point screen_point =
2320 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2321 aura::Window* root_window = window_->GetRootWindow();
2322 if (!root_window)
2323 return;
2325 gfx::Point root_window_point = screen_point;
2326 aura::client::ScreenPositionClient* screen_position_client =
2327 aura::client::GetScreenPositionClient(root_window);
2328 if (screen_position_client) {
2329 screen_position_client->ConvertPointFromScreen(
2330 root_window, &root_window_point);
2333 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
2334 return;
2336 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
2337 // Do not show loading cursor when the cursor is currently hidden.
2338 if (is_loading_ && cursor != ui::kCursorNone)
2339 cursor = ui::kCursorPointer;
2341 aura::client::CursorClient* cursor_client =
2342 aura::client::GetCursorClient(root_window);
2343 if (cursor_client) {
2344 cursor_client->SetCursor(cursor);
2348 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2349 aura::Window* root_window = window_->GetRootWindow();
2350 if (!root_window)
2351 return NULL;
2352 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
2355 void RenderWidgetHostViewAura::Shutdown() {
2356 if (!in_shutdown_) {
2357 in_shutdown_ = true;
2358 host_->Shutdown();
2362 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2363 return popup_type_ == blink::WebPopupTypeSelect ||
2364 popup_type_ == blink::WebPopupTypePage;
2367 bool RenderWidgetHostViewAura::NeedsMouseCapture() {
2368 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2369 return NeedsInputGrab();
2370 #endif
2371 return false;
2374 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2375 if (!has_composition_text_)
2376 return;
2377 if (host_) {
2378 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2379 false);
2381 ImeCancelComposition();
2384 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2385 blink::WebMouseEvent* event) {
2386 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2387 // reset any global_mouse_position set previously.
2388 if (event->type == blink::WebInputEvent::MouseEnter ||
2389 event->type == blink::WebInputEvent::MouseLeave)
2390 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2392 // Movement is computed by taking the difference of the new cursor position
2393 // and the previous. Under mouse lock the cursor will be warped back to the
2394 // center so that we are not limited by clipping boundaries.
2395 // We do not measure movement as the delta from cursor to center because
2396 // we may receive more mouse movement events before our warp has taken
2397 // effect.
2398 event->movementX = event->globalX - global_mouse_position_.x();
2399 event->movementY = event->globalY - global_mouse_position_.y();
2401 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2403 // Under mouse lock, coordinates of mouse are locked to what they were when
2404 // mouse lock was entered.
2405 if (mouse_locked_) {
2406 event->x = unlocked_mouse_position_.x();
2407 event->y = unlocked_mouse_position_.y();
2408 event->windowX = unlocked_mouse_position_.x();
2409 event->windowY = unlocked_mouse_position_.y();
2410 event->globalX = unlocked_global_mouse_position_.x();
2411 event->globalY = unlocked_global_mouse_position_.y();
2412 } else {
2413 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
2414 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2418 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2419 bool is_visible) {
2420 if (host_->is_hidden() ||
2421 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2422 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2423 return;
2425 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2426 host_->SendCursorVisibilityState(is_visible);
2429 void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
2430 if (!enabled)
2431 overscroll_controller_.reset();
2432 else if (!overscroll_controller_)
2433 overscroll_controller_.reset(new OverscrollController());
2436 void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
2437 // The top left corner of our view in window coordinates might not land on a
2438 // device pixel boundary if we have a non-integer device scale. In that case,
2439 // to avoid the web contents area looking blurry we translate the web contents
2440 // in the +x, +y direction to land on the nearest pixel boundary. This may
2441 // cause the bottom and right edges to be clipped slightly, but that's ok.
2442 aura::Window* snapped = NULL;
2443 // On desktop, use the root window. On alternative environment (ash),
2444 // use the toplevel window which must be already snapped.
2445 if (gfx::Screen::GetScreenFor(window_) !=
2446 gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
2447 snapped = window_->GetRootWindow();
2448 } else {
2449 snapped = window_->GetToplevelWindow();
2451 if (snapped && snapped != window_)
2452 ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
2454 has_snapped_to_boundary_ = true;
2457 void RenderWidgetHostViewAura::OnShowContextMenu() {
2458 #if defined(OS_WIN)
2459 showing_context_menu_ = true;
2460 #endif
2463 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
2464 if (HasDisplayPropertyChanged(window_))
2465 host_->InvalidateScreenInfo();
2467 SnapToPhysicalPixelBoundary();
2468 // Don't recursively call SetBounds if this bounds update is the result of
2469 // a Window::SetBoundsInternal call.
2470 if (!in_bounds_changed_)
2471 window_->SetBounds(rect);
2472 host_->WasResized();
2473 delegated_frame_host_->WasResized();
2474 if (touch_editing_client_) {
2475 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_,
2476 selection_focus_);
2478 #if defined(OS_WIN)
2479 // Create the legacy dummy window which corresponds to the bounds of the
2480 // webcontents. This will be passed as the container window for windowless
2481 // plugins.
2482 // Plugins like Flash assume the container window which is returned via the
2483 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
2484 // This is not true in Aura where we have only HWND which is the main Aura
2485 // window. If we return this window to plugins like Flash then it causes the
2486 // coordinate translations done by these plugins to break.
2487 // Additonally the legacy dummy window is needed for accessibility and for
2488 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
2489 if (!legacy_window_destroyed_ && GetNativeViewId()) {
2490 if (!legacy_render_widget_host_HWND_) {
2491 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
2492 reinterpret_cast<HWND>(GetNativeViewId()));
2494 if (legacy_render_widget_host_HWND_) {
2495 legacy_render_widget_host_HWND_->set_host(this);
2496 legacy_render_widget_host_HWND_->SetBounds(
2497 window_->GetBoundsInRootWindow());
2498 // There are cases where the parent window is created, made visible and
2499 // the associated RenderWidget is also visible before the
2500 // LegacyRenderWidgetHostHWND instace is created. Ensure that it is shown
2501 // here.
2502 if (!host_->is_hidden())
2503 legacy_render_widget_host_HWND_->Show();
2507 if (mouse_locked_)
2508 UpdateMouseLockRegion();
2509 #endif
2512 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2513 const gfx::Rect& rect,
2514 const gfx::Rect& clip) {
2515 if (!clip.IsEmpty()) {
2516 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
2517 if (!to_paint.IsEmpty())
2518 window_->SchedulePaintInRect(to_paint);
2519 } else {
2520 window_->SchedulePaintInRect(rect);
2524 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2525 gfx::Rect rect = window_->bounds();
2526 rect = ConvertRectToScreen(rect);
2527 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
2528 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
2530 return global_mouse_position_.x() < rect.x() + border_x ||
2531 global_mouse_position_.x() > rect.right() - border_x ||
2532 global_mouse_position_.y() < rect.y() + border_y ||
2533 global_mouse_position_.y() > rect.bottom() - border_y;
2536 void RenderWidgetHostViewAura::AddedToRootWindow() {
2537 window_->GetHost()->AddObserver(this);
2538 UpdateScreenInfo(window_);
2540 aura::client::CursorClient* cursor_client =
2541 aura::client::GetCursorClient(window_->GetRootWindow());
2542 if (cursor_client) {
2543 cursor_client->AddObserver(this);
2544 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
2546 if (HasFocus()) {
2547 ui::InputMethod* input_method = GetInputMethod();
2548 if (input_method)
2549 input_method->SetFocusedTextInputClient(this);
2552 #if defined(OS_WIN)
2553 // The parent may have changed here. Ensure that the legacy window is
2554 // reparented accordingly.
2555 if (legacy_render_widget_host_HWND_)
2556 legacy_render_widget_host_HWND_->UpdateParent(
2557 reinterpret_cast<HWND>(GetNativeViewId()));
2558 #endif
2560 delegated_frame_host_->SetCompositor(window_->GetHost()->compositor());
2563 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2564 aura::client::CursorClient* cursor_client =
2565 aura::client::GetCursorClient(window_->GetRootWindow());
2566 if (cursor_client)
2567 cursor_client->RemoveObserver(this);
2569 DetachFromInputMethod();
2571 window_->GetHost()->RemoveObserver(this);
2572 delegated_frame_host_->ResetCompositor();
2574 #if defined(OS_WIN)
2575 // Update the legacy window's parent temporarily to the desktop window. It
2576 // will eventually get reparented to the right root.
2577 if (legacy_render_widget_host_HWND_)
2578 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
2579 #endif
2582 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2583 ui::InputMethod* input_method = GetInputMethod();
2584 if (input_method && input_method->GetTextInputClient() == this)
2585 input_method->SetFocusedTextInputClient(NULL);
2588 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2589 const NativeWebKeyboardEvent& event) {
2590 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2591 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
2592 ui::GetTextEditKeyBindingsDelegate();
2593 std::vector<ui::TextEditCommandAuraLinux> commands;
2594 if (!event.skip_in_browser &&
2595 keybinding_delegate &&
2596 event.os_event &&
2597 keybinding_delegate->MatchEvent(*event.os_event, &commands)) {
2598 // Transform from ui/ types to content/ types.
2599 EditCommands edit_commands;
2600 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it =
2601 commands.begin(); it != commands.end(); ++it) {
2602 edit_commands.push_back(EditCommand(it->GetCommandString(),
2603 it->argument()));
2605 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2606 host_->GetRoutingID(), edit_commands));
2607 NativeWebKeyboardEvent copy_event(event);
2608 copy_event.match_edit_command = true;
2609 host_->ForwardKeyboardEvent(copy_event);
2610 return;
2612 #endif
2614 host_->ForwardKeyboardEvent(event);
2617 SkColorType RenderWidgetHostViewAura::PreferredReadbackFormat() {
2618 return kN32_SkColorType;
2621 ////////////////////////////////////////////////////////////////////////////////
2622 // DelegatedFrameHost, public:
2624 ui::Layer* RenderWidgetHostViewAura::DelegatedFrameHostGetLayer() const {
2625 return window_->layer();
2628 bool RenderWidgetHostViewAura::DelegatedFrameHostIsVisible() const {
2629 return !host_->is_hidden();
2632 gfx::Size RenderWidgetHostViewAura::DelegatedFrameHostDesiredSizeInDIP() const {
2633 return window_->bounds().size();
2636 bool RenderWidgetHostViewAura::DelegatedFrameCanCreateResizeLock() const {
2637 #if !defined(OS_CHROMEOS)
2638 // On Windows and Linux, holding pointer moves will not help throttling
2639 // resizes.
2640 // TODO(piman): on Windows we need to block (nested message loop?) the
2641 // WM_SIZE event. On Linux we need to throttle at the WM level using
2642 // _NET_WM_SYNC_REQUEST.
2643 return false;
2644 #else
2645 if (host_->auto_resize_enabled())
2646 return false;
2647 return true;
2648 #endif
2651 scoped_ptr<ResizeLock>
2652 RenderWidgetHostViewAura::DelegatedFrameHostCreateResizeLock(
2653 bool defer_compositor_lock) {
2654 gfx::Size desired_size = window_->bounds().size();
2655 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
2656 window_->GetHost(),
2657 desired_size,
2658 defer_compositor_lock,
2659 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2662 void RenderWidgetHostViewAura::DelegatedFrameHostResizeLockWasReleased() {
2663 host_->WasResized();
2666 void RenderWidgetHostViewAura::DelegatedFrameHostSendCompositorSwapAck(
2667 int output_surface_id,
2668 const cc::CompositorFrameAck& ack) {
2669 host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
2670 output_surface_id, ack));
2673 void RenderWidgetHostViewAura::DelegatedFrameHostSendReclaimCompositorResources(
2674 int output_surface_id,
2675 const cc::CompositorFrameAck& ack) {
2676 host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
2677 output_surface_id, ack));
2680 void RenderWidgetHostViewAura::DelegatedFrameHostOnLostCompositorResources() {
2681 host_->ScheduleComposite();
2684 void RenderWidgetHostViewAura::DelegatedFrameHostUpdateVSyncParameters(
2685 const base::TimeTicks& timebase,
2686 const base::TimeDelta& interval) {
2687 host_->UpdateVSyncParameters(timebase, interval);
2690 void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() {
2691 ui::GestureRecognizer::Get()->CancelActiveTouches(window_);
2694 ////////////////////////////////////////////////////////////////////////////////
2695 // RenderWidgetHostViewBase, public:
2697 // static
2698 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2699 GetScreenInfoForWindow(results, NULL);
2702 } // namespace content