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/web_contents/web_contents_view_aura.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/browser/frame_host/interstitial_page_impl.h"
12 #include "content/browser/frame_host/navigation_entry_impl.h"
13 #include "content/browser/renderer_host/dip_util.h"
14 #include "content/browser/renderer_host/overscroll_controller.h"
15 #include "content/browser/renderer_host/render_view_host_factory.h"
16 #include "content/browser/renderer_host/render_view_host_impl.h"
17 #include "content/browser/renderer_host/render_widget_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
19 #include "content/browser/web_contents/aura/image_window_delegate.h"
20 #include "content/browser/web_contents/aura/shadow_layer_delegate.h"
21 #include "content/browser/web_contents/aura/window_slider.h"
22 #include "content/browser/web_contents/touch_editable_impl_aura.h"
23 #include "content/browser/web_contents/web_contents_impl.h"
24 #include "content/public/browser/notification_observer.h"
25 #include "content/public/browser/notification_registrar.h"
26 #include "content/public/browser/notification_source.h"
27 #include "content/public/browser/notification_types.h"
28 #include "content/public/browser/overscroll_configuration.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/render_widget_host.h"
31 #include "content/public/browser/render_widget_host_view.h"
32 #include "content/public/browser/web_contents_delegate.h"
33 #include "content/public/browser/web_contents_observer.h"
34 #include "content/public/browser/web_contents_view_delegate.h"
35 #include "content/public/browser/web_drag_dest_delegate.h"
36 #include "content/public/common/content_switches.h"
37 #include "content/public/common/drop_data.h"
38 #include "net/base/net_util.h"
39 #include "third_party/WebKit/public/web/WebInputEvent.h"
40 #include "ui/aura/client/aura_constants.h"
41 #include "ui/aura/client/drag_drop_client.h"
42 #include "ui/aura/client/drag_drop_delegate.h"
43 #include "ui/aura/client/window_tree_client.h"
44 #include "ui/aura/env.h"
45 #include "ui/aura/root_window.h"
46 #include "ui/aura/root_window_observer.h"
47 #include "ui/aura/window.h"
48 #include "ui/aura/window_observer.h"
49 #include "ui/base/clipboard/clipboard.h"
50 #include "ui/base/clipboard/custom_data_helper.h"
51 #include "ui/base/dragdrop/drag_drop_types.h"
52 #include "ui/base/dragdrop/drag_utils.h"
53 #include "ui/base/dragdrop/drop_target_event.h"
54 #include "ui/base/dragdrop/os_exchange_data.h"
55 #include "ui/base/hit_test.h"
56 #include "ui/compositor/layer.h"
57 #include "ui/compositor/scoped_layer_animation_settings.h"
58 #include "ui/events/event.h"
59 #include "ui/events/event_utils.h"
60 #include "ui/gfx/canvas.h"
61 #include "ui/gfx/image/image.h"
62 #include "ui/gfx/image/image_png_rep.h"
63 #include "ui/gfx/image/image_skia.h"
64 #include "ui/gfx/screen.h"
67 WebContentsViewPort* CreateWebContentsView(
68 WebContentsImpl* web_contents,
69 WebContentsViewDelegate* delegate,
70 RenderViewHostDelegateView** render_view_host_delegate_view) {
71 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
72 *render_view_host_delegate_view = rv;
78 bool IsScrollEndEffectEnabled() {
79 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
80 switches::kScrollEndEffect) == "1";
83 bool ShouldNavigateForward(const NavigationController& controller,
84 OverscrollMode mode) {
85 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
86 controller.CanGoForward();
89 bool ShouldNavigateBack(const NavigationController& controller,
90 OverscrollMode mode) {
91 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
92 controller.CanGoBack();
95 RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
96 RenderWidgetHostView* view) {
97 if (!view || RenderViewHostFactory::has_factory())
98 return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests.
99 RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
100 view->GetRenderWidgetHost()->GetProcess());
101 if (process->IsGuest())
103 return static_cast<RenderWidgetHostViewAura*>(view);
106 // The window delegate for the overscroll window. This redirects trackpad events
107 // to the web-contents window. The delegate destroys itself when the window is
109 class OverscrollWindowDelegate : public ImageWindowDelegate {
111 OverscrollWindowDelegate(WebContentsImpl* web_contents,
112 OverscrollMode overscroll_mode)
113 : web_contents_(web_contents),
114 forward_events_(true) {
115 const NavigationControllerImpl& controller = web_contents->GetController();
116 const NavigationEntryImpl* entry = NULL;
117 if (ShouldNavigateForward(controller, overscroll_mode)) {
118 entry = NavigationEntryImpl::FromNavigationEntry(
119 controller.GetEntryAtOffset(1));
120 } else if (ShouldNavigateBack(controller, overscroll_mode)) {
121 entry = NavigationEntryImpl::FromNavigationEntry(
122 controller.GetEntryAtOffset(-1));
126 if (entry && entry->screenshot().get()) {
127 std::vector<gfx::ImagePNGRep> image_reps;
128 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
130 ui::GetScaleFactorForNativeView(web_contents_window()))));
131 image = gfx::Image(image_reps);
136 void stop_forwarding_events() { forward_events_ = false; }
139 virtual ~OverscrollWindowDelegate() {}
141 aura::Window* web_contents_window() {
142 return web_contents_->GetView()->GetContentNativeView();
145 // Overridden from ui::EventHandler.
146 virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
147 if (forward_events_ && web_contents_window())
148 web_contents_window()->delegate()->OnScrollEvent(event);
151 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
152 if (forward_events_ && web_contents_window())
153 web_contents_window()->delegate()->OnGestureEvent(event);
156 WebContents* web_contents_;
158 // The window is displayed both during the gesture, and after the gesture
159 // while the navigation is in progress. During the gesture, it is necessary to
160 // forward input events to the content page (e.g. when the overscroll window
161 // slides under the cursor and starts receiving scroll events). However, once
162 // the gesture is complete, and the window is being displayed as an overlay
163 // window during navigation, events should not be forwarded anymore.
164 bool forward_events_;
166 DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
169 // Listens to all mouse drag events during a drag and drop and sends them to
171 class WebDragSourceAura : public base::MessageLoopForUI::Observer,
172 public NotificationObserver {
174 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
176 contents_(contents) {
177 base::MessageLoopForUI::current()->AddObserver(this);
179 NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
180 Source<WebContents>(contents));
183 virtual ~WebDragSourceAura() {
184 base::MessageLoopForUI::current()->RemoveObserver(this);
187 // MessageLoop::Observer implementation:
188 virtual base::EventStatus WillProcessEvent(
189 const base::NativeEvent& event) OVERRIDE {
190 return base::EVENT_CONTINUE;
192 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
195 ui::EventType type = ui::EventTypeFromNative(event);
196 RenderViewHost* rvh = NULL;
198 case ui::ET_MOUSE_DRAGGED:
199 rvh = contents_->GetRenderViewHost();
201 gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event);
202 gfx::Point screen_loc = ConvertViewPointToDIP(rvh->GetView(),
203 screen_loc_in_pixel);
204 gfx::Point client_loc = screen_loc;
205 aura::Window* window = rvh->GetView()->GetNativeView();
206 aura::Window::ConvertPointToTarget(window->GetRootWindow(),
207 window, &client_loc);
208 contents_->DragSourceMovedTo(client_loc.x(), client_loc.y(),
209 screen_loc.x(), screen_loc.y());
217 virtual void Observe(int type,
218 const NotificationSource& source,
219 const NotificationDetails& details) OVERRIDE {
220 if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
223 // Cancel the drag if it is still in progress.
224 aura::client::DragDropClient* dnd_client =
225 aura::client::GetDragDropClient(window_->GetRootWindow());
226 if (dnd_client && dnd_client->IsDragDropInProgress())
227 dnd_client->DragCancel();
233 aura::Window* window() const { return window_; }
236 aura::Window* window_;
237 WebContentsImpl* contents_;
238 NotificationRegistrar registrar_;
240 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
244 // Fill out the OSExchangeData with a file contents, synthesizing a name if
246 void PrepareDragForFileContents(const DropData& drop_data,
247 ui::OSExchangeData::Provider* provider) {
248 base::FilePath file_name(drop_data.file_description_filename);
249 // Images without ALT text will only have a file extension so we need to
250 // synthesize one from the provided extension and URL.
251 if (file_name.BaseName().RemoveExtension().empty()) {
252 const string16 extension = file_name.Extension();
253 // Retrieve the name from the URL.
254 file_name = base::FilePath(net::GetSuggestedFilename(
255 drop_data.url, "", "", "", "", "")).ReplaceExtension(extension);
257 provider->SetFileContents(file_name, drop_data.file_contents);
261 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
262 void PrepareDragData(const DropData& drop_data,
263 ui::OSExchangeData::Provider* provider) {
265 // We set the file contents before the URL because the URL also sets file
266 // contents (to a .URL shortcut). We want to prefer file content data over
267 // a shortcut so we add it first.
268 if (!drop_data.file_contents.empty())
269 PrepareDragForFileContents(drop_data, provider);
271 if (!drop_data.text.string().empty())
272 provider->SetString(drop_data.text.string());
273 if (drop_data.url.is_valid())
274 provider->SetURL(drop_data.url, drop_data.url_title);
275 if (!drop_data.html.string().empty())
276 provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
277 if (!drop_data.filenames.empty()) {
278 std::vector<ui::OSExchangeData::FileInfo> filenames;
279 for (std::vector<DropData::FileInfo>::const_iterator it =
280 drop_data.filenames.begin();
281 it != drop_data.filenames.end(); ++it) {
283 ui::OSExchangeData::FileInfo(
284 base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->path)),
285 base::FilePath::FromUTF8Unsafe(UTF16ToUTF8(it->display_name))));
287 provider->SetFilenames(filenames);
289 if (!drop_data.custom_data.empty()) {
291 ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
292 provider->SetPickledData(ui::Clipboard::GetWebCustomDataFormatType(),
297 // Utility to fill a DropData object from ui::OSExchangeData.
298 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
300 data.GetString(&plain_text);
301 if (!plain_text.empty())
302 drop_data->text = base::NullableString16(plain_text, false);
306 data.GetURLAndTitle(&url, &url_title);
307 if (url.is_valid()) {
308 drop_data->url = url;
309 drop_data->url_title = url_title;
314 data.GetHtml(&html, &html_base_url);
316 drop_data->html = base::NullableString16(html, false);
317 if (html_base_url.is_valid())
318 drop_data->html_base_url = html_base_url;
320 std::vector<ui::OSExchangeData::FileInfo> files;
321 if (data.GetFilenames(&files) && !files.empty()) {
322 for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator
323 it = files.begin(); it != files.end(); ++it) {
324 drop_data->filenames.push_back(
326 UTF8ToUTF16(it->path.AsUTF8Unsafe()),
327 UTF8ToUTF16(it->display_name.AsUTF8Unsafe())));
332 if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
333 ui::ReadCustomDataIntoMap(
334 pickle.data(), pickle.size(), &drop_data->custom_data);
337 // Utilities to convert between WebKit::WebDragOperationsMask and
338 // ui::DragDropTypes.
339 int ConvertFromWeb(WebKit::WebDragOperationsMask ops) {
340 int drag_op = ui::DragDropTypes::DRAG_NONE;
341 if (ops & WebKit::WebDragOperationCopy)
342 drag_op |= ui::DragDropTypes::DRAG_COPY;
343 if (ops & WebKit::WebDragOperationMove)
344 drag_op |= ui::DragDropTypes::DRAG_MOVE;
345 if (ops & WebKit::WebDragOperationLink)
346 drag_op |= ui::DragDropTypes::DRAG_LINK;
350 WebKit::WebDragOperationsMask ConvertToWeb(int drag_op) {
351 int web_drag_op = WebKit::WebDragOperationNone;
352 if (drag_op & ui::DragDropTypes::DRAG_COPY)
353 web_drag_op |= WebKit::WebDragOperationCopy;
354 if (drag_op & ui::DragDropTypes::DRAG_MOVE)
355 web_drag_op |= WebKit::WebDragOperationMove;
356 if (drag_op & ui::DragDropTypes::DRAG_LINK)
357 web_drag_op |= WebKit::WebDragOperationLink;
358 return (WebKit::WebDragOperationsMask) web_drag_op;
361 int ConvertAuraEventFlagsToWebInputEventModifiers(int aura_event_flags) {
362 int web_input_event_modifiers = 0;
363 if (aura_event_flags & ui::EF_SHIFT_DOWN)
364 web_input_event_modifiers |= WebKit::WebInputEvent::ShiftKey;
365 if (aura_event_flags & ui::EF_CONTROL_DOWN)
366 web_input_event_modifiers |= WebKit::WebInputEvent::ControlKey;
367 if (aura_event_flags & ui::EF_ALT_DOWN)
368 web_input_event_modifiers |= WebKit::WebInputEvent::AltKey;
369 if (aura_event_flags & ui::EF_COMMAND_DOWN)
370 web_input_event_modifiers |= WebKit::WebInputEvent::MetaKey;
371 return web_input_event_modifiers;
374 // A LayerDelegate that paints an image for the layer.
375 class ImageLayerDelegate : public ui::LayerDelegate {
377 ImageLayerDelegate() {}
379 virtual ~ImageLayerDelegate() {}
381 void SetImage(const gfx::Image& image) {
383 image_size_ = image.AsImageSkia().size();
385 const gfx::Image& image() const { return image_; }
388 // Overridden from ui::LayerDelegate:
389 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
390 if (image_.IsEmpty()) {
391 canvas->DrawColor(SK_ColorGRAY);
393 SkISize size = canvas->sk_canvas()->getDeviceSize();
394 if (size.width() != image_size_.width() ||
395 size.height() != image_size_.height()) {
396 canvas->DrawColor(SK_ColorWHITE);
398 canvas->DrawImageInt(image_.AsImageSkia(), 0, 0);
402 // Called when the layer's device scale factor has changed.
403 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
406 // Invoked prior to the bounds changing. The returned closured is run after
407 // the bounds change.
408 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
409 return base::Closure();
413 gfx::Size image_size_;
415 DISALLOW_COPY_AND_ASSIGN(ImageLayerDelegate);
420 // When a history navigation is triggered at the end of an overscroll
421 // navigation, it is necessary to show the history-screenshot until the page is
422 // done navigating and painting. This class accomplishes this by showing the
423 // screenshot window on top of the page until the page has completed loading and
425 class OverscrollNavigationOverlay :
426 public RenderWidgetHostViewAura::PaintObserver,
427 public WindowSlider::Delegate {
429 explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents)
430 : web_contents_(web_contents),
431 image_delegate_(NULL),
433 loading_complete_(false),
434 received_paint_update_(false),
435 compositor_updated_(false),
436 slide_direction_(SLIDE_UNKNOWN),
437 need_paint_update_(true) {
440 virtual ~OverscrollNavigationOverlay() {
442 view_->set_paint_observer(NULL);
445 bool has_window() const { return !!window_.get(); }
447 void StartObservingView(RenderWidgetHostViewAura* view) {
449 view_->set_paint_observer(NULL);
451 loading_complete_ = false;
452 received_paint_update_ = false;
453 compositor_updated_ = false;
456 view_->set_paint_observer(this);
458 // Make sure the overlay window is on top.
459 if (window_.get() && window_->parent())
460 window_->parent()->StackChildAtTop(window_.get());
463 void SetOverlayWindow(scoped_ptr<aura::Window> window,
464 ImageWindowDelegate* delegate) {
465 window_ = window.Pass();
466 if (window_.get() && window_->parent())
467 window_->parent()->StackChildAtTop(window_.get());
468 image_delegate_ = delegate;
470 if (window_.get() && delegate->has_image()) {
471 window_slider_.reset(new WindowSlider(this,
474 slide_direction_ = SLIDE_UNKNOWN;
476 window_slider_.reset();
480 void SetupForTesting() {
481 need_paint_update_ = false;
485 // Stop observing the page if the page-load has completed and the page has
486 // been painted, and a window-slide isn't in progress.
487 void StopObservingIfDone() {
488 // If there is a screenshot displayed in the overlay window, then wait for
489 // the navigated page to complete loading and some paint update before
490 // hiding the overlay.
491 // If there is no screenshot in the overlay window, then hide this view
492 // as soon as there is any new painting notification.
493 if ((need_paint_update_ && !received_paint_update_) ||
494 (image_delegate_->has_image() && !loading_complete_)) {
498 // If a slide is in progress, then do not destroy the window or the slide.
499 if (window_slider_.get() && window_slider_->IsSlideInProgress())
502 window_slider_.reset();
504 image_delegate_ = NULL;
506 view_->set_paint_observer(NULL);
511 // Creates a layer to be used for window-slide. |offset| is the offset of the
512 // NavigationEntry for the screenshot image to display.
513 ui::Layer* CreateSlideLayer(int offset) {
514 const NavigationControllerImpl& controller = web_contents_->GetController();
515 const NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
516 controller.GetEntryAtOffset(offset));
519 if (entry && entry->screenshot().get()) {
520 std::vector<gfx::ImagePNGRep> image_reps;
521 image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
523 ui::GetScaleFactorForNativeView(window_.get()))));
524 image = gfx::Image(image_reps);
526 layer_delegate_.SetImage(image);
528 ui::Layer* layer = new ui::Layer(ui::LAYER_TEXTURED);
529 layer->set_delegate(&layer_delegate_);
533 // Overridden from WindowSlider::Delegate:
534 virtual ui::Layer* CreateBackLayer() OVERRIDE {
535 if (!web_contents_->GetController().CanGoBack())
537 slide_direction_ = SLIDE_BACK;
538 return CreateSlideLayer(-1);
541 virtual ui::Layer* CreateFrontLayer() OVERRIDE {
542 if (!web_contents_->GetController().CanGoForward())
544 slide_direction_ = SLIDE_FRONT;
545 return CreateSlideLayer(1);
548 virtual void OnWindowSlideComplete() OVERRIDE {
549 if (slide_direction_ == SLIDE_UNKNOWN) {
550 window_slider_.reset();
551 StopObservingIfDone();
555 // Change the image used for the overlay window.
556 image_delegate_->SetImage(layer_delegate_.image());
557 window_->layer()->SetTransform(gfx::Transform());
558 window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
560 SlideDirection direction = slide_direction_;
561 slide_direction_ = SLIDE_UNKNOWN;
563 // Reset state and wait for the new navigation page to complete
565 StartObservingView(ToRenderWidgetHostViewAura(
566 web_contents_->GetRenderWidgetHostView()));
568 // Perform the navigation.
569 if (direction == SLIDE_BACK)
570 web_contents_->GetController().GoBack();
571 else if (direction == SLIDE_FRONT)
572 web_contents_->GetController().GoForward();
577 virtual void OnWindowSlideAborted() OVERRIDE {
578 StopObservingIfDone();
581 virtual void OnWindowSliderDestroyed() OVERRIDE {
582 // The slider has just been destroyed. Release the ownership.
583 WindowSlider* slider ALLOW_UNUSED = window_slider_.release();
584 StopObservingIfDone();
587 // Overridden from RenderWidgetHostViewAura::PaintObserver:
588 virtual void OnPaintComplete() OVERRIDE {
589 received_paint_update_ = true;
590 StopObservingIfDone();
593 virtual void OnCompositingComplete() OVERRIDE {
594 received_paint_update_ = compositor_updated_;
595 StopObservingIfDone();
598 virtual void OnUpdateCompositorContent() OVERRIDE {
599 compositor_updated_ = true;
602 virtual void OnPageLoadComplete() OVERRIDE {
603 loading_complete_ = true;
604 StopObservingIfDone();
607 virtual void OnViewDestroyed() OVERRIDE {
609 view_->set_paint_observer(NULL);
613 // The WebContents which is being navigated.
614 WebContentsImpl* web_contents_;
616 scoped_ptr<aura::Window> window_;
618 // This is the WindowDelegate of |window_|. The delegate manages its own
619 // lifetime (destroys itself when |window_| is destroyed).
620 ImageWindowDelegate* image_delegate_;
622 RenderWidgetHostViewAura* view_;
623 bool loading_complete_;
624 bool received_paint_update_;
625 bool compositor_updated_;
627 enum SlideDirection {
633 // The |WindowSlider| that allows sliding history layers while the page is
635 scoped_ptr<WindowSlider> window_slider_;
637 // The direction of the in-progress slide (if any).
638 SlideDirection slide_direction_;
640 // The LayerDelegate used for the back/front layers during a slide.
641 ImageLayerDelegate layer_delegate_;
643 // During tests, the aura windows don't get any paint updates. So the overlay
644 // container keeps waiting for a paint update it never receives, causing a
645 // timeout. So during tests, disable the wait for paint updates.
646 bool need_paint_update_;
648 DISALLOW_COPY_AND_ASSIGN(OverscrollNavigationOverlay);
651 class WebContentsViewAura::WindowObserver
652 : public aura::WindowObserver, public aura::RootWindowObserver {
654 explicit WindowObserver(WebContentsViewAura* view)
657 view_->window_->AddObserver(this);
660 virtual ~WindowObserver() {
661 view_->window_->RemoveObserver(this);
662 if (view_->window_->GetDispatcher())
663 view_->window_->GetDispatcher()->RemoveRootWindowObserver(this);
665 parent_->RemoveObserver(this);
669 const aura::Window::Windows& children = parent_->children();
670 for (size_t i = 0; i < children.size(); ++i)
671 children[i]->RemoveObserver(this);
676 // Overridden from aura::WindowObserver:
678 // Constrained windows are added as children of the parent's parent's view
679 // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
680 // so that it can update the plugins' cutout rects accordingly.
681 // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
682 // going to be deprecated in a year, this is ok for now. The test for this is
683 // PrintPreviewTest.WindowedNPAPIPluginHidden.
684 virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
685 if (new_window->parent() != parent_)
688 new_window->AddObserver(this);
689 UpdateConstrainedWindows(NULL);
692 virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
693 if (window->parent() == parent_ && window != view_->window_) {
694 window->RemoveObserver(this);
695 UpdateConstrainedWindows(window);
699 virtual void OnWindowVisibilityChanged(aura::Window* window,
700 bool visible) OVERRIDE {
701 if (window->parent() == parent_ && window != view_->window_)
702 UpdateConstrainedWindows(NULL);
706 virtual void OnWindowParentChanged(aura::Window* window,
707 aura::Window* parent) OVERRIDE {
708 if (window != view_->window_)
711 parent_->RemoveObserver(this);
715 const aura::Window::Windows& children = parent_->children();
716 for (size_t i = 0; i < children.size(); ++i)
717 children[i]->RemoveObserver(this);
719 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
720 view_->web_contents_->GetRenderWidgetHostView());
722 view->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
728 parent->AddObserver(this);
730 const aura::Window::Windows& children = parent_->children();
731 for (size_t i = 0; i < children.size(); ++i) {
732 if (children[i] != view_->window_)
733 children[i]->AddObserver(this);
739 virtual void OnWindowBoundsChanged(aura::Window* window,
740 const gfx::Rect& old_bounds,
741 const gfx::Rect& new_bounds) OVERRIDE {
742 if (window == parent_ || window == view_->window_) {
744 if (view_->touch_editable_)
745 view_->touch_editable_->UpdateEditingController();
748 UpdateConstrainedWindows(NULL);
753 virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
754 if (window == view_->window_)
755 window->GetDispatcher()->AddRootWindowObserver(this);
758 virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
759 if (window == view_->window_)
760 window->GetDispatcher()->RemoveRootWindowObserver(this);
763 // Overridden RootWindowObserver:
764 virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
765 const gfx::Point& new_origin) OVERRIDE {
766 // This is for the desktop case (i.e. Aura desktop).
771 void SendScreenRects() {
772 RenderWidgetHostImpl::From(view_->web_contents_->GetRenderViewHost())->
777 void UpdateConstrainedWindows(aura::Window* exclude) {
778 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
779 view_->web_contents_->GetRenderWidgetHostView());
783 std::vector<gfx::Rect> constrained_windows;
784 const aura::Window::Windows& children = parent_->children();
785 for (size_t i = 0; i < children.size(); ++i) {
786 if (children[i] != view_->window_ &&
787 children[i] != exclude &&
788 children[i]->IsVisible()) {
789 constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
793 view->UpdateConstrainedWindowRects(constrained_windows);
797 WebContentsViewAura* view_;
799 // We cache the old parent so that we can unregister when it's not the parent
801 aura::Window* parent_;
803 DISALLOW_COPY_AND_ASSIGN(WindowObserver);
806 ////////////////////////////////////////////////////////////////////////////////
807 // WebContentsViewAura, public:
809 WebContentsViewAura::WebContentsViewAura(
810 WebContentsImpl* web_contents,
811 WebContentsViewDelegate* delegate)
812 : web_contents_(web_contents),
814 current_drag_op_(WebKit::WebDragOperationNone),
815 drag_dest_delegate_(NULL),
816 current_rvh_for_drag_(NULL),
817 overscroll_change_brightness_(false),
818 current_overscroll_gesture_(OVERSCROLL_NONE),
819 completed_overscroll_gesture_(OVERSCROLL_NONE),
820 touch_editable_(TouchEditableImplAura::Create()) {
823 ////////////////////////////////////////////////////////////////////////////////
824 // WebContentsViewAura, private:
826 WebContentsViewAura::~WebContentsViewAura() {
830 window_observer_.reset();
832 // Window needs a valid delegate during its destructor, so we explicitly
837 void WebContentsViewAura::SetupOverlayWindowForTesting() {
838 if (navigation_overlay_)
839 navigation_overlay_->SetupForTesting();
842 void WebContentsViewAura::SetTouchEditableForTest(
843 TouchEditableImplAura* touch_editable) {
844 touch_editable_.reset(touch_editable);
845 AttachTouchEditableToRenderView();
848 void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
849 if (web_contents_->GetInterstitialPage())
850 web_contents_->GetInterstitialPage()->SetSize(size);
851 RenderWidgetHostView* rwhv =
852 web_contents_->GetRenderWidgetHostView();
857 void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
858 aura::Window* root_window = GetNativeView()->GetRootWindow();
859 gfx::Point screen_loc =
860 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
861 gfx::Point client_loc = screen_loc;
862 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
863 aura::Window* window = rvh->GetView()->GetNativeView();
864 aura::Window::ConvertPointToTarget(root_window, window, &client_loc);
867 web_contents_->DragSourceEndedAt(client_loc.x(), client_loc.y(),
868 screen_loc.x(), screen_loc.y(), ops);
871 void WebContentsViewAura::PrepareOverscrollWindow() {
872 // If there is an existing |overscroll_window_| which is in the middle of an
873 // animation, then destroying the window here causes the animation to be
874 // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
875 // callback, and that tries to reset |overscroll_window_| again, causing a
876 // double-free. So use a temporary variable here.
877 if (overscroll_window_) {
878 base::AutoReset<OverscrollMode> reset_state(¤t_overscroll_gesture_,
879 current_overscroll_gesture_);
880 scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
883 OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
885 current_overscroll_gesture_);
886 overscroll_window_.reset(new aura::Window(overscroll_delegate));
887 overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
888 overscroll_window_->SetTransparent(true);
889 overscroll_window_->Init(ui::LAYER_TEXTURED);
890 overscroll_window_->layer()->SetMasksToBounds(false);
891 overscroll_window_->SetName("OverscrollOverlay");
893 overscroll_change_brightness_ = overscroll_delegate->has_image();
894 window_->AddChild(overscroll_window_.get());
896 gfx::Rect bounds = gfx::Rect(window_->bounds().size());
897 if (ShouldNavigateForward(web_contents_->GetController(),
898 current_overscroll_gesture_)) {
899 // The overlay will be sliding in from the right edge towards the left in
900 // non-RTL, or sliding in from the left edge towards the right in RTL.
901 // So position the overlay window accordingly.
902 bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
905 aura::Window* animate_window = GetWindowToAnimateForOverscroll();
906 if (animate_window == overscroll_window_)
907 window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
909 window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
911 UpdateOverscrollWindowBrightness(0.f);
913 overscroll_window_->SetBounds(bounds);
914 overscroll_window_->Show();
916 overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
919 void WebContentsViewAura::PrepareContentWindowForOverscroll() {
920 StopObservingImplicitAnimations();
921 aura::Window* content = GetContentNativeView();
922 content->layer()->GetAnimator()->AbortAllAnimations();
923 content->SetTransform(gfx::Transform());
924 content->layer()->SetLayerBrightness(0.f);
927 void WebContentsViewAura::ResetOverscrollTransform() {
928 if (!web_contents_->GetRenderWidgetHostView())
930 aura::Window* target = GetWindowToAnimateForOverscroll();
934 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
935 settings.SetPreemptionStrategy(
936 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
937 settings.SetTweenType(gfx::Tween::EASE_OUT);
938 settings.AddObserver(this);
939 target->SetTransform(gfx::Transform());
942 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
943 settings.SetPreemptionStrategy(
944 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
945 settings.SetTweenType(gfx::Tween::EASE_OUT);
946 UpdateOverscrollWindowBrightness(0.f);
950 void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
951 if (!web_contents_->GetRenderWidgetHostView())
954 // Animate out the current view first. Navigate to the requested history at
955 // the end of the animation.
956 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
959 UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
960 current_overscroll_gesture_, OVERSCROLL_COUNT);
961 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
962 overscroll_window_->delegate());
963 delegate->stop_forwarding_events();
965 completed_overscroll_gesture_ = mode;
966 aura::Window* target = GetWindowToAnimateForOverscroll();
967 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
968 settings.SetPreemptionStrategy(
969 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
970 settings.SetTweenType(gfx::Tween::EASE_OUT);
971 settings.AddObserver(this);
972 gfx::Transform transform;
974 web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
975 int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width;
976 transform.Translate(translate_x, 0);
977 target->SetTransform(transform);
978 UpdateOverscrollWindowBrightness(translate_x);
981 aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
982 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
985 return ShouldNavigateForward(web_contents_->GetController(),
986 current_overscroll_gesture_) ?
987 overscroll_window_.get() : GetContentNativeView();
990 gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
992 if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
993 current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
994 return gfx::Vector2d(0, delta_y);
996 // For horizontal overscroll, scroll freely if a navigation is possible. Do a
997 // resistive scroll otherwise.
998 const NavigationControllerImpl& controller = web_contents_->GetController();
999 const gfx::Rect& bounds = GetViewBounds();
1000 if (ShouldNavigateForward(controller, current_overscroll_gesture_))
1001 return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0);
1002 else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
1003 return gfx::Vector2d(std::min(bounds.width(), delta_x), 0);
1004 return gfx::Vector2d();
1007 void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
1008 OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
1009 overscroll_window_->delegate());
1010 overscroll_window_->SchedulePaintInRect(
1011 gfx::Rect(overscroll_window_->bounds().size()));
1012 overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
1013 overscroll_window_->SetTransform(gfx::Transform());
1014 navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
1016 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(
1017 web_contents_->GetRenderWidgetHostView()));
1020 void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
1021 if (!overscroll_change_brightness_)
1024 const float kBrightnessMin = -.1f;
1025 const float kBrightnessMax = -.01f;
1027 float ratio = fabs(delta_x) / GetViewBounds().width();
1028 ratio = std::min(1.f, ratio);
1029 if (base::i18n::IsRTL())
1030 ratio = 1.f - ratio;
1031 float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
1032 kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
1033 kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
1034 brightness = std::max(kBrightnessMin, brightness);
1035 brightness = std::min(kBrightnessMax, brightness);
1036 aura::Window* window = GetWindowToAnimateForOverscroll();
1037 window->layer()->SetLayerBrightness(brightness);
1040 void WebContentsViewAura::AttachTouchEditableToRenderView() {
1041 if (!touch_editable_)
1043 RenderWidgetHostViewAura* rwhva = ToRenderWidgetHostViewAura(
1044 web_contents_->GetRenderWidgetHostView());
1045 touch_editable_->AttachToView(rwhva);
1048 void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y) {
1049 if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
1050 web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
1053 ////////////////////////////////////////////////////////////////////////////////
1054 // WebContentsViewAura, WebContentsView implementation:
1056 gfx::NativeView WebContentsViewAura::GetNativeView() const {
1057 return window_.get();
1060 gfx::NativeView WebContentsViewAura::GetContentNativeView() const {
1061 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1062 return rwhv ? rwhv->GetNativeView() : NULL;
1065 gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const {
1066 return window_->GetToplevelWindow();
1069 void WebContentsViewAura::GetContainerBounds(gfx::Rect *out) const {
1070 *out = window_->GetBoundsInScreen();
1073 void WebContentsViewAura::OnTabCrashed(base::TerminationStatus status,
1077 void WebContentsViewAura::SizeContents(const gfx::Size& size) {
1078 gfx::Rect bounds = window_->bounds();
1079 if (bounds.size() != size) {
1080 bounds.set_size(size);
1081 window_->SetBounds(bounds);
1083 // Our size matches what we want but the renderers size may not match.
1084 // Pretend we were resized so that the renderers size is updated too.
1085 SizeChangedCommon(size);
1089 void WebContentsViewAura::Focus() {
1090 if (web_contents_->GetInterstitialPage()) {
1091 web_contents_->GetInterstitialPage()->Focus();
1095 if (delegate_.get() && delegate_->Focus())
1098 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1103 void WebContentsViewAura::SetInitialFocus() {
1104 if (web_contents_->FocusLocationBarByDefault())
1105 web_contents_->SetFocusToLocationBar(false);
1110 void WebContentsViewAura::StoreFocus() {
1112 delegate_->StoreFocus();
1115 void WebContentsViewAura::RestoreFocus() {
1117 delegate_->RestoreFocus();
1120 DropData* WebContentsViewAura::GetDropData() const {
1121 return current_drop_data_.get();
1124 gfx::Rect WebContentsViewAura::GetViewBounds() const {
1125 return window_->GetBoundsInScreen();
1128 ////////////////////////////////////////////////////////////////////////////////
1129 // WebContentsViewAura, WebContentsViewPort implementation:
1131 void WebContentsViewAura::CreateView(
1132 const gfx::Size& initial_size, gfx::NativeView context) {
1133 // NOTE: we ignore |initial_size| since in some cases it's wrong (such as
1134 // if the bookmark bar is not shown and you create a new tab). The right
1135 // value is set shortly after this, so its safe to ignore.
1137 aura::Env::CreateInstance();
1138 window_.reset(new aura::Window(this));
1139 window_->set_owned_by_parent(false);
1140 window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
1141 window_->SetTransparent(false);
1142 window_->Init(ui::LAYER_NOT_DRAWN);
1143 aura::Window* root_window = context ? context->GetRootWindow() : NULL;
1145 // There are places where there is no context currently because object
1146 // hierarchies are built before they're attached to a Widget. (See
1147 // views::WebView as an example; GetWidget() returns NULL at the point
1148 // where we are created.)
1150 // It should be OK to not set a default parent since such users will
1151 // explicitly add this WebContentsViewAura to their tree after they create
1154 aura::client::ParentWindowWithContext(
1155 window_.get(), root_window, root_window->GetBoundsInScreen());
1158 window_->layer()->SetMasksToBounds(true);
1159 window_->SetName("WebContentsViewAura");
1161 window_observer_.reset(new WindowObserver(this));
1163 // delegate_->GetDragDestDelegate() creates a new delegate on every call.
1164 // Hence, we save a reference to it locally. Similar model is used on other
1165 // platforms as well.
1167 drag_dest_delegate_ = delegate_->GetDragDestDelegate();
1170 RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
1171 RenderWidgetHost* render_widget_host) {
1172 if (render_widget_host->GetView()) {
1173 // During testing, the view will already be set up in most cases to the
1174 // test view, so we don't want to clobber it with a real one. To verify that
1175 // this actually is happening (and somebody isn't accidentally creating the
1176 // view twice), we check for the RVH Factory, which will be set when we're
1177 // making special ones (which go along with the special views).
1178 DCHECK(RenderViewHostFactory::has_factory());
1179 return render_widget_host->GetView();
1182 RenderWidgetHostView* view =
1183 RenderWidgetHostView::CreateViewForWidget(render_widget_host);
1184 view->InitAsChild(NULL);
1185 GetNativeView()->AddChild(view->GetNativeView());
1187 if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1188 navigation_overlay_->StartObservingView(ToRenderWidgetHostViewAura(view));
1191 RenderWidgetHostImpl* host_impl =
1192 RenderWidgetHostImpl::From(render_widget_host);
1194 if (!host_impl->is_hidden())
1197 // We listen to drag drop events in the newly created view's window.
1198 aura::client::SetDragDropDelegate(view->GetNativeView(), this);
1200 if (host_impl->overscroll_controller() &&
1201 (!web_contents_->GetDelegate() ||
1202 web_contents_->GetDelegate()->CanOverscrollContent())) {
1203 host_impl->overscroll_controller()->set_delegate(this);
1204 if (!navigation_overlay_)
1205 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1208 AttachTouchEditableToRenderView();
1212 RenderWidgetHostView* WebContentsViewAura::CreateViewForPopupWidget(
1213 RenderWidgetHost* render_widget_host) {
1214 return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
1217 void WebContentsViewAura::SetPageTitle(const string16& title) {
1218 window_->set_title(title);
1221 void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
1224 void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
1225 if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
1226 navigation_overlay_->StartObservingView(
1227 ToRenderWidgetHostViewAura(host->GetView()));
1229 AttachTouchEditableToRenderView();
1232 void WebContentsViewAura::SetOverscrollControllerEnabled(bool enabled) {
1233 RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
1234 web_contents_->GetRenderViewHost());
1236 host->SetOverscrollControllerEnabled(enabled);
1238 host->overscroll_controller()->set_delegate(this);
1242 navigation_overlay_.reset();
1243 else if (!navigation_overlay_)
1244 navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
1247 ////////////////////////////////////////////////////////////////////////////////
1248 // WebContentsViewAura, RenderViewHostDelegateView implementation:
1250 void WebContentsViewAura::ShowContextMenu(const ContextMenuParams& params) {
1251 if (touch_editable_)
1252 touch_editable_->EndTouchEditing();
1254 delegate_->ShowContextMenu(params);
1255 // WARNING: we may have been deleted during the call to ShowContextMenu().
1259 void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
1261 double item_font_size,
1263 const std::vector<MenuItem>& items,
1265 bool allow_multiple_selection) {
1266 // External popup menus are only used on Mac and Android.
1270 void WebContentsViewAura::StartDragging(
1271 const DropData& drop_data,
1272 WebKit::WebDragOperationsMask operations,
1273 const gfx::ImageSkia& image,
1274 const gfx::Vector2d& image_offset,
1275 const DragEventSourceInfo& event_info) {
1276 aura::Window* root_window = GetNativeView()->GetRootWindow();
1277 if (!aura::client::GetDragDropClient(root_window)) {
1278 web_contents_->SystemDragEnded();
1282 if (touch_editable_)
1283 touch_editable_->EndTouchEditing();
1285 ui::OSExchangeData::Provider* provider = ui::OSExchangeData::CreateProvider();
1286 PrepareDragData(drop_data, provider);
1288 ui::OSExchangeData data(provider); // takes ownership of |provider|.
1290 if (!image.isNull()) {
1291 drag_utils::SetDragImageOnDataObject(image,
1292 gfx::Size(image.width(), image.height()), image_offset, &data);
1295 scoped_ptr<WebDragSourceAura> drag_source(
1296 new WebDragSourceAura(GetNativeView(), web_contents_));
1298 // We need to enable recursive tasks on the message loop so we can get
1299 // updates while in the system DoDragDrop loop.
1302 gfx::NativeView content_native_view = GetContentNativeView();
1303 base::MessageLoop::ScopedNestableTaskAllower allow(
1304 base::MessageLoop::current());
1305 result_op = aura::client::GetDragDropClient(root_window)
1306 ->StartDragAndDrop(data,
1308 content_native_view,
1309 event_info.event_location,
1310 ConvertFromWeb(operations),
1311 event_info.event_source);
1314 // Bail out immediately if the contents view window is gone. Note that it is
1315 // not safe to access any class members in this case since |this| may already
1316 // be destroyed. The local variable |drag_source| will still be valid though,
1317 // so we can use it to determine if the window is gone.
1318 if (!drag_source->window()) {
1319 // Note that in this case, we don't need to call SystemDragEnded() since the
1320 // renderer is going away.
1324 EndDrag(ConvertToWeb(result_op));
1325 web_contents_->SystemDragEnded();
1328 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
1329 current_drag_op_ = operation;
1332 void WebContentsViewAura::GotFocus() {
1333 if (web_contents_->GetDelegate())
1334 web_contents_->GetDelegate()->WebContentsFocused(web_contents_);
1337 void WebContentsViewAura::TakeFocus(bool reverse) {
1338 if (web_contents_->GetDelegate() &&
1339 !web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
1341 delegate_->TakeFocus(reverse);
1345 ////////////////////////////////////////////////////////////////////////////////
1346 // WebContentsViewAura, OverscrollControllerDelegate implementation:
1348 gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
1349 RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
1350 if (!rwhv || !rwhv->IsShowing())
1353 return rwhv->GetViewBounds();
1356 void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
1357 if (current_overscroll_gesture_ == OVERSCROLL_NONE)
1360 aura::Window* target = GetWindowToAnimateForOverscroll();
1361 ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
1362 settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
1363 gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y);
1364 gfx::Transform transform;
1366 // Vertical overscrolls don't participate in the navigation gesture.
1367 if (current_overscroll_gesture_ != OVERSCROLL_NORTH &&
1368 current_overscroll_gesture_ != OVERSCROLL_SOUTH) {
1369 transform.Translate(translate.x(), translate.y());
1370 target->SetTransform(transform);
1371 UpdateOverscrollWindowBrightness(delta_x);
1374 OverscrollUpdateForWebContentsDelegate(translate.y());
1377 void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
1378 UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
1379 OverscrollUpdateForWebContentsDelegate(0);
1380 NavigationControllerImpl& controller = web_contents_->GetController();
1381 if (ShouldNavigateForward(controller, mode) ||
1382 ShouldNavigateBack(controller, mode)) {
1383 CompleteOverscrollNavigation(mode);
1387 ResetOverscrollTransform();
1390 void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
1391 OverscrollMode new_mode) {
1392 // Reset any in-progress overscroll animation first.
1393 ResetOverscrollTransform();
1395 if (new_mode != OVERSCROLL_NONE && touch_editable_)
1396 touch_editable_->OverscrollStarted();
1398 if (new_mode == OVERSCROLL_NONE ||
1399 !GetContentNativeView() ||
1400 ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
1401 navigation_overlay_.get() && navigation_overlay_->has_window())) {
1402 current_overscroll_gesture_ = OVERSCROLL_NONE;
1403 OverscrollUpdateForWebContentsDelegate(0);
1405 aura::Window* target = GetWindowToAnimateForOverscroll();
1407 StopObservingImplicitAnimations();
1408 target->layer()->GetAnimator()->AbortAllAnimations();
1410 // Cleanup state of the content window first, because that can reset the
1411 // value of |current_overscroll_gesture_|.
1412 PrepareContentWindowForOverscroll();
1414 current_overscroll_gesture_ = new_mode;
1415 if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
1416 current_overscroll_gesture_ == OVERSCROLL_WEST)
1417 PrepareOverscrollWindow();
1419 UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
1421 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1424 ////////////////////////////////////////////////////////////////////////////////
1425 // WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
1427 void WebContentsViewAura::OnImplicitAnimationsCompleted() {
1428 overscroll_shadow_.reset();
1430 if (ShouldNavigateForward(web_contents_->GetController(),
1431 completed_overscroll_gesture_)) {
1432 PrepareOverscrollNavigationOverlay();
1433 web_contents_->GetController().GoForward();
1434 } else if (ShouldNavigateBack(web_contents_->GetController(),
1435 completed_overscroll_gesture_)) {
1436 PrepareOverscrollNavigationOverlay();
1437 web_contents_->GetController().GoBack();
1439 if (touch_editable_)
1440 touch_editable_->OverscrollCompleted();
1443 aura::Window* content = GetContentNativeView();
1445 content->SetTransform(gfx::Transform());
1446 content->layer()->SetLayerBrightness(0.f);
1448 current_overscroll_gesture_ = OVERSCROLL_NONE;
1449 completed_overscroll_gesture_ = OVERSCROLL_NONE;
1450 overscroll_window_.reset();
1453 ////////////////////////////////////////////////////////////////////////////////
1454 // WebContentsViewAura, aura::WindowDelegate implementation:
1456 gfx::Size WebContentsViewAura::GetMinimumSize() const {
1460 gfx::Size WebContentsViewAura::GetMaximumSize() const {
1464 void WebContentsViewAura::OnBoundsChanged(const gfx::Rect& old_bounds,
1465 const gfx::Rect& new_bounds) {
1466 SizeChangedCommon(new_bounds.size());
1468 delegate_->SizeChanged(new_bounds.size());
1470 // Constrained web dialogs, need to be kept centered over our content area.
1471 for (size_t i = 0; i < window_->children().size(); i++) {
1472 if (window_->children()[i]->GetProperty(
1473 aura::client::kConstrainedWindowKey)) {
1474 gfx::Rect bounds = window_->children()[i]->bounds();
1476 gfx::Point((new_bounds.width() - bounds.width()) / 2,
1477 (new_bounds.height() - bounds.height()) / 2));
1478 window_->children()[i]->SetBounds(bounds);
1483 gfx::NativeCursor WebContentsViewAura::GetCursor(const gfx::Point& point) {
1484 return gfx::kNullCursor;
1487 int WebContentsViewAura::GetNonClientComponent(const gfx::Point& point) const {
1491 bool WebContentsViewAura::ShouldDescendIntoChildForEventHandling(
1492 aura::Window* child,
1493 const gfx::Point& location) {
1497 bool WebContentsViewAura::CanFocus() {
1498 // Do not take the focus if the render widget host view aura is gone or
1499 // is in the process of shutting down because neither the view window nor
1500 // this window can handle key events.
1501 RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
1502 web_contents_->GetRenderWidgetHostView());
1503 if (view != NULL && !view->IsClosing())
1509 void WebContentsViewAura::OnCaptureLost() {
1512 void WebContentsViewAura::OnPaint(gfx::Canvas* canvas) {
1515 void WebContentsViewAura::OnDeviceScaleFactorChanged(
1516 float device_scale_factor) {
1519 void WebContentsViewAura::OnWindowDestroying() {
1520 // This means the destructor is going to be called soon. If there is an
1521 // overscroll gesture in progress (i.e. |overscroll_window_| is not NULL),
1522 // then destroying it in the WebContentsViewAura destructor can trigger other
1523 // virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
1524 // destroy the overscroll window here.
1525 navigation_overlay_.reset();
1526 overscroll_window_.reset();
1529 void WebContentsViewAura::OnWindowDestroyed() {
1532 void WebContentsViewAura::OnWindowTargetVisibilityChanged(bool visible) {
1534 web_contents_->WasShown();
1536 web_contents_->WasHidden();
1539 bool WebContentsViewAura::HasHitTestMask() const {
1543 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
1546 void WebContentsViewAura::DidRecreateLayer(ui::Layer *old_layer,
1547 ui::Layer *new_layer) {
1550 ////////////////////////////////////////////////////////////////////////////////
1551 // WebContentsViewAura, ui::EventHandler implementation:
1553 void WebContentsViewAura::OnKeyEvent(ui::KeyEvent* event) {
1556 void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
1557 if (!web_contents_->GetDelegate())
1560 switch (event->type()) {
1561 case ui::ET_MOUSE_PRESSED:
1562 web_contents_->GetDelegate()->ActivateContents(web_contents_);
1564 case ui::ET_MOUSE_MOVED:
1565 case ui::ET_MOUSE_EXITED:
1566 web_contents_->GetDelegate()->ContentsMouseEvent(
1568 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1569 event->type() == ui::ET_MOUSE_MOVED);
1576 ////////////////////////////////////////////////////////////////////////////////
1577 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
1579 void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
1580 if (drag_dest_delegate_)
1581 drag_dest_delegate_->DragInitialize(web_contents_);
1583 current_drop_data_.reset(new DropData());
1585 PrepareDropData(current_drop_data_.get(), event.data());
1586 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1588 gfx::Point screen_pt =
1589 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1590 current_rvh_for_drag_ = web_contents_->GetRenderViewHost();
1591 web_contents_->GetRenderViewHost()->DragTargetDragEnter(
1592 *current_drop_data_.get(), event.location(), screen_pt, op,
1593 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1595 if (drag_dest_delegate_) {
1596 drag_dest_delegate_->OnReceiveDragData(event.data());
1597 drag_dest_delegate_->OnDragEnter();
1601 int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
1602 DCHECK(current_rvh_for_drag_);
1603 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1604 OnDragEntered(event);
1606 WebKit::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
1607 gfx::Point screen_pt =
1608 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
1609 web_contents_->GetRenderViewHost()->DragTargetDragOver(
1610 event.location(), screen_pt, op,
1611 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1613 if (drag_dest_delegate_)
1614 drag_dest_delegate_->OnDragOver();
1616 return ConvertFromWeb(current_drag_op_);
1619 void WebContentsViewAura::OnDragExited() {
1620 DCHECK(current_rvh_for_drag_);
1621 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1624 web_contents_->GetRenderViewHost()->DragTargetDragLeave();
1625 if (drag_dest_delegate_)
1626 drag_dest_delegate_->OnDragLeave();
1628 current_drop_data_.reset();
1631 int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
1632 DCHECK(current_rvh_for_drag_);
1633 if (current_rvh_for_drag_ != web_contents_->GetRenderViewHost())
1634 OnDragEntered(event);
1636 web_contents_->GetRenderViewHost()->DragTargetDrop(
1638 gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
1639 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
1640 if (drag_dest_delegate_)
1641 drag_dest_delegate_->OnDrop();
1642 current_drop_data_.reset();
1643 return current_drag_op_;
1646 } // namespace content