1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.h"
10 #include "base/callback_helpers.h"
11 #include "base/debug/trace_event.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "cc/output/copy_output_request.h"
16 #include "cc/output/copy_output_result.h"
17 #include "cc/resources/texture_mailbox.h"
18 #include "cc/trees/layer_tree_settings.h"
19 #include "content/browser/accessibility/browser_accessibility_manager.h"
20 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
21 #include "content/browser/frame_host/frame_tree.h"
22 #include "content/browser/frame_host/frame_tree_node.h"
23 #include "content/browser/frame_host/render_frame_host_impl.h"
24 #include "content/browser/gpu/compositor_util.h"
25 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
26 #include "content/browser/renderer_host/dip_util.h"
27 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
28 #include "content/browser/renderer_host/overscroll_controller.h"
29 #include "content/browser/renderer_host/render_view_host_delegate.h"
30 #include "content/browser/renderer_host/render_view_host_impl.h"
31 #include "content/browser/renderer_host/render_widget_host_impl.h"
32 #include "content/browser/renderer_host/ui_events_helper.h"
33 #include "content/browser/renderer_host/web_input_event_aura.h"
34 #include "content/common/gpu/client/gl_helper.h"
35 #include "content/common/gpu/gpu_messages.h"
36 #include "content/common/view_messages.h"
37 #include "content/public/browser/content_browser_client.h"
38 #include "content/public/browser/render_view_host.h"
39 #include "content/public/browser/render_widget_host_view_frame_subscriber.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
42 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
43 #include "third_party/WebKit/public/web/WebInputEvent.h"
44 #include "ui/aura/client/aura_constants.h"
45 #include "ui/aura/client/cursor_client.h"
46 #include "ui/aura/client/cursor_client_observer.h"
47 #include "ui/aura/client/focus_client.h"
48 #include "ui/aura/client/screen_position_client.h"
49 #include "ui/aura/client/window_tree_client.h"
50 #include "ui/aura/env.h"
51 #include "ui/aura/window.h"
52 #include "ui/aura/window_event_dispatcher.h"
53 #include "ui/aura/window_observer.h"
54 #include "ui/aura/window_tracker.h"
55 #include "ui/aura/window_tree_host.h"
56 #include "ui/base/clipboard/scoped_clipboard_writer.h"
57 #include "ui/base/hit_test.h"
58 #include "ui/base/ime/input_method.h"
59 #include "ui/base/ui_base_types.h"
60 #include "ui/compositor/compositor_vsync_manager.h"
61 #include "ui/events/event.h"
62 #include "ui/events/event_utils.h"
63 #include "ui/events/gestures/gesture_recognizer.h"
64 #include "ui/gfx/canvas.h"
65 #include "ui/gfx/display.h"
66 #include "ui/gfx/rect_conversions.h"
67 #include "ui/gfx/screen.h"
68 #include "ui/gfx/size_conversions.h"
69 #include "ui/gfx/skia_util.h"
70 #include "ui/wm/public/activation_client.h"
71 #include "ui/wm/public/scoped_tooltip_disabler.h"
72 #include "ui/wm/public/tooltip_client.h"
73 #include "ui/wm/public/transient_window_client.h"
74 #include "ui/wm/public/window_types.h"
77 #include "content/browser/accessibility/browser_accessibility_manager_win.h"
78 #include "content/browser/accessibility/browser_accessibility_win.h"
79 #include "content/browser/renderer_host/legacy_render_widget_host_win.h"
80 #include "content/common/plugin_constants_win.h"
81 #include "ui/base/win/hidden_window.h"
82 #include "ui/gfx/gdi_util.h"
83 #include "ui/gfx/win/dpi.h"
86 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
87 #include "content/common/input_messages.h"
88 #include "ui/events/linux/text_edit_command_auralinux.h"
89 #include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
92 using gfx::RectToSkIRect;
93 using gfx::SkIRectToRect;
95 using blink::WebScreenInfo;
96 using blink::WebTouchEvent;
102 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting
103 // the border of the view, in order to get valid movement information. However,
104 // forcing the cursor back to the center of the view after each mouse move
105 // doesn't work well. It reduces the frequency of useful mouse move messages
106 // significantly. Therefore, we move the cursor to the center of the view only
107 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width
108 // of the border area, in percentage of the corresponding dimension.
109 const int kMouseLockBorderPercentage = 15;
111 // When accelerated compositing is enabled and a widget resize is pending,
112 // we delay further resizes of the UI. The following constant is the maximum
113 // length of time that we should delay further UI resizes while waiting for a
114 // resized frame from a renderer.
115 const int kResizeLockTimeoutMs = 67;
118 // Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
119 const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
121 BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
122 RenderWidgetHostViewAura* widget =
123 reinterpret_cast<RenderWidgetHostViewAura*>(param);
124 if (GetProp(window, kWidgetOwnerProperty) == widget) {
125 // Properties set on HWNDs must be removed to avoid leaks.
126 RemoveProp(window, kWidgetOwnerProperty);
127 RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
132 BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
133 RenderWidgetHostViewAura* widget =
134 reinterpret_cast<RenderWidgetHostViewAura*>(param);
135 if (GetProp(window, kWidgetOwnerProperty) == widget)
136 SetParent(window, ui::GetHiddenWindow());
140 BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
141 RenderWidgetHostViewAura* widget =
142 reinterpret_cast<RenderWidgetHostViewAura*>(param);
144 if (GetProp(window, kWidgetOwnerProperty) == widget &&
145 widget->GetNativeView()->GetHost()) {
146 HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
147 SetParent(window, parent);
152 struct CutoutRectsParams {
153 RenderWidgetHostViewAura* widget;
154 std::vector<gfx::Rect> cutout_rects;
155 std::map<HWND, WebPluginGeometry>* geometry;
158 // Used to update the region for the windowed plugin to draw in. We start with
159 // the clip rect from the renderer, then remove the cutout rects from the
160 // renderer, and then remove the transient windows from the root window and the
161 // constrained windows from the parent window.
162 BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
163 CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
165 if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
166 // First calculate the offset of this plugin from the root window, since
167 // the cutouts are relative to the root window.
169 params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
171 offset.x = offset.y = 0;
172 MapWindowPoints(window, parent, &offset, 1);
174 // Now get the cached clip rect and cutouts for this plugin window that came
175 // from the renderer.
176 std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
177 while (i != params->geometry->end() &&
178 i->second.window != window &&
179 GetParent(i->second.window) != window) {
183 if (i == params->geometry->end()) {
188 HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
189 i->second.clip_rect.y(),
190 i->second.clip_rect.right(),
191 i->second.clip_rect.bottom());
192 // We start with the cutout rects that came from the renderer, then add the
193 // ones that came from transient and constrained windows.
194 std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
195 for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
196 gfx::Rect offset_cutout = params->cutout_rects[i];
197 offset_cutout.Offset(-offset.x, -offset.y);
198 cutout_rects.push_back(offset_cutout);
200 gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
201 // If we don't have any cutout rects then no point in messing with the
203 if (cutout_rects.size())
204 SetWindowRgn(window, hrgn, TRUE);
209 // A callback function for EnumThreadWindows to enumerate and dismiss
210 // any owned popup windows.
211 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
212 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg);
214 if (::IsWindowVisible(window)) {
215 const HWND owner = ::GetWindow(window, GW_OWNER);
216 if (toplevel_hwnd == owner) {
217 ::PostMessage(window, WM_CANCELMODE, 0, 0);
225 void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
226 blink::WebTouchPoint* point) {
227 if (point->state != blink::WebTouchPoint::StateReleased &&
228 point->state != blink::WebTouchPoint::StateCancelled)
230 --event->touchesLength;
231 for (unsigned i = point - event->touches;
232 i < event->touchesLength;
234 event->touches[i] = event->touches[i + 1];
238 bool CanRendererHandleEvent(const ui::MouseEvent* event) {
239 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
243 // Renderer cannot handle WM_XBUTTON or NC events.
244 switch (event->native_event().message) {
247 case WM_XBUTTONDBLCLK:
248 case WM_NCMOUSELEAVE:
250 case WM_NCLBUTTONDOWN:
252 case WM_NCLBUTTONDBLCLK:
253 case WM_NCRBUTTONDOWN:
255 case WM_NCRBUTTONDBLCLK:
256 case WM_NCMBUTTONDOWN:
258 case WM_NCMBUTTONDBLCLK:
259 case WM_NCXBUTTONDOWN:
261 case WM_NCXBUTTONDBLCLK:
266 #elif defined(USE_X11)
267 // Renderer only supports standard mouse buttons, so ignore programmable
269 switch (event->type()) {
270 case ui::ET_MOUSE_PRESSED:
271 case ui::ET_MOUSE_RELEASED:
272 return event->IsAnyButton();
280 // We don't mark these as handled so that they're sent back to the
281 // DefWindowProc so it can generate WM_APPCOMMAND as necessary.
282 bool IsXButtonUpEvent(const ui::MouseEvent* event) {
284 switch (event->native_event().message) {
293 void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
294 const gfx::Display display = window ?
295 gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
296 gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
297 results->rect = display.bounds();
298 results->availableRect = display.work_area();
299 // TODO(derat|oshima): Don't hardcode this. Get this from display object.
301 results->depthPerComponent = 8;
302 results->deviceScaleFactor = display.device_scale_factor();
303 results->orientationAngle = display.RotationAsDegree();
306 bool PointerEventActivates(const ui::Event& event) {
307 if (event.type() == ui::ET_MOUSE_PRESSED)
310 if (event.type() == ui::ET_GESTURE_BEGIN) {
311 const ui::GestureEvent& gesture =
312 static_cast<const ui::GestureEvent&>(event);
313 return gesture.details().touch_points() == 1;
321 // We need to watch for mouse events outside a Web Popup or its parent
322 // and dismiss the popup for certain events.
323 class RenderWidgetHostViewAura::EventFilterForPopupExit
324 : public ui::EventHandler {
326 explicit EventFilterForPopupExit(RenderWidgetHostViewAura* rwhva)
329 aura::Env::GetInstance()->AddPreTargetHandler(this);
332 virtual ~EventFilterForPopupExit() {
333 aura::Env::GetInstance()->RemovePreTargetHandler(this);
336 // Overridden from ui::EventHandler
337 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
338 rwhva_->ApplyEventFilterForPopupExit(event);
341 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
342 rwhva_->ApplyEventFilterForPopupExit(event);
346 RenderWidgetHostViewAura* rwhva_;
348 DISALLOW_COPY_AND_ASSIGN(EventFilterForPopupExit);
351 void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
352 ui::LocatedEvent* event) {
353 if (in_shutdown_ || is_fullscreen_ || !event->target())
356 if (event->type() != ui::ET_MOUSE_PRESSED &&
357 event->type() != ui::ET_TOUCH_PRESSED) {
361 aura::Window* target = static_cast<aura::Window*>(event->target());
362 if (target != window_ &&
363 (!popup_parent_host_view_ ||
364 target != popup_parent_host_view_->window_)) {
365 // Note: popup_parent_host_view_ may be NULL when there are multiple
366 // popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
372 // We have to implement the WindowObserver interface on a separate object
373 // because clang doesn't like implementing multiple interfaces that have
374 // methods with the same name. This object is owned by the
375 // RenderWidgetHostViewAura.
376 class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
378 explicit WindowObserver(RenderWidgetHostViewAura* view)
380 view_->window_->AddObserver(this);
383 virtual ~WindowObserver() {
384 view_->window_->RemoveObserver(this);
387 // Overridden from aura::WindowObserver:
388 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
389 if (window == view_->window_)
390 view_->AddedToRootWindow();
393 virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
394 aura::Window* new_root) OVERRIDE {
395 if (window == view_->window_)
396 view_->RemovingFromRootWindow();
400 RenderWidgetHostViewAura* view_;
402 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
405 ////////////////////////////////////////////////////////////////////////////////
406 // RenderWidgetHostViewAura, public:
408 RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
409 : host_(RenderWidgetHostImpl::From(host)),
410 window_(new aura::Window(this)),
411 delegated_frame_host_(new DelegatedFrameHost(this)),
413 in_bounds_changed_(false),
414 is_fullscreen_(false),
415 popup_parent_host_view_(NULL),
416 popup_child_host_view_(NULL),
418 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
419 text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
420 can_compose_inline_(true),
421 has_composition_text_(false),
422 accept_return_character_(false),
423 last_swapped_software_frame_scale_factor_(1.f),
425 synthetic_move_sent_(false),
426 cursor_visibility_state_in_renderer_(UNKNOWN),
427 touch_editing_client_(NULL),
428 weak_ptr_factory_(this) {
429 host_->SetView(this);
430 window_observer_.reset(new WindowObserver(this));
431 aura::client::SetTooltipText(window_, &tooltip_);
432 aura::client::SetActivationDelegate(window_, this);
433 aura::client::SetActivationChangeObserver(window_, this);
434 aura::client::SetFocusChangeObserver(window_, this);
435 window_->set_layer_owner_delegate(delegated_frame_host_.get());
436 gfx::Screen::GetScreenFor(window_)->AddObserver(this);
439 ////////////////////////////////////////////////////////////////////////////////
440 // RenderWidgetHostViewAura, RenderWidgetHostView implementation:
442 bool RenderWidgetHostViewAura::OnMessageReceived(
443 const IPC::Message& message) {
445 IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
446 // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
447 // messages for TextInput<State|Type>Changed. Corresponding code in
448 // RenderWidgetHostViewAndroid should also be moved at the same time.
449 IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
450 OnTextInputStateChanged)
451 IPC_MESSAGE_UNHANDLED(handled = false)
452 IPC_END_MESSAGE_MAP()
456 void RenderWidgetHostViewAura::InitAsChild(
457 gfx::NativeView parent_view) {
458 window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
459 window_->Init(aura::WINDOW_LAYER_TEXTURED);
460 window_->SetName("RenderWidgetHostViewAura");
463 void RenderWidgetHostViewAura::InitAsPopup(
464 RenderWidgetHostView* parent_host_view,
465 const gfx::Rect& bounds_in_screen) {
466 popup_parent_host_view_ =
467 static_cast<RenderWidgetHostViewAura*>(parent_host_view);
469 // TransientWindowClient may be NULL during tests.
470 aura::client::TransientWindowClient* transient_window_client =
471 aura::client::GetTransientWindowClient();
472 RenderWidgetHostViewAura* old_child =
473 popup_parent_host_view_->popup_child_host_view_;
475 // TODO(jhorwich): Allow multiple popup_child_host_view_ per view, or
476 // similar mechanism to ensure a second popup doesn't cause the first one
477 // to never get a chance to filter events. See crbug.com/160589.
478 DCHECK(old_child->popup_parent_host_view_ == popup_parent_host_view_);
479 if (transient_window_client) {
480 transient_window_client->RemoveTransientChild(
481 popup_parent_host_view_->window_, old_child->window_);
483 old_child->popup_parent_host_view_ = NULL;
485 popup_parent_host_view_->popup_child_host_view_ = this;
486 window_->SetType(ui::wm::WINDOW_TYPE_MENU);
487 window_->Init(aura::WINDOW_LAYER_TEXTURED);
488 window_->SetName("RenderWidgetHostViewAura");
490 aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
491 aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
492 // Setting the transient child allows for the popup to get mouse events when
493 // in a system modal dialog.
494 // This fixes crbug.com/328593.
495 if (transient_window_client) {
496 transient_window_client->AddTransientChild(
497 popup_parent_host_view_->window_, window_);
500 SetBounds(bounds_in_screen);
502 #if !defined(OS_WIN) && !defined(OS_CHROMEOS)
503 if (NeedsInputGrab())
504 window_->SetCapture();
507 event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
510 void RenderWidgetHostViewAura::InitAsFullscreen(
511 RenderWidgetHostView* reference_host_view) {
512 is_fullscreen_ = true;
513 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
514 window_->Init(aura::WINDOW_LAYER_TEXTURED);
515 window_->SetName("RenderWidgetHostViewAura");
516 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
518 aura::Window* parent = NULL;
520 if (reference_host_view) {
521 aura::Window* reference_window =
522 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
523 if (reference_window) {
524 host_tracker_.reset(new aura::WindowTracker);
525 host_tracker_->Add(reference_window);
527 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
528 GetDisplayNearestWindow(reference_window);
529 parent = reference_window->GetRootWindow();
530 bounds = display.bounds();
532 aura::client::ParentWindowWithContext(window_, parent, bounds);
537 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
541 void RenderWidgetHostViewAura::WasShown() {
543 if (!host_->is_hidden())
547 aura::Window* root = window_->GetRootWindow();
549 aura::client::CursorClient* cursor_client =
550 aura::client::GetCursorClient(root);
552 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
555 delegated_frame_host_->WasShown();
558 if (legacy_render_widget_host_HWND_) {
559 // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
560 // window before reparenting any plugins. This ensures that the plugin
561 // windows stay on top of the child Zorder in the parent and receive
562 // mouse events, etc.
563 legacy_render_widget_host_HWND_->UpdateParent(
564 GetNativeView()->GetHost()->GetAcceleratedWidget());
565 legacy_render_widget_host_HWND_->SetBounds(
566 window_->GetBoundsInRootWindow());
568 LPARAM lparam = reinterpret_cast<LPARAM>(this);
569 EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
573 void RenderWidgetHostViewAura::WasHidden() {
574 if (!host_ || host_->is_hidden())
577 delegated_frame_host_->WasHidden();
580 constrained_rects_.clear();
581 aura::WindowTreeHost* host = window_->GetHost();
583 HWND parent = host->GetAcceleratedWidget();
584 LPARAM lparam = reinterpret_cast<LPARAM>(this);
585 EnumChildWindows(parent, HideWindowsCallback, lparam);
586 // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
587 // hidden window on the same lines as Windowed plugin windows.
588 if (legacy_render_widget_host_HWND_)
589 legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
594 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
595 // For a SetSize operation, we don't care what coordinate system the origin
596 // of the window is in, it's only important to make sure that the origin
597 // remains constant after the operation.
598 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
601 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
602 gfx::Point relative_origin(rect.origin());
604 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
605 // Window::SetBounds() takes parent coordinates, so do the conversion here.
606 aura::Window* root = window_->GetRootWindow();
608 aura::client::ScreenPositionClient* screen_position_client =
609 aura::client::GetScreenPositionClient(root);
610 if (screen_position_client) {
611 screen_position_client->ConvertPointFromScreen(
612 window_->parent(), &relative_origin);
616 InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
619 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
623 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
625 aura::WindowTreeHost* host = window_->GetHost();
627 return reinterpret_cast<gfx::NativeViewId>(host->GetAcceleratedWidget());
629 return static_cast<gfx::NativeViewId>(NULL);
632 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
634 aura::WindowTreeHost* host = window_->GetHost();
636 return static_cast<gfx::NativeViewAccessible>(NULL);
637 HWND hwnd = host->GetAcceleratedWidget();
639 CreateBrowserAccessibilityManagerIfNeeded();
640 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
642 return manager->GetRoot()->ToBrowserAccessibilityWin();
646 return static_cast<gfx::NativeViewAccessible>(NULL);
649 ui::TextInputClient* RenderWidgetHostViewAura::GetTextInputClient() {
653 void RenderWidgetHostViewAura::SetKeyboardFocus() {
656 aura::WindowTreeHost* host = window_->GetHost();
658 ::SetFocus(host->GetAcceleratedWidget());
663 RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
664 if (!host_->IsRenderView())
666 RenderViewHost* rvh = RenderViewHost::From(host_);
667 FrameTreeNode* focused_frame =
668 rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
672 return focused_frame->current_frame_host();
675 void RenderWidgetHostViewAura::MovePluginWindows(
676 const std::vector<WebPluginGeometry>& plugin_window_moves) {
678 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
679 // over the browser UI.
680 if (!window_->GetRootWindow()) {
681 DCHECK(plugin_window_moves.empty());
684 HWND parent = window_->GetHost()->GetAcceleratedWidget();
685 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
686 std::vector<WebPluginGeometry> moves = plugin_window_moves;
688 gfx::Rect view_port(view_bounds.size());
690 for (size_t i = 0; i < moves.size(); ++i) {
691 gfx::Rect clip(moves[i].clip_rect);
692 gfx::Vector2d view_port_offset(
693 moves[i].window_rect.OffsetFromOrigin());
694 clip.Offset(view_port_offset);
695 clip.Intersect(view_port);
696 clip.Offset(-view_port_offset);
697 moves[i].clip_rect = clip;
699 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
701 plugin_window_moves_[moves[i].window] = moves[i];
703 // constrained_rects_ are relative to the root window. We want to convert
704 // them to be relative to the plugin window.
705 for (size_t j = 0; j < constrained_rects_.size(); ++j) {
706 gfx::Rect offset_cutout = constrained_rects_[j];
707 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
708 moves[i].cutout_rects.push_back(offset_cutout);
712 MovePluginWindowsHelper(parent, moves);
714 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
716 for (size_t i = 0; i < moves.size(); ++i) {
717 HWND window = moves[i].window;
718 if (GetParent(window) != parent) {
719 window = GetParent(window);
721 if (!GetProp(window, kWidgetOwnerProperty))
722 SetProp(window, kWidgetOwnerProperty, this);
724 #endif // defined(OS_WIN)
727 void RenderWidgetHostViewAura::Focus() {
728 // Make sure we have a FocusClient before attempting to Focus(). In some
729 // situations we may not yet be in a valid Window hierarchy (such as reloading
730 // after out of memory discarded the tab).
731 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
736 void RenderWidgetHostViewAura::Blur() {
740 bool RenderWidgetHostViewAura::HasFocus() const {
741 return window_->HasFocus();
744 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
745 return delegated_frame_host_->CanCopyToBitmap();
748 void RenderWidgetHostViewAura::Show() {
752 if (legacy_render_widget_host_HWND_)
753 legacy_render_widget_host_HWND_->Show();
757 void RenderWidgetHostViewAura::Hide() {
761 if (legacy_render_widget_host_HWND_)
762 legacy_render_widget_host_HWND_->Hide();
766 bool RenderWidgetHostViewAura::IsShowing() {
767 return window_->IsVisible();
770 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
771 // This is the size that we want the renderer to produce. While we're waiting
772 // for the correct frame (i.e. during a resize), don't change the size so that
773 // we don't pipeline more resizes than we can handle.
774 gfx::Rect bounds(window_->GetBoundsInScreen());
775 return delegated_frame_host_->GetViewBoundsWithResizeLock(bounds);
778 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
779 RenderWidgetHostViewBase::SetBackground(background);
780 host_->SetBackground(background);
781 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
784 gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
785 gfx::Rect window_bounds = window_->bounds();
786 int viewport_width = std::max(
787 0, window_bounds.width() - insets_.left() - insets_.right());
788 int viewport_height = std::max(
789 0, window_bounds.height() - insets_.top() - insets_.bottom());
790 return gfx::Size(viewport_width, viewport_height);
793 void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
794 if (insets != insets_) {
800 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
801 current_cursor_ = cursor;
802 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
803 GetDisplayNearestWindow(window_);
804 current_cursor_.SetDisplayInfo(display);
805 UpdateCursorIfOverSelf();
808 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
809 is_loading_ = is_loading;
810 UpdateCursorIfOverSelf();
813 void RenderWidgetHostViewAura::TextInputTypeChanged(
814 ui::TextInputType type,
815 ui::TextInputMode input_mode,
816 bool can_compose_inline) {
817 if (text_input_type_ != type ||
818 text_input_mode_ != input_mode ||
819 can_compose_inline_ != can_compose_inline) {
820 text_input_type_ = type;
821 text_input_mode_ = input_mode;
822 can_compose_inline_ = can_compose_inline;
823 if (GetInputMethod())
824 GetInputMethod()->OnTextInputTypeChanged(this);
825 if (touch_editing_client_)
826 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
830 void RenderWidgetHostViewAura::OnTextInputStateChanged(
831 const ViewHostMsg_TextInputState_Params& params) {
832 if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
833 if (GetInputMethod())
834 GetInputMethod()->ShowImeIfNeeded();
838 void RenderWidgetHostViewAura::ImeCancelComposition() {
839 if (GetInputMethod())
840 GetInputMethod()->CancelComposition(this);
841 has_composition_text_ = false;
844 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
845 const gfx::Range& range,
846 const std::vector<gfx::Rect>& character_bounds) {
847 composition_character_bounds_ = character_bounds;
850 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
852 UpdateCursorIfOverSelf();
856 void RenderWidgetHostViewAura::Destroy() {
857 // Beware, this function is not called on all destruction paths. It will
858 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
859 // destruction/cleanup code should happen there, not here.
864 void RenderWidgetHostViewAura::SetTooltipText(
865 const base::string16& tooltip_text) {
866 tooltip_ = tooltip_text;
867 aura::Window* root_window = window_->GetRootWindow();
868 aura::client::TooltipClient* tooltip_client =
869 aura::client::GetTooltipClient(root_window);
870 if (tooltip_client) {
871 tooltip_client->UpdateTooltip(window_);
872 // Content tooltips should be visible indefinitely.
873 tooltip_client->SetTooltipShownTimeout(window_, 0);
877 void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
879 const gfx::Range& range) {
880 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
882 #if defined(USE_X11) && !defined(OS_CHROMEOS)
883 if (text.empty() || range.is_empty())
885 size_t pos = range.GetMin() - offset;
886 size_t n = range.length();
888 DCHECK(pos + n <= text.length()) << "The text can not fully cover range.";
889 if (pos >= text.length()) {
890 NOTREACHED() << "The text can not cover range.";
894 // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
895 ui::ScopedClipboardWriter clipboard_writer(
896 ui::Clipboard::GetForCurrentThread(),
897 ui::CLIPBOARD_TYPE_SELECTION);
898 clipboard_writer.WriteText(text.substr(pos, n));
899 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
902 void RenderWidgetHostViewAura::SelectionBoundsChanged(
903 const ViewHostMsg_SelectionBounds_Params& params) {
904 if (selection_anchor_rect_ == params.anchor_rect &&
905 selection_focus_rect_ == params.focus_rect)
908 selection_anchor_rect_ = params.anchor_rect;
909 selection_focus_rect_ = params.focus_rect;
911 if (GetInputMethod())
912 GetInputMethod()->OnCaretBoundsChanged(this);
914 if (touch_editing_client_) {
915 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
916 selection_focus_rect_);
920 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
921 aura::Window* root = window_->GetRootWindow();
924 aura::client::CursorClient* cursor_client =
925 aura::client::GetCursorClient(root);
926 if (cursor_client && !cursor_client->IsCursorVisible())
927 cursor_client->DisableMouseEvents();
930 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
931 const gfx::Rect& src_subrect,
932 const gfx::Size& dst_size,
933 const base::Callback<void(bool, const SkBitmap&)>& callback,
934 const SkBitmap::Config config) {
935 delegated_frame_host_->CopyFromCompositingSurface(
936 src_subrect, dst_size, callback, config);
939 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
940 const gfx::Rect& src_subrect,
941 const scoped_refptr<media::VideoFrame>& target,
942 const base::Callback<void(bool)>& callback) {
943 delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
944 src_subrect, target, callback);
947 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
948 return delegated_frame_host_->CanCopyToVideoFrame();
951 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
952 return delegated_frame_host_->CanSubscribeFrame();
955 void RenderWidgetHostViewAura::BeginFrameSubscription(
956 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
957 delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
960 void RenderWidgetHostViewAura::EndFrameSubscription() {
961 delegated_frame_host_->EndFrameSubscription();
964 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
967 void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
971 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
972 if (HasDisplayPropertyChanged(window_))
973 host_->InvalidateScreenInfo();
975 // Don't recursively call SetBounds if this bounds update is the result of
976 // a Window::SetBoundsInternal call.
977 if (!in_bounds_changed_)
978 window_->SetBounds(rect);
980 delegated_frame_host_->WasResized();
981 if (touch_editing_client_) {
982 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
983 selection_focus_rect_);
986 // Create the legacy dummy window which corresponds to the bounds of the
987 // webcontents. This will be passed as the container window for windowless
989 // Plugins like Flash assume the container window which is returned via the
990 // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
991 // This is not true in Aura where we have only HWND which is the main Aura
992 // window. If we return this window to plugins like Flash then it causes the
993 // coordinate translations done by these plugins to break.
994 // Additonally the legacy dummy window is needed for accessibility and for
995 // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
996 if (GetNativeViewId()) {
997 if (!legacy_render_widget_host_HWND_) {
998 legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
999 reinterpret_cast<HWND>(GetNativeViewId()));
1001 if (legacy_render_widget_host_HWND_) {
1002 legacy_render_widget_host_HWND_->SetBounds(
1003 window_->GetBoundsInRootWindow());
1008 UpdateMouseLockRegion();
1013 bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
1014 return (legacy_render_widget_host_HWND_ != NULL);
1017 void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
1018 const std::vector<gfx::Rect>& rects) {
1019 // Check this before setting constrained_rects_, so that next time they're set
1020 // and we have a root window we don't early return.
1021 if (!window_->GetHost())
1024 if (rects == constrained_rects_)
1027 constrained_rects_ = rects;
1029 HWND parent = window_->GetHost()->GetAcceleratedWidget();
1030 CutoutRectsParams params;
1031 params.widget = this;
1032 params.cutout_rects = constrained_rects_;
1033 params.geometry = &plugin_window_moves_;
1034 LPARAM lparam = reinterpret_cast<LPARAM>(¶ms);
1035 EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
1038 void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
1039 // Clip the cursor if chrome is running on regular desktop.
1040 if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
1041 RECT window_rect = window_->GetBoundsInScreen().ToRECT();
1042 ::ClipCursor(&window_rect);
1047 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
1048 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
1050 // Oldschool composited mode is no longer supported.
1053 void RenderWidgetHostViewAura::OnSwapCompositorFrame(
1054 uint32 output_surface_id,
1055 scoped_ptr<cc::CompositorFrame> frame) {
1056 TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
1057 if (frame->delegated_frame_data) {
1058 delegated_frame_host_->SwapDelegatedFrame(
1060 frame->delegated_frame_data.Pass(),
1061 frame->metadata.device_scale_factor,
1062 frame->metadata.latency_info);
1066 if (frame->software_frame_data) {
1067 DLOG(ERROR) << "Unable to use software frame in aura";
1069 base::UserMetricsAction("BadMessageTerminate_SharedMemoryAura"));
1070 host_->GetProcess()->ReceivedBadMessage();
1076 void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
1077 gfx::NativeViewAccessible accessible_parent) {
1078 if (GetBrowserAccessibilityManager()) {
1079 GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
1080 ->set_parent_iaccessible(accessible_parent);
1084 gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
1086 if (legacy_render_widget_host_HWND_) {
1087 return reinterpret_cast<gfx::NativeViewId>(
1088 legacy_render_widget_host_HWND_->hwnd());
1094 void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
1095 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
1097 // Oldschool composited mode is no longer supported.
1100 void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
1103 void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
1106 bool RenderWidgetHostViewAura::HasAcceleratedSurface(
1107 const gfx::Size& desired_size) {
1108 // Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
1109 // matter what is returned here as GetBackingStore is the only caller of this
1110 // method. TODO(jbates) implement this if other Aura code needs it.
1114 void RenderWidgetHostViewAura::GetScreenInfo(WebScreenInfo* results) {
1115 GetScreenInfoForWindow(results, window_->GetRootWindow() ? window_ : NULL);
1118 gfx::Rect RenderWidgetHostViewAura::GetBoundsInRootWindow() {
1119 aura::Window* top_level = window_->GetToplevelWindow();
1120 gfx::Rect bounds(top_level->GetBoundsInScreen());
1123 // TODO(zturner,iyengar): This will break when we remove support for NPAPI and
1124 // remove the legacy hwnd, so a better fix will need to be decided when that
1126 if (UsesNativeWindowFrame()) {
1127 // aura::Window doesn't take into account non-client area of native windows
1128 // (e.g. HWNDs), so for that case ask Windows directly what the bounds are.
1129 aura::WindowTreeHost* host = top_level->GetHost();
1131 return top_level->GetBoundsInScreen();
1132 RECT window_rect = {0};
1133 HWND hwnd = host->GetAcceleratedWidget();
1134 ::GetWindowRect(hwnd, &window_rect);
1135 bounds = gfx::Rect(window_rect);
1137 // Maximized windows are outdented from the work area by the frame thickness
1138 // even though this "frame" is not painted. This confuses code (and people)
1139 // that think of a maximized window as corresponding exactly to the work
1140 // area. Correct for this by subtracting the frame thickness back off.
1141 if (::IsZoomed(hwnd)) {
1142 bounds.Inset(GetSystemMetrics(SM_CXSIZEFRAME),
1143 GetSystemMetrics(SM_CYSIZEFRAME));
1145 bounds.Inset(GetSystemMetrics(SM_CXPADDEDBORDER),
1146 GetSystemMetrics(SM_CXPADDEDBORDER));
1150 bounds = gfx::win::ScreenToDIPRect(bounds);
1156 void RenderWidgetHostViewAura::GestureEventAck(
1157 const blink::WebGestureEvent& event,
1158 InputEventAckState ack_result) {
1159 if (touch_editing_client_)
1160 touch_editing_client_->GestureEventAck(event.type);
1163 void RenderWidgetHostViewAura::ProcessAckedTouchEvent(
1164 const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
1165 ScopedVector<ui::TouchEvent> events;
1166 if (!MakeUITouchEventsFromWebTouchEvents(touch, &events,
1167 SCREEN_COORDINATES))
1170 aura::WindowTreeHost* host = window_->GetHost();
1171 // |host| is NULL during tests.
1175 ui::EventResult result = (ack_result ==
1176 INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
1177 for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
1178 end = events.end(); iter != end; ++iter) {
1179 host->dispatcher()->ProcessedTouchEvent((*iter), window_, result);
1183 scoped_ptr<SyntheticGestureTarget>
1184 RenderWidgetHostViewAura::CreateSyntheticGestureTarget() {
1185 return scoped_ptr<SyntheticGestureTarget>(
1186 new SyntheticGestureTargetAura(host_));
1189 void RenderWidgetHostViewAura::SetScrollOffsetPinning(
1190 bool is_pinned_to_left, bool is_pinned_to_right) {
1191 // Not needed. Mac-only.
1194 void RenderWidgetHostViewAura::CreateBrowserAccessibilityManagerIfNeeded() {
1195 if (GetBrowserAccessibilityManager())
1198 BrowserAccessibilityManager* manager = NULL;
1200 aura::WindowTreeHost* host = window_->GetHost();
1203 HWND hwnd = host->GetAcceleratedWidget();
1205 // The accessible_parent may be NULL at this point. The WebContents will pass
1206 // it down to this instance (by way of the RenderViewHost and
1207 // RenderWidgetHost) when it is known. This instance will then set it on its
1208 // BrowserAccessibilityManager.
1209 gfx::NativeViewAccessible accessible_parent =
1210 host_->GetParentNativeViewAccessible();
1212 if (legacy_render_widget_host_HWND_) {
1213 manager = new BrowserAccessibilityManagerWin(
1214 legacy_render_widget_host_HWND_.get(), accessible_parent,
1215 BrowserAccessibilityManagerWin::GetEmptyDocument(), host_);
1218 manager = BrowserAccessibilityManager::Create(
1219 BrowserAccessibilityManager::GetEmptyDocument(), host_);
1221 SetBrowserAccessibilityManager(manager);
1224 gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
1225 return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
1228 bool RenderWidgetHostViewAura::LockMouse() {
1229 aura::Window* root_window = window_->GetRootWindow();
1236 mouse_locked_ = true;
1237 #if !defined(OS_WIN)
1238 window_->SetCapture();
1240 UpdateMouseLockRegion();
1242 aura::client::CursorClient* cursor_client =
1243 aura::client::GetCursorClient(root_window);
1244 if (cursor_client) {
1245 cursor_client->HideCursor();
1246 cursor_client->LockCursor();
1249 if (ShouldMoveToCenter()) {
1250 synthetic_move_sent_ = true;
1251 window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
1253 tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
1257 void RenderWidgetHostViewAura::UnlockMouse() {
1258 tooltip_disabler_.reset();
1260 aura::Window* root_window = window_->GetRootWindow();
1261 if (!mouse_locked_ || !root_window)
1264 mouse_locked_ = false;
1266 #if !defined(OS_WIN)
1267 window_->ReleaseCapture();
1271 window_->MoveCursorTo(unlocked_mouse_position_);
1272 aura::client::CursorClient* cursor_client =
1273 aura::client::GetCursorClient(root_window);
1274 if (cursor_client) {
1275 cursor_client->UnlockCursor();
1276 cursor_client->ShowCursor();
1279 host_->LostMouseLock();
1282 ////////////////////////////////////////////////////////////////////////////////
1283 // RenderWidgetHostViewAura, ui::TextInputClient implementation:
1284 void RenderWidgetHostViewAura::SetCompositionText(
1285 const ui::CompositionText& composition) {
1289 // ui::CompositionUnderline should be identical to
1290 // blink::WebCompositionUnderline, so that we can do reinterpret_cast safely.
1291 COMPILE_ASSERT(sizeof(ui::CompositionUnderline) ==
1292 sizeof(blink::WebCompositionUnderline),
1293 ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
1295 // TODO(suzhe): convert both renderer_host and renderer to use
1296 // ui::CompositionText.
1297 const std::vector<blink::WebCompositionUnderline>& underlines =
1298 reinterpret_cast<const std::vector<blink::WebCompositionUnderline>&>(
1299 composition.underlines);
1301 // TODO(suzhe): due to a bug of webkit, we can't use selection range with
1302 // composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
1303 host_->ImeSetComposition(composition.text, underlines,
1304 composition.selection.end(),
1305 composition.selection.end());
1307 has_composition_text_ = !composition.text.empty();
1310 void RenderWidgetHostViewAura::ConfirmCompositionText() {
1311 if (host_ && has_composition_text_) {
1312 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
1315 has_composition_text_ = false;
1318 void RenderWidgetHostViewAura::ClearCompositionText() {
1319 if (host_ && has_composition_text_)
1320 host_->ImeCancelComposition();
1321 has_composition_text_ = false;
1324 void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
1325 DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
1327 host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
1328 has_composition_text_ = false;
1331 void RenderWidgetHostViewAura::InsertChar(base::char16 ch, int flags) {
1332 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1333 popup_child_host_view_->InsertChar(ch, flags);
1337 // Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
1338 if (host_ && (accept_return_character_ || ch != ui::VKEY_RETURN)) {
1339 double now = ui::EventTimeForNow().InSecondsF();
1340 // Send a blink::WebInputEvent::Char event to |host_|.
1341 NativeWebKeyboardEvent webkit_event(ui::ET_KEY_PRESSED,
1346 ForwardKeyboardEvent(webkit_event);
1350 gfx::NativeWindow RenderWidgetHostViewAura::GetAttachedWindow() const {
1354 ui::TextInputType RenderWidgetHostViewAura::GetTextInputType() const {
1355 return text_input_type_;
1358 ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
1359 return text_input_mode_;
1362 bool RenderWidgetHostViewAura::CanComposeInline() const {
1363 return can_compose_inline_;
1366 gfx::Rect RenderWidgetHostViewAura::ConvertRectToScreen(
1367 const gfx::Rect& rect) const {
1368 gfx::Point origin = rect.origin();
1369 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1371 aura::Window* root_window = window_->GetRootWindow();
1374 aura::client::ScreenPositionClient* screen_position_client =
1375 aura::client::GetScreenPositionClient(root_window);
1376 if (!screen_position_client)
1378 screen_position_client->ConvertPointToScreen(window_, &origin);
1379 screen_position_client->ConvertPointToScreen(window_, &end);
1380 return gfx::Rect(origin.x(),
1382 end.x() - origin.x(),
1383 end.y() - origin.y());
1386 gfx::Rect RenderWidgetHostViewAura::ConvertRectFromScreen(
1387 const gfx::Rect& rect) const {
1388 gfx::Point origin = rect.origin();
1389 gfx::Point end = gfx::Point(rect.right(), rect.bottom());
1391 aura::Window* root_window = window_->GetRootWindow();
1393 aura::client::ScreenPositionClient* screen_position_client =
1394 aura::client::GetScreenPositionClient(root_window);
1395 screen_position_client->ConvertPointFromScreen(window_, &origin);
1396 screen_position_client->ConvertPointFromScreen(window_, &end);
1397 return gfx::Rect(origin.x(),
1399 end.x() - origin.x(),
1400 end.y() - origin.y());
1406 gfx::Rect RenderWidgetHostViewAura::GetCaretBounds() const {
1407 const gfx::Rect rect =
1408 gfx::UnionRects(selection_anchor_rect_, selection_focus_rect_);
1409 return ConvertRectToScreen(rect);
1412 bool RenderWidgetHostViewAura::GetCompositionCharacterBounds(
1414 gfx::Rect* rect) const {
1416 if (index >= composition_character_bounds_.size())
1418 *rect = ConvertRectToScreen(composition_character_bounds_[index]);
1422 bool RenderWidgetHostViewAura::HasCompositionText() const {
1423 return has_composition_text_;
1426 bool RenderWidgetHostViewAura::GetTextRange(gfx::Range* range) const {
1427 range->set_start(selection_text_offset_);
1428 range->set_end(selection_text_offset_ + selection_text_.length());
1432 bool RenderWidgetHostViewAura::GetCompositionTextRange(
1433 gfx::Range* range) const {
1434 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1439 bool RenderWidgetHostViewAura::GetSelectionRange(gfx::Range* range) const {
1440 range->set_start(selection_range_.start());
1441 range->set_end(selection_range_.end());
1445 bool RenderWidgetHostViewAura::SetSelectionRange(const gfx::Range& range) {
1446 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1451 bool RenderWidgetHostViewAura::DeleteRange(const gfx::Range& range) {
1452 // TODO(suzhe): implement this method when fixing http://crbug.com/55130.
1457 bool RenderWidgetHostViewAura::GetTextFromRange(
1458 const gfx::Range& range,
1459 base::string16* text) const {
1460 gfx::Range selection_text_range(selection_text_offset_,
1461 selection_text_offset_ + selection_text_.length());
1463 if (!selection_text_range.Contains(range)) {
1467 if (selection_text_range.EqualsIgnoringDirection(range)) {
1468 // Avoid calling substr whose performance is low.
1469 *text = selection_text_;
1471 *text = selection_text_.substr(
1472 range.GetMin() - selection_text_offset_,
1478 void RenderWidgetHostViewAura::OnInputMethodChanged() {
1482 if (GetInputMethod())
1483 host_->SetInputMethodActive(GetInputMethod()->IsActive());
1485 // TODO(suzhe): implement the newly added “locale” property of HTML DOM
1489 bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
1490 base::i18n::TextDirection direction) {
1493 host_->UpdateTextDirection(
1494 direction == base::i18n::RIGHT_TO_LEFT ?
1495 blink::WebTextDirectionRightToLeft :
1496 blink::WebTextDirectionLeftToRight);
1497 host_->NotifyTextDirection();
1501 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
1502 size_t before, size_t after) {
1503 RenderFrameHostImpl* rfh = GetFocusedFrame();
1505 rfh->ExtendSelectionAndDelete(before, after);
1508 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
1509 gfx::Rect intersected_rect(
1510 gfx::IntersectRects(rect, window_->GetBoundsInScreen()));
1512 if (intersected_rect.IsEmpty())
1515 host_->ScrollFocusedEditableNodeIntoRect(
1516 ConvertRectFromScreen(intersected_rect));
1519 void RenderWidgetHostViewAura::OnCandidateWindowShown() {
1520 host_->CandidateWindowShown();
1523 void RenderWidgetHostViewAura::OnCandidateWindowUpdated() {
1524 host_->CandidateWindowUpdated();
1527 void RenderWidgetHostViewAura::OnCandidateWindowHidden() {
1528 host_->CandidateWindowHidden();
1531 ////////////////////////////////////////////////////////////////////////////////
1532 // RenderWidgetHostViewAura, gfx::DisplayObserver implementation:
1534 void RenderWidgetHostViewAura::OnDisplayBoundsChanged(
1535 const gfx::Display& display) {
1536 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
1537 if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
1538 UpdateScreenInfo(window_);
1539 current_cursor_.SetDisplayInfo(display);
1540 UpdateCursorIfOverSelf();
1544 void RenderWidgetHostViewAura::OnDisplayAdded(
1545 const gfx::Display& new_display) {
1548 void RenderWidgetHostViewAura::OnDisplayRemoved(
1549 const gfx::Display& old_display) {
1552 ////////////////////////////////////////////////////////////////////////////////
1553 // RenderWidgetHostViewAura, aura::WindowDelegate implementation:
1555 gfx::Size RenderWidgetHostViewAura::GetMinimumSize() const {
1559 gfx::Size RenderWidgetHostViewAura::GetMaximumSize() const {
1563 void RenderWidgetHostViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1564 const gfx::Rect& new_bounds) {
1565 base::AutoReset<bool> in_bounds_changed(&in_bounds_changed_, true);
1566 // We care about this whenever RenderWidgetHostViewAura is not owned by a
1567 // WebContentsViewAura since changes to the Window's bounds need to be
1568 // messaged to the renderer. WebContentsViewAura invokes SetSize() or
1569 // SetBounds() itself. No matter how we got here, any redundant calls are
1571 SetSize(new_bounds.size());
1573 if (GetInputMethod())
1574 GetInputMethod()->OnCaretBoundsChanged(this);
1577 gfx::NativeCursor RenderWidgetHostViewAura::GetCursor(const gfx::Point& point) {
1579 return ui::kCursorNone;
1580 return current_cursor_.GetNativeCursor();
1583 int RenderWidgetHostViewAura::GetNonClientComponent(
1584 const gfx::Point& point) const {
1588 bool RenderWidgetHostViewAura::ShouldDescendIntoChildForEventHandling(
1589 aura::Window* child,
1590 const gfx::Point& location) {
1594 bool RenderWidgetHostViewAura::CanFocus() {
1595 return popup_type_ == blink::WebPopupTypeNone;
1598 void RenderWidgetHostViewAura::OnCaptureLost() {
1599 host_->LostCapture();
1600 if (touch_editing_client_)
1601 touch_editing_client_->EndTouchEditing(false);
1604 void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
1605 // For non-opaque windows, we don't draw anything, since we depend on the
1606 // canvas coming from the compositor to already be initialized as
1608 if (window_->layer()->fills_bounds_opaquely())
1609 canvas->DrawColor(SK_ColorWHITE);
1612 void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
1613 float device_scale_factor) {
1617 UpdateScreenInfo(window_);
1619 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1620 GetDisplayNearestWindow(window_);
1621 DCHECK_EQ(device_scale_factor, display.device_scale_factor());
1622 current_cursor_.SetDisplayInfo(display);
1625 void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
1628 // If the tab was hidden and it's closed, host_->is_hidden would have been
1629 // reset to false in RenderWidgetHostImpl::RendererExited.
1630 if (!window_->GetRootWindow() || host_->is_hidden()) {
1631 parent = ui::GetHiddenWindow();
1633 parent = window_->GetHost()->GetAcceleratedWidget();
1635 LPARAM lparam = reinterpret_cast<LPARAM>(this);
1636 EnumChildWindows(parent, WindowDestroyingCallback, lparam);
1639 // Make sure that the input method no longer references to this object before
1640 // this object is removed from the root window (i.e. this object loses access
1641 // to the input method).
1642 ui::InputMethod* input_method = GetInputMethod();
1644 input_method->DetachTextInputClient(this);
1647 void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
1648 host_->ViewDestroyed();
1652 void RenderWidgetHostViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1655 bool RenderWidgetHostViewAura::HasHitTestMask() const {
1659 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
1662 ////////////////////////////////////////////////////////////////////////////////
1663 // RenderWidgetHostViewAura, ui::EventHandler implementation:
1665 void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
1666 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnKeyEvent");
1667 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1670 if (popup_child_host_view_ && popup_child_host_view_->NeedsInputGrab()) {
1671 popup_child_host_view_->OnKeyEvent(event);
1672 if (event->handled())
1676 // We need to handle the Escape key for Pepper Flash.
1677 if (is_fullscreen_ && event->key_code() == ui::VKEY_ESCAPE) {
1678 // Focus the window we were created from.
1679 if (host_tracker_.get() && !host_tracker_->windows().empty()) {
1680 aura::Window* host = *(host_tracker_->windows().begin());
1681 aura::client::FocusClient* client = aura::client::GetFocusClient(host);
1683 // Calling host->Focus() may delete |this|. We create a local observer
1684 // for that. In that case we exit without further access to any members.
1685 aura::WindowTracker tracker;
1686 aura::Window* window = window_;
1687 tracker.Add(window);
1689 if (!tracker.Contains(window)) {
1690 event->SetHandled();
1695 if (!in_shutdown_) {
1696 in_shutdown_ = true;
1700 if (event->key_code() == ui::VKEY_RETURN) {
1701 // Do not forward return key release events if no press event was handled.
1702 if (event->type() == ui::ET_KEY_RELEASED && !accept_return_character_)
1704 // Accept return key character events between press and release events.
1705 accept_return_character_ = event->type() == ui::ET_KEY_PRESSED;
1708 // We don't have to communicate with an input method here.
1709 if (!event->HasNativeEvent()) {
1710 NativeWebKeyboardEvent webkit_event(
1713 event->is_char() ? event->GetCharacter() : event->key_code(),
1715 ui::EventTimeForNow().InSecondsF());
1716 ForwardKeyboardEvent(webkit_event);
1718 NativeWebKeyboardEvent webkit_event(event);
1719 ForwardKeyboardEvent(webkit_event);
1722 event->SetHandled();
1725 void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
1726 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
1728 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1731 if (mouse_locked_) {
1732 aura::client::CursorClient* cursor_client =
1733 aura::client::GetCursorClient(window_->GetRootWindow());
1734 DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
1736 if (event->type() == ui::ET_MOUSEWHEEL) {
1737 blink::WebMouseWheelEvent mouse_wheel_event =
1738 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
1739 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
1740 host_->ForwardWheelEvent(mouse_wheel_event);
1744 gfx::Point center(gfx::Rect(window_->bounds().size()).CenterPoint());
1746 // If we receive non client mouse messages while we are in the locked state
1747 // it probably means that the mouse left the borders of our window and
1748 // needs to be moved back to the center.
1749 if (event->flags() & ui::EF_IS_NON_CLIENT) {
1750 synthetic_move_sent_ = true;
1751 window_->MoveCursorTo(center);
1755 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
1757 bool is_move_to_center_event = (event->type() == ui::ET_MOUSE_MOVED ||
1758 event->type() == ui::ET_MOUSE_DRAGGED) &&
1759 mouse_event.x == center.x() && mouse_event.y == center.y();
1761 ModifyEventMovementAndCoords(&mouse_event);
1763 bool should_not_forward = is_move_to_center_event && synthetic_move_sent_;
1764 if (should_not_forward) {
1765 synthetic_move_sent_ = false;
1767 // Check if the mouse has reached the border and needs to be centered.
1768 if (ShouldMoveToCenter()) {
1769 synthetic_move_sent_ = true;
1770 window_->MoveCursorTo(center);
1772 // Forward event to renderer.
1773 if (CanRendererHandleEvent(event) &&
1774 !(event->flags() & ui::EF_FROM_TOUCH)) {
1775 host_->ForwardMouseEvent(mouse_event);
1776 // Ensure that we get keyboard focus on mouse down as a plugin window
1777 // may have grabbed keyboard focus.
1778 if (event->type() == ui::ET_MOUSE_PRESSED)
1785 // As the overscroll is handled during scroll events from the trackpad, the
1786 // RWHVA window is transformed by the overscroll controller. This transform
1787 // triggers a synthetic mouse-move event to be generated (by the aura
1788 // RootWindow). But this event interferes with the overscroll gesture. So,
1789 // ignore such synthetic mouse-move events if an overscroll gesture is in
1791 if (host_->overscroll_controller() &&
1792 host_->overscroll_controller()->overscroll_mode() != OVERSCROLL_NONE &&
1793 event->flags() & ui::EF_IS_SYNTHESIZED &&
1794 (event->type() == ui::ET_MOUSE_ENTERED ||
1795 event->type() == ui::ET_MOUSE_EXITED ||
1796 event->type() == ui::ET_MOUSE_MOVED)) {
1797 event->StopPropagation();
1801 if (event->type() == ui::ET_MOUSEWHEEL) {
1803 // We get mouse wheel/scroll messages even if we are not in the foreground.
1804 // So here we check if we have any owned popup windows in the foreground and
1806 aura::WindowTreeHost* host = window_->GetHost();
1808 HWND parent = host->GetAcceleratedWidget();
1809 HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
1810 EnumThreadWindows(GetCurrentThreadId(),
1812 reinterpret_cast<LPARAM>(toplevel_hwnd));
1815 blink::WebMouseWheelEvent mouse_wheel_event =
1816 MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
1817 if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
1818 host_->ForwardWheelEvent(mouse_wheel_event);
1819 } else if (CanRendererHandleEvent(event) &&
1820 !(event->flags() & ui::EF_FROM_TOUCH)) {
1821 blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
1822 ModifyEventMovementAndCoords(&mouse_event);
1823 host_->ForwardMouseEvent(mouse_event);
1824 // Ensure that we get keyboard focus on mouse down as a plugin window may
1825 // have grabbed keyboard focus.
1826 if (event->type() == ui::ET_MOUSE_PRESSED)
1830 switch (event->type()) {
1831 case ui::ET_MOUSE_PRESSED:
1832 window_->SetCapture();
1833 // Confirm existing composition text on mouse click events, to make sure
1834 // the input caret won't be moved with an ongoing composition text.
1835 FinishImeCompositionSession();
1837 case ui::ET_MOUSE_RELEASED:
1838 window_->ReleaseCapture();
1844 // Needed to propagate mouse event to |window_->parent()->delegate()|, but
1845 // note that it might be something other than a WebContentsViewAura instance.
1846 // TODO(pkotwicz): Find a better way of doing this.
1847 // In fullscreen mode which is typically used by flash, don't forward
1848 // the mouse events to the parent. The renderer and the plugin process
1849 // handle these events.
1850 if (!is_fullscreen_ && window_->parent()->delegate() &&
1851 !(event->flags() & ui::EF_FROM_TOUCH)) {
1852 event->ConvertLocationToTarget(window_, window_->parent());
1853 window_->parent()->delegate()->OnMouseEvent(event);
1856 if (!IsXButtonUpEvent(event))
1857 event->SetHandled();
1860 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
1861 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnScrollEvent");
1862 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1865 if (event->type() == ui::ET_SCROLL) {
1866 #if !defined(OS_WIN)
1868 // Investigate if this is true for Windows 8 Metro ASH as well.
1869 if (event->finger_count() != 2)
1872 blink::WebGestureEvent gesture_event =
1873 MakeWebGestureEventFlingCancel();
1874 host_->ForwardGestureEvent(gesture_event);
1875 blink::WebMouseWheelEvent mouse_wheel_event =
1876 MakeWebMouseWheelEvent(event);
1877 host_->ForwardWheelEvent(mouse_wheel_event);
1878 RecordAction(base::UserMetricsAction("TrackpadScroll"));
1879 } else if (event->type() == ui::ET_SCROLL_FLING_START ||
1880 event->type() == ui::ET_SCROLL_FLING_CANCEL) {
1881 blink::WebGestureEvent gesture_event =
1882 MakeWebGestureEvent(event);
1883 host_->ForwardGestureEvent(gesture_event);
1884 if (event->type() == ui::ET_SCROLL_FLING_START)
1885 RecordAction(base::UserMetricsAction("TrackpadScrollFling"));
1888 event->SetHandled();
1891 void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) {
1892 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnTouchEvent");
1893 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1896 // Update the touch event first.
1897 blink::WebTouchPoint* point = UpdateWebTouchEventFromUIEvent(*event,
1900 // Forward the touch event only if a touch point was updated, and there's a
1901 // touch-event handler in the page, and no other touch-event is in the queue.
1902 // It is important to always consume the event if there is a touch-event
1903 // handler in the page, or some touch-event is already in the queue, even if
1904 // no point has been updated, to make sure that this event does not get
1905 // processed by the gesture recognizer before the events in the queue.
1906 if (host_->ShouldForwardTouchEvent())
1907 event->StopPropagation();
1910 if (host_->ShouldForwardTouchEvent())
1911 host_->ForwardTouchEventWithLatencyInfo(touch_event_, *event->latency());
1912 UpdateWebTouchEventAfterDispatch(&touch_event_, point);
1916 void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
1917 TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnGestureEvent");
1918 if ((event->type() == ui::ET_GESTURE_PINCH_BEGIN ||
1919 event->type() == ui::ET_GESTURE_PINCH_UPDATE ||
1920 event->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
1921 event->SetHandled();
1925 if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
1928 RenderViewHostDelegate* delegate = NULL;
1929 if (host_->IsRenderView())
1930 delegate = RenderViewHost::From(host_)->GetDelegate();
1932 if (delegate && event->type() == ui::ET_GESTURE_BEGIN &&
1933 event->details().touch_points() == 1) {
1934 delegate->HandleGestureBegin();
1937 blink::WebGestureEvent gesture = MakeWebGestureEvent(event);
1938 if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
1939 // Webkit does not stop a fling-scroll on tap-down. So explicitly send an
1940 // event to stop any in-progress flings.
1941 blink::WebGestureEvent fling_cancel = gesture;
1942 fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
1943 fling_cancel.sourceDevice = blink::WebGestureEvent::Touchscreen;
1944 host_->ForwardGestureEvent(fling_cancel);
1947 if (gesture.type != blink::WebInputEvent::Undefined) {
1948 host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
1950 if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
1951 event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
1952 event->type() == ui::ET_GESTURE_SCROLL_END) {
1953 RecordAction(base::UserMetricsAction("TouchscreenScroll"));
1954 } else if (event->type() == ui::ET_SCROLL_FLING_START) {
1955 RecordAction(base::UserMetricsAction("TouchscreenScrollFling"));
1959 if (delegate && event->type() == ui::ET_GESTURE_END &&
1960 event->details().touch_points() == 1) {
1961 delegate->HandleGestureEnd();
1964 // If a gesture is not processed by the webpage, then WebKit processes it
1965 // (e.g. generates synthetic mouse events).
1966 event->SetHandled();
1969 ////////////////////////////////////////////////////////////////////////////////
1970 // RenderWidgetHostViewAura, aura::client::ActivationDelegate implementation:
1972 bool RenderWidgetHostViewAura::ShouldActivate() const {
1973 aura::WindowTreeHost* host = window_->GetHost();
1976 const ui::Event* event = host->dispatcher()->current_event();
1979 return is_fullscreen_;
1982 ////////////////////////////////////////////////////////////////////////////////
1983 // RenderWidgetHostViewAura,
1984 // aura::client::ActivationChangeObserver implementation:
1986 void RenderWidgetHostViewAura::OnWindowActivated(aura::Window* gained_active,
1987 aura::Window* lost_active) {
1988 DCHECK(window_ == gained_active || window_ == lost_active);
1989 if (window_ == gained_active) {
1990 const ui::Event* event = window_->GetHost()->dispatcher()->current_event();
1991 if (event && PointerEventActivates(*event))
1992 host_->OnPointerEventActivate();
1996 ////////////////////////////////////////////////////////////////////////////////
1997 // RenderWidgetHostViewAura, aura::client::CursorClientObserver implementation:
1999 void RenderWidgetHostViewAura::OnCursorVisibilityChanged(bool is_visible) {
2000 NotifyRendererOfCursorVisibilityState(is_visible);
2003 ////////////////////////////////////////////////////////////////////////////////
2004 // RenderWidgetHostViewAura, aura::client::FocusChangeObserver implementation:
2006 void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
2007 aura::Window* lost_focus) {
2008 DCHECK(window_ == gained_focus || window_ == lost_focus);
2009 if (window_ == gained_focus) {
2010 // We need to honor input bypass if the associated tab is does not want
2011 // input. This gives the current focused window a chance to be the text
2012 // input client and handle events.
2013 if (host_->ignore_input_events())
2017 host_->SetActive(true);
2019 ui::InputMethod* input_method = GetInputMethod();
2021 // Ask the system-wide IME to send all TextInputClient messages to |this|
2023 input_method->SetFocusedTextInputClient(this);
2024 host_->SetInputMethodActive(input_method->IsActive());
2026 // Often the application can set focus to the view in response to a key
2027 // down. However the following char event shouldn't be sent to the web
2029 host_->SuppressNextCharEvents();
2031 host_->SetInputMethodActive(false);
2034 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
2036 manager->OnWindowFocused();
2037 } else if (window_ == lost_focus) {
2038 host_->SetActive(false);
2041 DetachFromInputMethod();
2042 host_->SetInputMethodActive(false);
2044 if (touch_editing_client_)
2045 touch_editing_client_->EndTouchEditing(false);
2047 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
2049 manager->OnWindowBlurred();
2051 // If we lose the focus while fullscreen, close the window; Pepper Flash
2052 // won't do it for us (unlike NPAPI Flash). However, we do not close the
2053 // window if we lose the focus to a window on another display.
2054 gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
2055 bool focusing_other_display =
2056 gained_focus && screen->GetNumDisplays() > 1 &&
2057 (screen->GetDisplayNearestWindow(window_).id() !=
2058 screen->GetDisplayNearestWindow(gained_focus).id());
2059 if (is_fullscreen_ && !in_shutdown_ && !focusing_other_display) {
2061 // On Windows, if we are switching to a non Aura Window on a different
2062 // screen we should not close the fullscreen window.
2063 if (!gained_focus) {
2065 ::GetCursorPos(&point);
2066 if (screen->GetDisplayNearestWindow(window_).id() !=
2067 screen->GetDisplayNearestPoint(gfx::Point(point)).id())
2071 in_shutdown_ = true;
2077 ////////////////////////////////////////////////////////////////////////////////
2078 // RenderWidgetHostViewAura, aura::WindowTreeHostObserver implementation:
2080 void RenderWidgetHostViewAura::OnHostMoved(const aura::WindowTreeHost* host,
2081 const gfx::Point& new_origin) {
2082 TRACE_EVENT1("ui", "RenderWidgetHostViewAura::OnHostMoved",
2083 "new_origin", new_origin.ToString());
2085 UpdateScreenInfo(window_);
2088 ////////////////////////////////////////////////////////////////////////////////
2089 // RenderWidgetHostViewAura, private:
2091 RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
2092 if (touch_editing_client_)
2093 touch_editing_client_->OnViewDestroyed();
2095 delegated_frame_host_.reset();
2096 window_observer_.reset();
2097 if (window_->GetHost())
2098 window_->GetHost()->RemoveObserver(this);
2100 if (popup_parent_host_view_) {
2101 DCHECK(popup_parent_host_view_->popup_child_host_view_ == NULL ||
2102 popup_parent_host_view_->popup_child_host_view_ == this);
2103 popup_parent_host_view_->popup_child_host_view_ = NULL;
2105 if (popup_child_host_view_) {
2106 DCHECK(popup_child_host_view_->popup_parent_host_view_ == NULL ||
2107 popup_child_host_view_->popup_parent_host_view_ == this);
2108 popup_child_host_view_->popup_parent_host_view_ = NULL;
2110 event_filter_for_popup_exit_.reset();
2111 aura::client::SetTooltipText(window_, NULL);
2112 gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
2114 // This call is usually no-op since |this| object is already removed from the
2115 // Aura root window and we don't have a way to get an input method object
2116 // associated with the window, but just in case.
2117 DetachFromInputMethod();
2120 legacy_render_widget_host_HWND_.reset(NULL);
2124 void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
2125 const gfx::Point screen_point =
2126 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
2127 aura::Window* root_window = window_->GetRootWindow();
2131 gfx::Point root_window_point = screen_point;
2132 aura::client::ScreenPositionClient* screen_position_client =
2133 aura::client::GetScreenPositionClient(root_window);
2134 if (screen_position_client) {
2135 screen_position_client->ConvertPointFromScreen(
2136 root_window, &root_window_point);
2139 if (root_window->GetEventHandlerForPoint(root_window_point) != window_)
2142 gfx::NativeCursor cursor = current_cursor_.GetNativeCursor();
2143 // Do not show loading cursor when the cursor is currently hidden.
2144 if (is_loading_ && cursor != ui::kCursorNone)
2145 cursor = ui::kCursorPointer;
2147 aura::client::CursorClient* cursor_client =
2148 aura::client::GetCursorClient(root_window);
2149 if (cursor_client) {
2150 cursor_client->SetCursor(cursor);
2154 ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
2155 aura::Window* root_window = window_->GetRootWindow();
2158 return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
2161 bool RenderWidgetHostViewAura::NeedsInputGrab() {
2162 return popup_type_ == blink::WebPopupTypeSelect;
2165 void RenderWidgetHostViewAura::FinishImeCompositionSession() {
2166 if (!has_composition_text_)
2169 host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
2172 ImeCancelComposition();
2175 void RenderWidgetHostViewAura::ModifyEventMovementAndCoords(
2176 blink::WebMouseEvent* event) {
2177 // If the mouse has just entered, we must report zero movementX/Y. Hence we
2178 // reset any global_mouse_position set previously.
2179 if (event->type == blink::WebInputEvent::MouseEnter ||
2180 event->type == blink::WebInputEvent::MouseLeave)
2181 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2183 // Movement is computed by taking the difference of the new cursor position
2184 // and the previous. Under mouse lock the cursor will be warped back to the
2185 // center so that we are not limited by clipping boundaries.
2186 // We do not measure movement as the delta from cursor to center because
2187 // we may receive more mouse movement events before our warp has taken
2189 event->movementX = event->globalX - global_mouse_position_.x();
2190 event->movementY = event->globalY - global_mouse_position_.y();
2192 global_mouse_position_.SetPoint(event->globalX, event->globalY);
2194 // Under mouse lock, coordinates of mouse are locked to what they were when
2195 // mouse lock was entered.
2196 if (mouse_locked_) {
2197 event->x = unlocked_mouse_position_.x();
2198 event->y = unlocked_mouse_position_.y();
2199 event->windowX = unlocked_mouse_position_.x();
2200 event->windowY = unlocked_mouse_position_.y();
2201 event->globalX = unlocked_global_mouse_position_.x();
2202 event->globalY = unlocked_global_mouse_position_.y();
2204 unlocked_mouse_position_.SetPoint(event->windowX, event->windowY);
2205 unlocked_global_mouse_position_.SetPoint(event->globalX, event->globalY);
2209 void RenderWidgetHostViewAura::NotifyRendererOfCursorVisibilityState(
2211 if (host_->is_hidden() ||
2212 (cursor_visibility_state_in_renderer_ == VISIBLE && is_visible) ||
2213 (cursor_visibility_state_in_renderer_ == NOT_VISIBLE && !is_visible))
2216 cursor_visibility_state_in_renderer_ = is_visible ? VISIBLE : NOT_VISIBLE;
2217 host_->SendCursorVisibilityState(is_visible);
2220 void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
2221 const gfx::Rect& rect,
2222 const gfx::Rect& clip) {
2223 if (!clip.IsEmpty()) {
2224 gfx::Rect to_paint = gfx::SubtractRects(rect, clip);
2225 if (!to_paint.IsEmpty())
2226 window_->SchedulePaintInRect(to_paint);
2228 window_->SchedulePaintInRect(rect);
2232 bool RenderWidgetHostViewAura::ShouldMoveToCenter() {
2233 gfx::Rect rect = window_->bounds();
2234 rect = ConvertRectToScreen(rect);
2235 int border_x = rect.width() * kMouseLockBorderPercentage / 100;
2236 int border_y = rect.height() * kMouseLockBorderPercentage / 100;
2238 return global_mouse_position_.x() < rect.x() + border_x ||
2239 global_mouse_position_.x() > rect.right() - border_x ||
2240 global_mouse_position_.y() < rect.y() + border_y ||
2241 global_mouse_position_.y() > rect.bottom() - border_y;
2244 void RenderWidgetHostViewAura::AddedToRootWindow() {
2245 window_->GetHost()->AddObserver(this);
2246 UpdateScreenInfo(window_);
2248 aura::client::CursorClient* cursor_client =
2249 aura::client::GetCursorClient(window_->GetRootWindow());
2250 if (cursor_client) {
2251 cursor_client->AddObserver(this);
2252 NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
2255 ui::InputMethod* input_method = GetInputMethod();
2257 input_method->SetFocusedTextInputClient(this);
2261 // The parent may have changed here. Ensure that the legacy window is
2262 // reparented accordingly.
2263 if (legacy_render_widget_host_HWND_)
2264 legacy_render_widget_host_HWND_->UpdateParent(
2265 reinterpret_cast<HWND>(GetNativeViewId()));
2268 delegated_frame_host_->AddedToWindow();
2271 void RenderWidgetHostViewAura::RemovingFromRootWindow() {
2272 aura::client::CursorClient* cursor_client =
2273 aura::client::GetCursorClient(window_->GetRootWindow());
2275 cursor_client->RemoveObserver(this);
2277 DetachFromInputMethod();
2279 window_->GetHost()->RemoveObserver(this);
2280 delegated_frame_host_->RemovingFromWindow();
2283 // Update the legacy window's parent temporarily to the desktop window. It
2284 // will eventually get reparented to the right root.
2285 if (legacy_render_widget_host_HWND_)
2286 legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
2290 void RenderWidgetHostViewAura::DetachFromInputMethod() {
2291 ui::InputMethod* input_method = GetInputMethod();
2292 if (input_method && input_method->GetTextInputClient() == this)
2293 input_method->SetFocusedTextInputClient(NULL);
2296 void RenderWidgetHostViewAura::ForwardKeyboardEvent(
2297 const NativeWebKeyboardEvent& event) {
2298 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
2299 ui::TextEditKeyBindingsDelegateAuraLinux* keybinding_delegate =
2300 ui::GetTextEditKeyBindingsDelegate();
2301 std::vector<ui::TextEditCommandAuraLinux> commands;
2302 if (!event.skip_in_browser &&
2303 keybinding_delegate &&
2305 keybinding_delegate->MatchEvent(*event.os_event, &commands)) {
2306 // Transform from ui/ types to content/ types.
2307 EditCommands edit_commands;
2308 for (std::vector<ui::TextEditCommandAuraLinux>::const_iterator it =
2309 commands.begin(); it != commands.end(); ++it) {
2310 edit_commands.push_back(EditCommand(it->GetCommandString(),
2313 host_->Send(new InputMsg_SetEditCommandsForNextKeyEvent(
2314 host_->GetRoutingID(), edit_commands));
2315 NativeWebKeyboardEvent copy_event(event);
2316 copy_event.match_edit_command = true;
2317 host_->ForwardKeyboardEvent(copy_event);
2322 host_->ForwardKeyboardEvent(event);
2325 SkBitmap::Config RenderWidgetHostViewAura::PreferredReadbackFormat() {
2326 return SkBitmap::kARGB_8888_Config;
2329 ////////////////////////////////////////////////////////////////////////////////
2330 // DelegatedFrameHost, public:
2332 ui::Compositor* RenderWidgetHostViewAura::GetCompositor() const {
2333 aura::WindowTreeHost* host = window_->GetHost();
2334 return host ? host->compositor() : NULL;
2337 ui::Layer* RenderWidgetHostViewAura::GetLayer() {
2338 return window_->layer();
2341 RenderWidgetHostImpl* RenderWidgetHostViewAura::GetHost() {
2345 void RenderWidgetHostViewAura::SchedulePaintInRect(
2346 const gfx::Rect& damage_rect_in_dip) {
2347 window_->SchedulePaintInRect(damage_rect_in_dip);
2350 bool RenderWidgetHostViewAura::IsVisible() {
2354 gfx::Size RenderWidgetHostViewAura::DesiredFrameSize() {
2355 return window_->bounds().size();
2358 float RenderWidgetHostViewAura::CurrentDeviceScaleFactor() {
2359 return current_device_scale_factor_;
2362 gfx::Size RenderWidgetHostViewAura::ConvertViewSizeToPixel(
2363 const gfx::Size& size) {
2364 return content::ConvertViewSizeToPixel(this, size);
2367 scoped_ptr<ResizeLock> RenderWidgetHostViewAura::CreateResizeLock(
2368 bool defer_compositor_lock) {
2369 gfx::Size desired_size = window_->bounds().size();
2370 return scoped_ptr<ResizeLock>(new CompositorResizeLock(
2373 defer_compositor_lock,
2374 base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs)));
2375 ResizeLock* lock = NULL;
2376 return scoped_ptr<ResizeLock>(lock);
2379 DelegatedFrameHost* RenderWidgetHostViewAura::GetDelegatedFrameHost() const {
2380 return delegated_frame_host_.get();
2383 ////////////////////////////////////////////////////////////////////////////////
2384 // RenderWidgetHostViewBase, public:
2387 void RenderWidgetHostViewBase::GetDefaultScreenInfo(WebScreenInfo* results) {
2388 GetScreenInfoForWindow(results, NULL);
2391 } // namespace content