OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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. |
| 4 |
| 5 #include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h" |
| 6 |
| 7 #include "base/string_util.h" |
| 8 #include "build/build_config.h" |
| 9 #include "chrome/browser/download/download_shelf.h" |
| 10 #include "chrome/browser/renderer_host/render_view_host.h" |
| 11 #include "chrome/browser/renderer_host/render_view_host_factory.h" |
| 12 #include "chrome/browser/renderer_host/render_widget_host_view_views.h" |
| 13 #include "chrome/browser/tab_contents/interstitial_page.h" |
| 14 #include "chrome/browser/tab_contents/tab_contents.h" |
| 15 #include "chrome/browser/tab_contents/tab_contents_delegate.h" |
| 16 #include "chrome/browser/views/sad_tab_view.h" |
| 17 #include "chrome/browser/views/tab_contents/render_view_context_menu_views.h" |
| 18 #include "gfx/canvas_skia_paint.h" |
| 19 #include "gfx/point.h" |
| 20 #include "gfx/rect.h" |
| 21 #include "gfx/size.h" |
| 22 #include "views/controls/native/native_view_host.h" |
| 23 #include "views/fill_layout.h" |
| 24 #include "views/focus/focus_manager.h" |
| 25 #include "views/focus/view_storage.h" |
| 26 #include "views/screen.h" |
| 27 #include "views/widget/widget.h" |
| 28 |
| 29 using WebKit::WebDragOperation; |
| 30 using WebKit::WebDragOperationsMask; |
| 31 using WebKit::WebInputEvent; |
| 32 |
| 33 // static |
| 34 TabContentsView* TabContentsView::Create(TabContents* tab_contents) { |
| 35 return new TabContentsViewViews(tab_contents); |
| 36 } |
| 37 |
| 38 TabContentsViewViews::TabContentsViewViews(TabContents* tab_contents) |
| 39 : TabContentsView(tab_contents), |
| 40 sad_tab_(NULL), |
| 41 ignore_next_char_event_(false) { |
| 42 last_focused_view_storage_id_ = |
| 43 views::ViewStorage::GetSharedInstance()->CreateStorageID(); |
| 44 SetLayoutManager(new views::FillLayout()); |
| 45 } |
| 46 |
| 47 TabContentsViewViews::~TabContentsViewViews() { |
| 48 // Make sure to remove any stored view we may still have in the ViewStorage. |
| 49 // |
| 50 // It is possible the view went away before us, so we only do this if the |
| 51 // view is registered. |
| 52 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); |
| 53 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) |
| 54 view_storage->RemoveView(last_focused_view_storage_id_); |
| 55 } |
| 56 |
| 57 void TabContentsViewViews::AttachConstrainedWindow( |
| 58 ConstrainedWindowGtk* constrained_window) { |
| 59 // TODO(anicolao): reimplement all dialogs as DOMUI |
| 60 NOTIMPLEMENTED(); |
| 61 } |
| 62 |
| 63 void TabContentsViewViews::RemoveConstrainedWindow( |
| 64 ConstrainedWindowGtk* constrained_window) { |
| 65 // TODO(anicolao): reimplement all dialogs as DOMUI |
| 66 NOTIMPLEMENTED(); |
| 67 } |
| 68 |
| 69 void TabContentsViewViews::CreateView(const gfx::Size& initial_size) { |
| 70 SetBounds(gfx::Rect(bounds().origin(), initial_size)); |
| 71 } |
| 72 |
| 73 RenderWidgetHostView* TabContentsViewViews::CreateViewForWidget( |
| 74 RenderWidgetHost* render_widget_host) { |
| 75 if (render_widget_host->view()) { |
| 76 // During testing, the view will already be set up in most cases to the |
| 77 // test view, so we don't want to clobber it with a real one. To verify that |
| 78 // this actually is happening (and somebody isn't accidentally creating the |
| 79 // view twice), we check for the RVH Factory, which will be set when we're |
| 80 // making special ones (which go along with the special views). |
| 81 DCHECK(RenderViewHostFactory::has_factory()); |
| 82 return render_widget_host->view(); |
| 83 } |
| 84 |
| 85 // If we were showing sad tab, remove it now. |
| 86 if (sad_tab_ != NULL) { |
| 87 RemoveChildView(sad_tab_); |
| 88 AddChildView(new views::View()); |
| 89 sad_tab_ = NULL; |
| 90 } |
| 91 |
| 92 RenderWidgetHostViewViews* view = |
| 93 new RenderWidgetHostViewViews(render_widget_host); |
| 94 AddChildView(view); |
| 95 view->Show(); |
| 96 view->InitAsChild(); |
| 97 |
| 98 // TODO(anicolao): implement drag'n'drop hooks if needed |
| 99 |
| 100 return view; |
| 101 } |
| 102 |
| 103 gfx::NativeView TabContentsViewViews::GetNativeView() const { |
| 104 return GetWidget()->GetNativeView(); |
| 105 } |
| 106 |
| 107 gfx::NativeView TabContentsViewViews::GetContentNativeView() const { |
| 108 RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView(); |
| 109 if (!rwhv) |
| 110 return NULL; |
| 111 return rwhv->GetNativeView(); |
| 112 } |
| 113 |
| 114 gfx::NativeWindow TabContentsViewViews::GetTopLevelNativeWindow() const { |
| 115 GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW); |
| 116 return window ? GTK_WINDOW(window) : NULL; |
| 117 } |
| 118 |
| 119 void TabContentsViewViews::GetContainerBounds(gfx::Rect* out) const { |
| 120 *out = bounds(); |
| 121 } |
| 122 |
| 123 void TabContentsViewViews::StartDragging(const WebDropData& drop_data, |
| 124 WebDragOperationsMask ops, |
| 125 const SkBitmap& image, |
| 126 const gfx::Point& image_offset) { |
| 127 // TODO(anicolao): implement dragging |
| 128 } |
| 129 |
| 130 void TabContentsViewViews::SetPageTitle(const std::wstring& title) { |
| 131 // TODO(anicolao): figure out if there's anything useful to do here |
| 132 } |
| 133 |
| 134 void TabContentsViewViews::OnTabCrashed() { |
| 135 } |
| 136 |
| 137 void TabContentsViewViews::SizeContents(const gfx::Size& size) { |
| 138 WasSized(size); |
| 139 |
| 140 // We need to send this immediately. |
| 141 RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView(); |
| 142 if (rwhv) |
| 143 rwhv->SetSize(size); |
| 144 } |
| 145 |
| 146 void TabContentsViewViews::Focus() { |
| 147 if (tab_contents()->interstitial_page()) { |
| 148 tab_contents()->interstitial_page()->Focus(); |
| 149 return; |
| 150 } |
| 151 |
| 152 if (tab_contents()->is_crashed() && sad_tab_ != NULL) { |
| 153 sad_tab_->RequestFocus(); |
| 154 return; |
| 155 } |
| 156 |
| 157 RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView(); |
| 158 gtk_widget_grab_focus(rwhv ? rwhv->GetNativeView() : GetNativeView()); |
| 159 } |
| 160 |
| 161 void TabContentsViewViews::SetInitialFocus() { |
| 162 if (tab_contents()->FocusLocationBarByDefault()) |
| 163 tab_contents()->SetFocusToLocationBar(false); |
| 164 else |
| 165 Focus(); |
| 166 } |
| 167 |
| 168 void TabContentsViewViews::StoreFocus() { |
| 169 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); |
| 170 |
| 171 if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL) |
| 172 view_storage->RemoveView(last_focused_view_storage_id_); |
| 173 |
| 174 views::FocusManager* focus_manager = |
| 175 views::FocusManager::GetFocusManagerForNativeView(GetNativeView()); |
| 176 if (focus_manager) { |
| 177 // |focus_manager| can be NULL if the tab has been detached but still |
| 178 // exists. |
| 179 views::View* focused_view = focus_manager->GetFocusedView(); |
| 180 if (focused_view) |
| 181 view_storage->StoreView(last_focused_view_storage_id_, focused_view); |
| 182 } |
| 183 } |
| 184 |
| 185 void TabContentsViewViews::RestoreFocus() { |
| 186 views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance(); |
| 187 views::View* last_focused_view = |
| 188 view_storage->RetrieveView(last_focused_view_storage_id_); |
| 189 if (!last_focused_view) { |
| 190 SetInitialFocus(); |
| 191 } else { |
| 192 views::FocusManager* focus_manager = |
| 193 views::FocusManager::GetFocusManagerForNativeView(GetNativeView()); |
| 194 |
| 195 // If you hit this DCHECK, please report it to Jay (jcampan). |
| 196 DCHECK(focus_manager != NULL) << "No focus manager when restoring focus."; |
| 197 |
| 198 if (last_focused_view->IsFocusableInRootView() && focus_manager && |
| 199 focus_manager->ContainsView(last_focused_view)) { |
| 200 last_focused_view->RequestFocus(); |
| 201 } else { |
| 202 // The focused view may not belong to the same window hierarchy (e.g. |
| 203 // if the location bar was focused and the tab is dragged out), or it may |
| 204 // no longer be focusable (e.g. if the location bar was focused and then |
| 205 // we switched to fullscreen mode). In that case we default to the |
| 206 // default focus. |
| 207 SetInitialFocus(); |
| 208 } |
| 209 view_storage->RemoveView(last_focused_view_storage_id_); |
| 210 } |
| 211 } |
| 212 |
| 213 void TabContentsViewViews::Paint(gfx::Canvas* canvas) { |
| 214 } |
| 215 |
| 216 void TabContentsViewViews::UpdateDragCursor(WebDragOperation operation) { |
| 217 NOTIMPLEMENTED(); |
| 218 // It's not even clear a drag cursor will make sense for touch. |
| 219 // TODO(anicolao): implement dragging |
| 220 } |
| 221 |
| 222 void TabContentsViewViews::GotFocus() { |
| 223 if (tab_contents()->delegate()) |
| 224 tab_contents()->delegate()->TabContentsFocused(tab_contents()); |
| 225 } |
| 226 |
| 227 void TabContentsViewViews::TakeFocus(bool reverse) { |
| 228 if (tab_contents()->delegate() && |
| 229 !tab_contents()->delegate()->TakeFocus(reverse)) { |
| 230 |
| 231 views::FocusManager* focus_manager = |
| 232 views::FocusManager::GetFocusManagerForNativeView(GetNativeView()); |
| 233 |
| 234 // We may not have a focus manager if the tab has been switched before this |
| 235 // message arrived. |
| 236 if (focus_manager) |
| 237 focus_manager->AdvanceFocus(reverse); |
| 238 } |
| 239 } |
| 240 |
| 241 void TabContentsViewViews::VisibilityChanged(views::View *, bool is_visible) { |
| 242 if (is_visible) { |
| 243 WasShown(); |
| 244 } else { |
| 245 WasHidden(); |
| 246 } |
| 247 } |
| 248 |
| 249 void TabContentsViewViews::ShowContextMenu(const ContextMenuParams& params) { |
| 250 // Allow delegates to handle the context menu operation first. |
| 251 if (tab_contents()->delegate()->HandleContextMenu(params)) |
| 252 return; |
| 253 |
| 254 // TODO(anicolao): implement context menus for touch |
| 255 NOTIMPLEMENTED(); |
| 256 } |
| 257 |
| 258 void TabContentsViewViews::ShowPopupMenu(const gfx::Rect& bounds, |
| 259 int item_height, |
| 260 double item_font_size, |
| 261 int selected_item, |
| 262 const std::vector<WebMenuItem>& items, |
| 263 bool right_aligned) { |
| 264 // External popup menus are only used on Mac. |
| 265 NOTREACHED(); |
| 266 } |
| 267 |
| 268 void TabContentsViewViews::WasHidden() { |
| 269 tab_contents()->HideContents(); |
| 270 } |
| 271 |
| 272 void TabContentsViewViews::WasShown() { |
| 273 tab_contents()->ShowContents(); |
| 274 } |
| 275 |
| 276 void TabContentsViewViews::WasSized(const gfx::Size& size) { |
| 277 // We have to check that the RenderWidgetHostView is the proper size. |
| 278 // It can be wrong in cases where the renderer has died and the host |
| 279 // view needed to be recreated. |
| 280 bool needs_resize = size != size_; |
| 281 |
| 282 if (needs_resize) { |
| 283 size_ = size; |
| 284 if (tab_contents()->interstitial_page()) |
| 285 tab_contents()->interstitial_page()->SetSize(size); |
| 286 } |
| 287 |
| 288 RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView(); |
| 289 if (rwhv && rwhv->GetViewBounds().size() != size) |
| 290 rwhv->SetSize(size); |
| 291 |
| 292 if (needs_resize) |
| 293 SetFloatingPosition(size); |
| 294 } |
| 295 |
| 296 void TabContentsViewViews::SetFloatingPosition(const gfx::Size& size) { |
| 297 // TODO(anicolao): rework this once we have DOMUI views for dialogs |
| 298 SetBounds(x(), y(), size.width(), size.height()); |
| 299 } |
OLD | NEW |