Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_aura.cc

Issue 19681003: Fix issue where window bounds were being passed with wrong coordinates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Adds unit test to catch coordinate system related errors in the RWHVA. Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/render_widget_host_view_aura.h" 5 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 old_child->popup_parent_host_view_ = NULL; 670 old_child->popup_parent_host_view_ = NULL;
671 } 671 }
672 popup_parent_host_view_->popup_child_host_view_ = this; 672 popup_parent_host_view_->popup_child_host_view_ = this;
673 window_->SetType(aura::client::WINDOW_TYPE_MENU); 673 window_->SetType(aura::client::WINDOW_TYPE_MENU);
674 window_->Init(ui::LAYER_TEXTURED); 674 window_->Init(ui::LAYER_TEXTURED);
675 window_->SetName("RenderWidgetHostViewAura"); 675 window_->SetName("RenderWidgetHostViewAura");
676 676
677 aura::RootWindow* root = popup_parent_host_view_->window_->GetRootWindow(); 677 aura::RootWindow* root = popup_parent_host_view_->window_->GetRootWindow();
678 window_->SetDefaultParentByRootWindow(root, bounds_in_screen); 678 window_->SetDefaultParentByRootWindow(root, bounds_in_screen);
679 679
680 // TODO(erg): While I could make sure details of the StackingClient are 680 SetBounds(bounds_in_screen);
681 // hidden behind aura, hiding the details of the ScreenPositionClient will
682 // take another effort.
683 aura::client::ScreenPositionClient* screen_position_client =
684 aura::client::GetScreenPositionClient(root);
685 gfx::Point origin_in_parent(bounds_in_screen.origin());
686 if (screen_position_client) {
687 screen_position_client->ConvertPointFromScreen(
688 window_->parent(), &origin_in_parent);
689 }
690 SetBounds(gfx::Rect(origin_in_parent, bounds_in_screen.size()));
691 Show(); 681 Show();
692 } 682 }
693 683
694 void RenderWidgetHostViewAura::InitAsFullscreen( 684 void RenderWidgetHostViewAura::InitAsFullscreen(
695 RenderWidgetHostView* reference_host_view) { 685 RenderWidgetHostView* reference_host_view) {
696 is_fullscreen_ = true; 686 is_fullscreen_ = true;
697 window_->SetType(aura::client::WINDOW_TYPE_NORMAL); 687 window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
698 window_->Init(ui::LAYER_TEXTURED); 688 window_->Init(ui::LAYER_TEXTURED);
699 window_->SetName("RenderWidgetHostViewAura"); 689 window_->SetName("RenderWidgetHostViewAura");
700 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 690 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
701 691
702 aura::RootWindow* parent = NULL; 692 aura::RootWindow* parent = NULL;
703 gfx::Rect bounds; 693 gfx::Rect bounds;
704 if (reference_host_view) { 694 if (reference_host_view) {
705 aura::Window* reference_window = 695 aura::Window* reference_window =
706 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_; 696 static_cast<RenderWidgetHostViewAura*>(reference_host_view)->window_;
707 if (reference_window) { 697 if (reference_window) {
708 host_tracker_.reset(new aura::WindowTracker); 698 host_tracker_.reset(new aura::WindowTracker);
709 host_tracker_->Add(reference_window); 699 host_tracker_->Add(reference_window);
710 } 700 }
711 gfx::Display display = gfx::Screen::GetScreenFor(window_)-> 701 gfx::Display display = gfx::Screen::GetScreenFor(window_)->
712 GetDisplayNearestWindow(reference_window); 702 GetDisplayNearestWindow(reference_window);
713 parent = reference_window->GetRootWindow(); 703 parent = reference_window->GetRootWindow();
714 bounds = display.bounds(); 704 bounds = display.bounds();
715 } 705 }
706
716 window_->SetDefaultParentByRootWindow(parent, bounds); 707 window_->SetDefaultParentByRootWindow(parent, bounds);
717 Show(); 708 Show();
718 Focus(); 709 Focus();
719 } 710 }
720 711
721 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const { 712 RenderWidgetHost* RenderWidgetHostViewAura::GetRenderWidgetHost() const {
722 return host_; 713 return host_;
723 } 714 }
724 715
725 void RenderWidgetHostViewAura::WasShown() { 716 void RenderWidgetHostViewAura::WasShown() {
(...skipping 30 matching lines...) Expand all
756 if (root_window) { 747 if (root_window) {
757 HWND parent = root_window->GetAcceleratedWidget(); 748 HWND parent = root_window->GetAcceleratedWidget();
758 LPARAM lparam = reinterpret_cast<LPARAM>(this); 749 LPARAM lparam = reinterpret_cast<LPARAM>(this);
759 750
760 EnumChildWindows(parent, HideWindowsCallback, lparam); 751 EnumChildWindows(parent, HideWindowsCallback, lparam);
761 } 752 }
762 #endif 753 #endif
763 } 754 }
764 755
765 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) { 756 void RenderWidgetHostViewAura::SetSize(const gfx::Size& size) {
766 SetBounds(gfx::Rect(window_->bounds().origin(), size)); 757 // For a set size operation, we don't care what coordinate system the origin
758 // of the window is stored in, it's only important to make sure the origin
759 // remains constant after the operation.
760 InternalSetBounds(gfx::Rect(window_->bounds().origin(), size));
767 } 761 }
768 762
769 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) { 763 void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
764 // RenderWidgetHostViewAura::SetBounds() takes screen coordinates, but
765 // Window::SetBounds() takes parent coordinates, so we do the conversion here.
766 aura::RootWindow* root = window_->GetRootWindow();
767 aura::client::ScreenPositionClient* screen_position_client =
768 aura::client::GetScreenPositionClient(root);
769 gfx::Point origin_in_parent(rect.origin());
770 if (screen_position_client) {
771 screen_position_client->ConvertPointFromScreen(
772 window_->parent(), &origin_in_parent);
773 }
774
775 InternalSetBounds(gfx::Rect(origin_in_parent, rect.size()));
776 }
777
778 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
779 return window_;
780 }
781
782 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
783 #if defined(OS_WIN)
784 aura::RootWindow* root_window = window_->GetRootWindow();
785 if (root_window) {
786 HWND window = root_window->GetAcceleratedWidget();
787 return reinterpret_cast<gfx::NativeViewId>(window);
788 }
789 #endif
790 return static_cast<gfx::NativeViewId>(NULL);
791 }
792
793 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
794 #if defined(OS_WIN)
795 aura::RootWindow* root_window = window_->GetRootWindow();
796 if (!root_window)
797 return static_cast<gfx::NativeViewAccessible>(NULL);
798 HWND hwnd = root_window->GetAcceleratedWidget();
799
800 BrowserAccessibilityManager* manager =
801 GetOrCreateBrowserAccessibilityManager();
802 if (manager)
803 return manager->GetRoot()->ToBrowserAccessibilityWin();
804 #endif
805
806 NOTIMPLEMENTED();
807 return static_cast<gfx::NativeViewAccessible>(NULL);
808 }
809
810 BrowserAccessibilityManager*
811 RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
812 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
813 if (manager)
814 return manager;
815
816 #if defined(OS_WIN)
817 aura::RootWindow* root_window = window_->GetRootWindow();
818 if (!root_window)
819 return NULL;
820 HWND hwnd = root_window->GetAcceleratedWidget();
821
822 // The accessible_parent may be NULL at this point. The WebContents will pass
823 // it down to this instance (by way of the RenderViewHost and
824 // RenderWidgetHost) when it is known. This instance will then set it on its
825 // BrowserAccessibilityManager.
826 gfx::NativeViewAccessible accessible_parent =
827 host_->GetParentNativeViewAccessible();
828
829 manager = new BrowserAccessibilityManagerWin(
830 hwnd, accessible_parent,
831 BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
832 #else
833 manager = BrowserAccessibilityManager::Create(
834 BrowserAccessibilityManager::GetEmptyDocument(), this);
835 #endif
836
837 SetBrowserAccessibilityManager(manager);
838 return manager;
839 }
840
841 void RenderWidgetHostViewAura::MovePluginWindows(
842 const gfx::Vector2d& scroll_offset,
843 const std::vector<WebPluginGeometry>& plugin_window_moves) {
844 #if defined(OS_WIN)
845 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
846 // over the browser UI.
847 if (!window_->GetRootWindow()) {
848 DCHECK(plugin_window_moves.empty());
849 return;
850 }
851 HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
852 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
853 std::vector<WebPluginGeometry> moves = plugin_window_moves;
854
855 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
856 view_bounds.height());
857
858 for (size_t i = 0; i < moves.size(); ++i) {
859 gfx::Rect clip(moves[i].clip_rect);
860 gfx::Vector2d view_port_offset(
861 moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
862 clip.Offset(view_port_offset);
863 clip.Intersect(view_port);
864 clip.Offset(-view_port_offset);
865 moves[i].clip_rect = clip;
866
867 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
868
869 plugin_window_moves_[moves[i].window] = moves[i];
870
871 // transient_rects_ and constrained_rects_ are relative to the root window.
872 // We want to convert them to be relative to the plugin window.
873 std::vector<gfx::Rect> cutout_rects;
874 cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
875 cutout_rects.insert(cutout_rects.end(), constrained_rects_.begin(),
876 constrained_rects_.end());
877 for (size_t j = 0; j < cutout_rects.size(); ++j) {
878 gfx::Rect offset_cutout = cutout_rects[j];
879 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
880 moves[i].cutout_rects.push_back(offset_cutout);
881 }
882 }
883
884 MovePluginWindowsHelper(parent, moves);
885
886 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
887 // |this|.
888 for (size_t i = 0; i < moves.size(); ++i) {
889 HWND window = moves[i].window;
890 if (GetParent(window) != parent) {
891 window = GetParent(window);
892 DCHECK(GetParent(window) == parent);
893 }
894 if (!GetProp(window, kWidgetOwnerProperty))
895 CHECK(SetProp(window, kWidgetOwnerProperty, this));
896 }
897 #endif // defined(OS_WIN)
898 }
899
900 void RenderWidgetHostViewAura::Focus() {
901 // Make sure we have a FocusClient before attempting to Focus(). In some
902 // situations we may not yet be in a valid Window hierarchy (such as reloading
903 // after out of memory discarded the tab).
904 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
905 if (client)
906 window_->Focus();
907 }
908
909 void RenderWidgetHostViewAura::Blur() {
910 window_->Blur();
911 }
912
913 bool RenderWidgetHostViewAura::HasFocus() const {
914 return window_->HasFocus();
915 }
916
917 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
918 return window_->layer()->has_external_content() ||
919 !!host_->GetBackingStore(false);
920 }
921
922 void RenderWidgetHostViewAura::Show() {
923 window_->Show();
924 }
925
926 void RenderWidgetHostViewAura::Hide() {
927 window_->Hide();
928 }
929
930 bool RenderWidgetHostViewAura::IsShowing() {
931 return window_->IsVisible();
932 }
933
934 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
935 // This is the size that we want the renderer to produce. While we're waiting
936 // for the correct frame (i.e. during a resize), don't change the size so that
937 // we don't pipeline more resizes than we can handle.
938 gfx::Rect bounds(window_->GetBoundsInScreen());
939 if (resize_lock_.get())
940 return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
941 else
942 return bounds;
943 }
944
945 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
946 RenderWidgetHostViewBase::SetBackground(background);
947 host_->SetBackground(background);
948 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
949 }
950
951 #if defined(OS_WIN)
952 gfx::NativeViewAccessible
953 RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
954 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
955 if (!manager)
956 return NULL;
957
958 return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
959 child_id);
960 }
961 #endif // defined(OS_WIN)
962
963 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
964 current_cursor_ = cursor;
965 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
966 GetDisplayNearestWindow(window_);
967 current_cursor_.SetDeviceScaleFactor(display.device_scale_factor());
968 UpdateCursorIfOverSelf();
969 }
970
971 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
972 if (is_loading_ && !is_loading && paint_observer_)
973 paint_observer_->OnPageLoadComplete();
974 is_loading_ = is_loading;
975 UpdateCursorIfOverSelf();
976 }
977
978 void RenderWidgetHostViewAura::TextInputTypeChanged(
979 ui::TextInputType type,
980 bool can_compose_inline,
981 ui::TextInputMode input_mode) {
982 if (text_input_type_ != type ||
983 can_compose_inline_ != can_compose_inline) {
984 text_input_type_ = type;
985 can_compose_inline_ = can_compose_inline;
986 if (GetInputMethod())
987 GetInputMethod()->OnTextInputTypeChanged(this);
988 if (touch_editing_client_)
989 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
990 }
991 }
992
993 void RenderWidgetHostViewAura::ImeCancelComposition() {
994 if (GetInputMethod())
995 GetInputMethod()->CancelComposition(this);
996 has_composition_text_ = false;
997 }
998
999 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
1000 const ui::Range& range,
1001 const std::vector<gfx::Rect>& character_bounds) {
1002 composition_character_bounds_ = character_bounds;
1003 }
1004
1005 void RenderWidgetHostViewAura::DidUpdateBackingStore(
1006 const gfx::Rect& scroll_rect,
1007 const gfx::Vector2d& scroll_delta,
1008 const std::vector<gfx::Rect>& copy_rects,
1009 const ui::LatencyInfo& latency_info) {
1010 if (accelerated_compositing_state_changed_)
1011 UpdateExternalTexture();
1012
1013 software_latency_info_.MergeWith(latency_info);
1014
1015 // Use the state of the RenderWidgetHost and not the window as the two may
1016 // differ. In particular if the window is hidden but the renderer isn't and we
1017 // ignore the update and the window is made visible again the layer isn't
1018 // marked as dirty and we show the wrong thing.
1019 // We do this after UpdateExternalTexture() so that when we become visible
1020 // we're not drawing a stale texture.
1021 if (host_->is_hidden())
1022 return;
1023
1024 gfx::Rect clip_rect;
1025 if (paint_canvas_) {
1026 SkRect sk_clip_rect;
1027 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
1028 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
1029 }
1030
1031 if (!scroll_rect.IsEmpty())
1032 SchedulePaintIfNotInClip(scroll_rect, clip_rect);
1033
1034 #if defined(OS_WIN)
1035 aura::RootWindow* root_window = window_->GetRootWindow();
1036 #endif
1037 for (size_t i = 0; i < copy_rects.size(); ++i) {
1038 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
1039 if (rect.IsEmpty())
1040 continue;
1041
1042 SchedulePaintIfNotInClip(rect, clip_rect);
1043
1044 #if defined(OS_WIN)
1045 if (root_window) {
1046 // Send the invalid rect in screen coordinates.
1047 gfx::Rect screen_rect = GetViewBounds();
1048 gfx::Rect invalid_screen_rect(rect);
1049 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
1050 HWND hwnd = root_window->GetAcceleratedWidget();
1051 PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
1052 }
1053 #endif // defined(OS_WIN)
1054 }
1055 }
1056
1057 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
1058 int error_code) {
1059 UpdateCursorIfOverSelf();
1060 Destroy();
1061 }
1062
1063 void RenderWidgetHostViewAura::Destroy() {
1064 // Beware, this function is not called on all destruction paths. It will
1065 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1066 // destruction/cleanup code should happen there, not here.
1067 in_shutdown_ = true;
1068 delete window_;
1069 }
1070
1071 void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
1072 tooltip_ = tooltip_text;
1073 aura::RootWindow* root_window = window_->GetRootWindow();
1074 aura::client::TooltipClient* tooltip_client =
1075 aura::client::GetTooltipClient(root_window);
1076 if (tooltip_client) {
1077 tooltip_client->UpdateTooltip(window_);
1078 // Content tooltips should be visible indefinitely.
1079 tooltip_client->SetTooltipShownTimeout(window_, 0);
1080 }
1081 }
1082
1083 void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
1084 size_t offset,
1085 const ui::Range& range) {
1086 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1087
1088 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1089 if (text.empty() || range.is_empty())
1090 return;
1091
1092 // Set the BUFFER_SELECTION to the ui::Clipboard.
1093 ui::ScopedClipboardWriter clipboard_writer(
1094 ui::Clipboard::GetForCurrentThread(),
1095 ui::Clipboard::BUFFER_SELECTION);
1096 clipboard_writer.WriteText(text);
1097 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1098 }
1099
1100 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1101 const ViewHostMsg_SelectionBounds_Params& params) {
1102 if (selection_anchor_rect_ == params.anchor_rect &&
1103 selection_focus_rect_ == params.focus_rect)
1104 return;
1105
1106 selection_anchor_rect_ = params.anchor_rect;
1107 selection_focus_rect_ = params.focus_rect;
1108
1109 if (GetInputMethod())
1110 GetInputMethod()->OnCaretBoundsChanged(this);
1111
1112 if (touch_editing_client_) {
1113 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1114 selection_focus_rect_);
1115 }
1116 }
1117
1118 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
1119 aura::RootWindow* root = window_->GetRootWindow();
1120 if (!root)
1121 return;
1122 aura::client::CursorClient* cursor_client =
1123 aura::client::GetCursorClient(root);
1124 if (cursor_client && !cursor_client->IsCursorVisible())
1125 cursor_client->DisableMouseEvents();
1126 }
1127
1128 BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
1129 const gfx::Size& size) {
1130 return new BackingStoreAura(host_, size);
1131 }
1132
1133 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1134 const gfx::Rect& src_subrect,
1135 const gfx::Size& dst_size,
1136 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1137 if (!window_->layer()->has_external_content()) {
1138 callback.Run(false, SkBitmap());
1139 return;
1140 }
1141
1142 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
1143
1144 scoped_ptr<cc::CopyOutputRequest> request =
1145 cc::CopyOutputRequest::CreateRequest(base::Bind(
1146 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
1147 dst_size_in_pixel,
1148 callback));
1149 request->set_area(src_subrect);
1150 window_->layer()->RequestCopyOfOutput(request.Pass());
1151 }
1152
1153 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1154 const gfx::Rect& src_subrect,
1155 const scoped_refptr<media::VideoFrame>& target,
1156 const base::Callback<void(bool)>& callback) {
1157 if (!window_->layer()->has_external_content()) {
1158 callback.Run(false);
1159 return;
1160 }
1161
1162 scoped_ptr<cc::CopyOutputRequest> request =
1163 cc::CopyOutputRequest::CreateRequest(base::Bind(
1164 &RenderWidgetHostViewAura::
1165 CopyFromCompositingSurfaceHasResultForVideo,
1166 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
1167 target,
1168 callback));
1169 request->set_area(src_subrect);
1170 window_->layer()->RequestCopyOfOutput(request.Pass());
1171 }
1172
1173 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1174 // TODO(skaslev): Implement this path for s/w compositing.
1175 return window_->layer()->has_external_content() &&
1176 host_->is_accelerated_compositing_active();
1177 }
1178
1179 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1180 return true;
1181 }
1182
1183 void RenderWidgetHostViewAura::BeginFrameSubscription(
1184 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1185 frame_subscriber_ = subscriber.Pass();
1186 }
1187
1188 void RenderWidgetHostViewAura::EndFrameSubscription() {
1189 frame_subscriber_.reset();
1190 }
1191
1192
1193 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
1194 // Delay processing the state change until we either get a software frame if
1195 // switching to software mode or receive a buffers swapped notification
1196 // if switching to accelerated mode.
1197 // Sometimes (e.g. on a page load) the renderer will spuriously disable then
1198 // re-enable accelerated compositing, causing us to flash.
1199 // TODO(piman): factor the enable/disable accelerated compositing message into
1200 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
1201 // fewer inconsistent temporary states.
1202 accelerated_compositing_state_changed_ = true;
1203 }
1204
1205 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
1206 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
1207 can_lock_compositor_ == NO_PENDING_COMMIT ||
1208 !resize_lock_.get())
1209 return false;
1210
1211 return size_in_dip != resize_lock_->expected_size();
1212 }
1213
1214 void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
770 if (HasDisplayPropertyChanged(window_)) 1215 if (HasDisplayPropertyChanged(window_))
771 host_->InvalidateScreenInfo(); 1216 host_->InvalidateScreenInfo();
772 1217
773 window_->SetBounds(rect); 1218 window_->SetBounds(rect);
774 host_->WasResized(); 1219 host_->WasResized();
775 MaybeCreateResizeLock(); 1220 MaybeCreateResizeLock();
776 if (touch_editing_client_) { 1221 if (touch_editing_client_) {
777 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_, 1222 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
778 selection_focus_rect_); 1223 selection_focus_rect_);
779 } 1224 }
(...skipping 28 matching lines...) Expand all
808 if (can_lock_compositor_ == YES) 1253 if (can_lock_compositor_ == YES)
809 can_lock_compositor_ = YES_DID_LOCK; 1254 can_lock_compositor_ = YES_DID_LOCK;
810 1255
811 resize_lock_.reset(new ResizeLock(root_window, desired_size, 1256 resize_lock_.reset(new ResizeLock(root_window, desired_size,
812 defer_compositor_lock)); 1257 defer_compositor_lock));
813 #endif 1258 #endif
814 } 1259 }
815 } 1260 }
816 } 1261 }
817 1262
818 gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
819 return window_;
820 }
821
822 gfx::NativeViewId RenderWidgetHostViewAura::GetNativeViewId() const {
823 #if defined(OS_WIN)
824 aura::RootWindow* root_window = window_->GetRootWindow();
825 if (root_window) {
826 HWND window = root_window->GetAcceleratedWidget();
827 return reinterpret_cast<gfx::NativeViewId>(window);
828 }
829 #endif
830 return static_cast<gfx::NativeViewId>(NULL);
831 }
832
833 gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
834 #if defined(OS_WIN)
835 aura::RootWindow* root_window = window_->GetRootWindow();
836 if (!root_window)
837 return static_cast<gfx::NativeViewAccessible>(NULL);
838 HWND hwnd = root_window->GetAcceleratedWidget();
839
840 BrowserAccessibilityManager* manager =
841 GetOrCreateBrowserAccessibilityManager();
842 if (manager)
843 return manager->GetRoot()->ToBrowserAccessibilityWin();
844 #endif
845
846 NOTIMPLEMENTED();
847 return static_cast<gfx::NativeViewAccessible>(NULL);
848 }
849
850 BrowserAccessibilityManager*
851 RenderWidgetHostViewAura::GetOrCreateBrowserAccessibilityManager() {
852 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
853 if (manager)
854 return manager;
855
856 #if defined(OS_WIN)
857 aura::RootWindow* root_window = window_->GetRootWindow();
858 if (!root_window)
859 return NULL;
860 HWND hwnd = root_window->GetAcceleratedWidget();
861
862 // The accessible_parent may be NULL at this point. The WebContents will pass
863 // it down to this instance (by way of the RenderViewHost and
864 // RenderWidgetHost) when it is known. This instance will then set it on its
865 // BrowserAccessibilityManager.
866 gfx::NativeViewAccessible accessible_parent =
867 host_->GetParentNativeViewAccessible();
868
869 manager = new BrowserAccessibilityManagerWin(
870 hwnd, accessible_parent,
871 BrowserAccessibilityManagerWin::GetEmptyDocument(), this);
872 #else
873 manager = BrowserAccessibilityManager::Create(
874 BrowserAccessibilityManager::GetEmptyDocument(), this);
875 #endif
876
877 SetBrowserAccessibilityManager(manager);
878 return manager;
879 }
880
881 void RenderWidgetHostViewAura::MovePluginWindows(
882 const gfx::Vector2d& scroll_offset,
883 const std::vector<WebPluginGeometry>& plugin_window_moves) {
884 #if defined(OS_WIN)
885 // We need to clip the rectangle to the tab's viewport, otherwise we will draw
886 // over the browser UI.
887 if (!window_->GetRootWindow()) {
888 DCHECK(plugin_window_moves.empty());
889 return;
890 }
891 HWND parent = window_->GetRootWindow()->GetAcceleratedWidget();
892 gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
893 std::vector<WebPluginGeometry> moves = plugin_window_moves;
894
895 gfx::Rect view_port(scroll_offset.x(), scroll_offset.y(), view_bounds.width(),
896 view_bounds.height());
897
898 for (size_t i = 0; i < moves.size(); ++i) {
899 gfx::Rect clip(moves[i].clip_rect);
900 gfx::Vector2d view_port_offset(
901 moves[i].window_rect.OffsetFromOrigin() + scroll_offset);
902 clip.Offset(view_port_offset);
903 clip.Intersect(view_port);
904 clip.Offset(-view_port_offset);
905 moves[i].clip_rect = clip;
906
907 moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
908
909 plugin_window_moves_[moves[i].window] = moves[i];
910
911 // transient_rects_ and constrained_rects_ are relative to the root window.
912 // We want to convert them to be relative to the plugin window.
913 std::vector<gfx::Rect> cutout_rects;
914 cutout_rects.assign(transient_rects_.begin(), transient_rects_.end());
915 cutout_rects.insert(cutout_rects.end(), constrained_rects_.begin(),
916 constrained_rects_.end());
917 for (size_t j = 0; j < cutout_rects.size(); ++j) {
918 gfx::Rect offset_cutout = cutout_rects[j];
919 offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
920 moves[i].cutout_rects.push_back(offset_cutout);
921 }
922 }
923
924 MovePluginWindowsHelper(parent, moves);
925
926 // Make sure each plugin window (or its wrapper if it exists) has a pointer to
927 // |this|.
928 for (size_t i = 0; i < moves.size(); ++i) {
929 HWND window = moves[i].window;
930 if (GetParent(window) != parent) {
931 window = GetParent(window);
932 DCHECK(GetParent(window) == parent);
933 }
934 if (!GetProp(window, kWidgetOwnerProperty))
935 CHECK(SetProp(window, kWidgetOwnerProperty, this));
936 }
937 #endif // defined(OS_WIN)
938 }
939
940 void RenderWidgetHostViewAura::Focus() {
941 // Make sure we have a FocusClient before attempting to Focus(). In some
942 // situations we may not yet be in a valid Window hierarchy (such as reloading
943 // after out of memory discarded the tab).
944 aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
945 if (client)
946 window_->Focus();
947 }
948
949 void RenderWidgetHostViewAura::Blur() {
950 window_->Blur();
951 }
952
953 bool RenderWidgetHostViewAura::HasFocus() const {
954 return window_->HasFocus();
955 }
956
957 bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
958 return window_->layer()->has_external_content() ||
959 !!host_->GetBackingStore(false);
960 }
961
962 void RenderWidgetHostViewAura::Show() {
963 window_->Show();
964 }
965
966 void RenderWidgetHostViewAura::Hide() {
967 window_->Hide();
968 }
969
970 bool RenderWidgetHostViewAura::IsShowing() {
971 return window_->IsVisible();
972 }
973
974 gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
975 // This is the size that we want the renderer to produce. While we're waiting
976 // for the correct frame (i.e. during a resize), don't change the size so that
977 // we don't pipeline more resizes than we can handle.
978 gfx::Rect bounds(window_->GetBoundsInScreen());
979 if (resize_lock_.get())
980 return gfx::Rect(bounds.origin(), resize_lock_->expected_size());
981 else
982 return bounds;
983 }
984
985 void RenderWidgetHostViewAura::SetBackground(const SkBitmap& background) {
986 RenderWidgetHostViewBase::SetBackground(background);
987 host_->SetBackground(background);
988 window_->layer()->SetFillsBoundsOpaquely(background.isOpaque());
989 }
990
991 #if defined(OS_WIN)
992 gfx::NativeViewAccessible
993 RenderWidgetHostViewAura::AccessibleObjectFromChildId(long child_id) {
994 BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
995 if (!manager)
996 return NULL;
997
998 return manager->ToBrowserAccessibilityManagerWin()->GetFromUniqueIdWin(
999 child_id);
1000 }
1001 #endif // defined(OS_WIN)
1002
1003 void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
1004 current_cursor_ = cursor;
1005 const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
1006 GetDisplayNearestWindow(window_);
1007 current_cursor_.SetDeviceScaleFactor(display.device_scale_factor());
1008 UpdateCursorIfOverSelf();
1009 }
1010
1011 void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
1012 if (is_loading_ && !is_loading && paint_observer_)
1013 paint_observer_->OnPageLoadComplete();
1014 is_loading_ = is_loading;
1015 UpdateCursorIfOverSelf();
1016 }
1017
1018 void RenderWidgetHostViewAura::TextInputTypeChanged(
1019 ui::TextInputType type,
1020 bool can_compose_inline,
1021 ui::TextInputMode input_mode) {
1022 if (text_input_type_ != type ||
1023 can_compose_inline_ != can_compose_inline) {
1024 text_input_type_ = type;
1025 can_compose_inline_ = can_compose_inline;
1026 if (GetInputMethod())
1027 GetInputMethod()->OnTextInputTypeChanged(this);
1028 if (touch_editing_client_)
1029 touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
1030 }
1031 }
1032
1033 void RenderWidgetHostViewAura::ImeCancelComposition() {
1034 if (GetInputMethod())
1035 GetInputMethod()->CancelComposition(this);
1036 has_composition_text_ = false;
1037 }
1038
1039 void RenderWidgetHostViewAura::ImeCompositionRangeChanged(
1040 const ui::Range& range,
1041 const std::vector<gfx::Rect>& character_bounds) {
1042 composition_character_bounds_ = character_bounds;
1043 }
1044
1045 void RenderWidgetHostViewAura::DidUpdateBackingStore(
1046 const gfx::Rect& scroll_rect,
1047 const gfx::Vector2d& scroll_delta,
1048 const std::vector<gfx::Rect>& copy_rects,
1049 const ui::LatencyInfo& latency_info) {
1050 if (accelerated_compositing_state_changed_)
1051 UpdateExternalTexture();
1052
1053 software_latency_info_.MergeWith(latency_info);
1054
1055 // Use the state of the RenderWidgetHost and not the window as the two may
1056 // differ. In particular if the window is hidden but the renderer isn't and we
1057 // ignore the update and the window is made visible again the layer isn't
1058 // marked as dirty and we show the wrong thing.
1059 // We do this after UpdateExternalTexture() so that when we become visible
1060 // we're not drawing a stale texture.
1061 if (host_->is_hidden())
1062 return;
1063
1064 gfx::Rect clip_rect;
1065 if (paint_canvas_) {
1066 SkRect sk_clip_rect;
1067 if (paint_canvas_->sk_canvas()->getClipBounds(&sk_clip_rect))
1068 clip_rect = gfx::ToEnclosingRect(gfx::SkRectToRectF(sk_clip_rect));
1069 }
1070
1071 if (!scroll_rect.IsEmpty())
1072 SchedulePaintIfNotInClip(scroll_rect, clip_rect);
1073
1074 #if defined(OS_WIN)
1075 aura::RootWindow* root_window = window_->GetRootWindow();
1076 #endif
1077 for (size_t i = 0; i < copy_rects.size(); ++i) {
1078 gfx::Rect rect = gfx::SubtractRects(copy_rects[i], scroll_rect);
1079 if (rect.IsEmpty())
1080 continue;
1081
1082 SchedulePaintIfNotInClip(rect, clip_rect);
1083
1084 #if defined(OS_WIN)
1085 if (root_window) {
1086 // Send the invalid rect in screen coordinates.
1087 gfx::Rect screen_rect = GetViewBounds();
1088 gfx::Rect invalid_screen_rect(rect);
1089 invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
1090 HWND hwnd = root_window->GetAcceleratedWidget();
1091 PaintPluginWindowsHelper(hwnd, invalid_screen_rect);
1092 }
1093 #endif // defined(OS_WIN)
1094 }
1095 }
1096
1097 void RenderWidgetHostViewAura::RenderProcessGone(base::TerminationStatus status,
1098 int error_code) {
1099 UpdateCursorIfOverSelf();
1100 Destroy();
1101 }
1102
1103 void RenderWidgetHostViewAura::Destroy() {
1104 // Beware, this function is not called on all destruction paths. It will
1105 // implicitly end up calling ~RenderWidgetHostViewAura though, so all
1106 // destruction/cleanup code should happen there, not here.
1107 in_shutdown_ = true;
1108 delete window_;
1109 }
1110
1111 void RenderWidgetHostViewAura::SetTooltipText(const string16& tooltip_text) {
1112 tooltip_ = tooltip_text;
1113 aura::RootWindow* root_window = window_->GetRootWindow();
1114 aura::client::TooltipClient* tooltip_client =
1115 aura::client::GetTooltipClient(root_window);
1116 if (tooltip_client) {
1117 tooltip_client->UpdateTooltip(window_);
1118 // Content tooltips should be visible indefinitely.
1119 tooltip_client->SetTooltipShownTimeout(window_, 0);
1120 }
1121 }
1122
1123 void RenderWidgetHostViewAura::SelectionChanged(const string16& text,
1124 size_t offset,
1125 const ui::Range& range) {
1126 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
1127
1128 #if defined(USE_X11) && !defined(OS_CHROMEOS)
1129 if (text.empty() || range.is_empty())
1130 return;
1131
1132 // Set the BUFFER_SELECTION to the ui::Clipboard.
1133 ui::ScopedClipboardWriter clipboard_writer(
1134 ui::Clipboard::GetForCurrentThread(),
1135 ui::Clipboard::BUFFER_SELECTION);
1136 clipboard_writer.WriteText(text);
1137 #endif // defined(USE_X11) && !defined(OS_CHROMEOS)
1138 }
1139
1140 void RenderWidgetHostViewAura::SelectionBoundsChanged(
1141 const ViewHostMsg_SelectionBounds_Params& params) {
1142 if (selection_anchor_rect_ == params.anchor_rect &&
1143 selection_focus_rect_ == params.focus_rect)
1144 return;
1145
1146 selection_anchor_rect_ = params.anchor_rect;
1147 selection_focus_rect_ = params.focus_rect;
1148
1149 if (GetInputMethod())
1150 GetInputMethod()->OnCaretBoundsChanged(this);
1151
1152 if (touch_editing_client_) {
1153 touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
1154 selection_focus_rect_);
1155 }
1156 }
1157
1158 void RenderWidgetHostViewAura::ScrollOffsetChanged() {
1159 aura::RootWindow* root = window_->GetRootWindow();
1160 if (!root)
1161 return;
1162 aura::client::CursorClient* cursor_client =
1163 aura::client::GetCursorClient(root);
1164 if (cursor_client && !cursor_client->IsCursorVisible())
1165 cursor_client->DisableMouseEvents();
1166 }
1167
1168 BackingStore* RenderWidgetHostViewAura::AllocBackingStore(
1169 const gfx::Size& size) {
1170 return new BackingStoreAura(host_, size);
1171 }
1172
1173 void RenderWidgetHostViewAura::CopyFromCompositingSurface(
1174 const gfx::Rect& src_subrect,
1175 const gfx::Size& dst_size,
1176 const base::Callback<void(bool, const SkBitmap&)>& callback) {
1177 if (!window_->layer()->has_external_content()) {
1178 callback.Run(false, SkBitmap());
1179 return;
1180 }
1181
1182 const gfx::Size& dst_size_in_pixel = ConvertViewSizeToPixel(this, dst_size);
1183 scoped_ptr<cc::CopyOutputRequest> request =
1184 cc::CopyOutputRequest::CreateRequest(base::Bind(
1185 &RenderWidgetHostViewAura::CopyFromCompositingSurfaceHasResult,
1186 dst_size_in_pixel,
1187 callback));
1188 request->set_area(src_subrect);
1189 window_->layer()->RequestCopyOfOutput(request.Pass());
1190 }
1191
1192 void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
1193 const gfx::Rect& src_subrect,
1194 const scoped_refptr<media::VideoFrame>& target,
1195 const base::Callback<void(bool)>& callback) {
1196 if (!window_->layer()->has_external_content()) {
1197 callback.Run(false);
1198 return;
1199 }
1200
1201 scoped_ptr<cc::CopyOutputRequest> request =
1202 cc::CopyOutputRequest::CreateRequest(base::Bind(
1203 &RenderWidgetHostViewAura::
1204 CopyFromCompositingSurfaceHasResultForVideo,
1205 AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
1206 target,
1207 callback));
1208 request->set_area(src_subrect);
1209 window_->layer()->RequestCopyOfOutput(request.Pass());
1210 }
1211
1212 bool RenderWidgetHostViewAura::CanCopyToVideoFrame() const {
1213 // TODO(skaslev): Implement this path for s/w compositing.
1214 return window_->layer()->has_external_content() &&
1215 host_->is_accelerated_compositing_active();
1216 }
1217
1218 bool RenderWidgetHostViewAura::CanSubscribeFrame() const {
1219 return true;
1220 }
1221
1222 void RenderWidgetHostViewAura::BeginFrameSubscription(
1223 scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
1224 frame_subscriber_ = subscriber.Pass();
1225 }
1226
1227 void RenderWidgetHostViewAura::EndFrameSubscription() {
1228 frame_subscriber_.reset();
1229 }
1230
1231
1232 void RenderWidgetHostViewAura::OnAcceleratedCompositingStateChange() {
1233 // Delay processing the state change until we either get a software frame if
1234 // switching to software mode or receive a buffers swapped notification
1235 // if switching to accelerated mode.
1236 // Sometimes (e.g. on a page load) the renderer will spuriously disable then
1237 // re-enable accelerated compositing, causing us to flash.
1238 // TODO(piman): factor the enable/disable accelerated compositing message into
1239 // the UpdateRect/AcceleratedSurfaceBuffersSwapped messages so that we have
1240 // fewer inconsistent temporary states.
1241 accelerated_compositing_state_changed_ = true;
1242 }
1243
1244 bool RenderWidgetHostViewAura::ShouldSkipFrame(gfx::Size size_in_dip) const {
1245 if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
1246 can_lock_compositor_ == NO_PENDING_COMMIT ||
1247 !resize_lock_.get())
1248 return false;
1249
1250 return size_in_dip != resize_lock_->expected_size();
1251 }
1252
1253 void RenderWidgetHostViewAura::CheckResizeLock() { 1263 void RenderWidgetHostViewAura::CheckResizeLock() {
1254 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_) 1264 if (!resize_lock_ || resize_lock_->expected_size() != current_frame_size_)
1255 return; 1265 return;
1256 1266
1257 // Since we got the size we were looking for, unlock the compositor. But delay 1267 // Since we got the size we were looking for, unlock the compositor. But delay
1258 // the release of the lock until we've kicked a frame with the new texture, to 1268 // the release of the lock until we've kicked a frame with the new texture, to
1259 // avoid resizing the UI before we have a chance to draw a "good" frame. 1269 // avoid resizing the UI before we have a chance to draw a "good" frame.
1260 resize_lock_->UnlockCompositor(); 1270 resize_lock_->UnlockCompositor();
1261 ui::Compositor* compositor = GetCompositor(); 1271 ui::Compositor* compositor = GetCompositor();
1262 if (compositor) { 1272 if (compositor) {
(...skipping 1879 matching lines...) Expand 10 before | Expand all | Expand 10 after
3142 RenderWidgetHost* widget) { 3152 RenderWidgetHost* widget) {
3143 return new RenderWidgetHostViewAura(widget); 3153 return new RenderWidgetHostViewAura(widget);
3144 } 3154 }
3145 3155
3146 // static 3156 // static
3147 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) { 3157 void RenderWidgetHostViewPort::GetDefaultScreenInfo(WebScreenInfo* results) {
3148 GetScreenInfoForWindow(results, NULL); 3158 GetScreenInfoForWindow(results, NULL);
3149 } 3159 }
3150 3160
3151 } // namespace content 3161 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698