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

Unified Diff: chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc

Issue 7015051: Re-land: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc
===================================================================
--- chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc (revision 85284)
+++ chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc (working copy)
@@ -1,488 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.h"
-
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "chrome/browser/download/download_shelf.h"
-#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
-#include "chrome/browser/tab_contents/web_drag_dest_gtk.h"
-#include "chrome/browser/ui/gtk/constrained_window_gtk.h"
-#include "chrome/browser/ui/gtk/tab_contents_drag_source.h"
-#include "chrome/browser/ui/views/sad_tab_view.h"
-#include "chrome/browser/ui/views/tab_contents/render_view_context_menu_views.h"
-#include "content/browser/renderer_host/render_view_host.h"
-#include "content/browser/renderer_host/render_view_host_factory.h"
-#include "content/browser/tab_contents/interstitial_page.h"
-#include "content/browser/tab_contents/tab_contents.h"
-#include "content/browser/tab_contents/tab_contents_delegate.h"
-#include "ui/gfx/canvas_skia_paint.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
-#include "views/controls/native/native_view_host.h"
-#include "views/focus/view_storage.h"
-#include "views/screen.h"
-#include "views/widget/root_view.h"
-#include "views/widget/widget_gtk.h"
-
-using WebKit::WebDragOperation;
-using WebKit::WebDragOperationsMask;
-using WebKit::WebInputEvent;
-
-
-namespace {
-
-// Called when the content view gtk widget is tabbed to, or after the call to
-// gtk_widget_child_focus() in TakeFocus(). We return true
-// and grab focus if we don't have it. The call to
-// FocusThroughTabTraversal(bool) forwards the "move focus forward" effect to
-// webkit.
-gboolean OnFocus(GtkWidget* widget, GtkDirectionType focus,
- TabContents* tab_contents) {
- // If we already have focus, let the next widget have a shot at it. We will
- // reach this situation after the call to gtk_widget_child_focus() in
- // TakeFocus().
- if (gtk_widget_is_focus(widget))
- return FALSE;
-
- gtk_widget_grab_focus(widget);
- bool reverse = focus == GTK_DIR_TAB_BACKWARD;
- tab_contents->FocusThroughTabTraversal(reverse);
- return TRUE;
-}
-
-// Called when the mouse leaves the widget. We notify our delegate.
-// WidgetGtk also defines OnLeaveNotify, so we use the name OnLeaveNotify2
-// here.
-gboolean OnLeaveNotify2(GtkWidget* widget, GdkEventCrossing* event,
- TabContents* tab_contents) {
- if (tab_contents->delegate())
- tab_contents->delegate()->ContentsMouseEvent(
- tab_contents, views::Screen::GetCursorScreenPoint(), false);
- return FALSE;
-}
-
-// Called when the mouse moves within the widget.
-gboolean CallMouseMove(GtkWidget* widget, GdkEventMotion* event,
- TabContentsViewGtk* tab_contents_view) {
- return tab_contents_view->OnMouseMove(widget, event);
-}
-
-// See tab_contents_view_gtk.cc for discussion of mouse scroll zooming.
-gboolean OnMouseScroll(GtkWidget* widget, GdkEventScroll* event,
- TabContents* tab_contents) {
- if ((event->state & gtk_accelerator_get_default_mod_mask()) ==
- GDK_CONTROL_MASK) {
- if (tab_contents->delegate()) {
- if (event->direction == GDK_SCROLL_DOWN) {
- tab_contents->delegate()->ContentsZoomChange(false);
- return TRUE;
- } else if (event->direction == GDK_SCROLL_UP) {
- tab_contents->delegate()->ContentsZoomChange(true);
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-} // namespace
-
-// static
-TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
- return new TabContentsViewGtk(tab_contents);
-}
-
-TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents)
- : TabContentsView(tab_contents),
- sad_tab_(NULL),
- ignore_next_char_event_(false) {
- drag_source_.reset(new TabContentsDragSource(this));
- last_focused_view_storage_id_ =
- views::ViewStorage::GetInstance()->CreateStorageID();
-}
-
-TabContentsViewGtk::~TabContentsViewGtk() {
- // Make sure to remove any stored view we may still have in the ViewStorage.
- //
- // It is possible the view went away before us, so we only do this if the
- // view is registered.
- views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
- if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
- view_storage->RemoveView(last_focused_view_storage_id_);
-
- // Just deleting the object doesn't destroy the GtkWidget. We need to do that
- // manually, and synchronously, since subsequent signal handlers may expect
- // to locate this object.
- CloseNow();
-}
-
-void TabContentsViewGtk::AttachConstrainedWindow(
- ConstrainedWindowGtk* constrained_window) {
- DCHECK(find(constrained_windows_.begin(), constrained_windows_.end(),
- constrained_window) == constrained_windows_.end());
-
- constrained_windows_.push_back(constrained_window);
- AddChild(constrained_window->widget());
-
- gfx::Rect bounds;
- GetContainerBounds(&bounds);
- SetFloatingPosition(bounds.size());
-}
-
-void TabContentsViewGtk::RemoveConstrainedWindow(
- ConstrainedWindowGtk* constrained_window) {
- std::vector<ConstrainedWindowGtk*>::iterator item =
- find(constrained_windows_.begin(), constrained_windows_.end(),
- constrained_window);
- DCHECK(item != constrained_windows_.end());
- RemoveChild((*item)->widget());
- constrained_windows_.erase(item);
-}
-
-void TabContentsViewGtk::CreateView(const gfx::Size& initial_size) {
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
- params.delete_on_destroy = false;
- params.bounds = gfx::Rect(initial_size);
- GetWidget()->Init(params);
- // We need to own the widget in order to attach/detach the native view
- // to container.
- gtk_object_ref(GTK_OBJECT(GetNativeView()));
-}
-
-RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget(
- RenderWidgetHost* render_widget_host) {
- if (render_widget_host->view()) {
- // During testing, the view will already be set up in most cases to the
- // test view, so we don't want to clobber it with a real one. To verify that
- // this actually is happening (and somebody isn't accidentally creating the
- // view twice), we check for the RVH Factory, which will be set when we're
- // making special ones (which go along with the special views).
- DCHECK(RenderViewHostFactory::has_factory());
- return render_widget_host->view();
- }
-
- // If we were showing sad tab, remove it now.
- if (sad_tab_ != NULL) {
- SetContentsView(new views::View());
- sad_tab_ = NULL;
- }
-
- RenderWidgetHostViewGtk* view =
- new RenderWidgetHostViewGtk(render_widget_host);
- view->InitAsChild();
- g_signal_connect(view->native_view(), "focus",
- G_CALLBACK(OnFocus), tab_contents());
- g_signal_connect(view->native_view(), "leave-notify-event",
- G_CALLBACK(OnLeaveNotify2), tab_contents());
- g_signal_connect(view->native_view(), "motion-notify-event",
- G_CALLBACK(CallMouseMove), this);
- g_signal_connect(view->native_view(), "scroll-event",
- G_CALLBACK(OnMouseScroll), tab_contents());
- gtk_widget_add_events(view->native_view(), GDK_LEAVE_NOTIFY_MASK |
- GDK_POINTER_MOTION_MASK);
-
- // Let widget know that the tab contents has been painted.
- views::WidgetGtk::RegisterChildExposeHandler(view->native_view());
-
- // Renderer target DnD.
- if (tab_contents()->ShouldAcceptDragAndDrop())
- drag_dest_.reset(new WebDragDestGtk(tab_contents(), view->native_view()));
-
- gtk_fixed_put(GTK_FIXED(GetNativeView()), view->native_view(), 0, 0);
- return view;
-}
-
-gfx::NativeView TabContentsViewGtk::GetNativeView() const {
- return WidgetGtk::GetNativeView();
-}
-
-gfx::NativeView TabContentsViewGtk::GetContentNativeView() const {
- RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
- if (!rwhv)
- return NULL;
- return rwhv->GetNativeView();
-}
-
-gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const {
- GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
- return window ? GTK_WINDOW(window) : NULL;
-}
-
-void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const {
- // Callers expect the requested bounds not the actual bounds. For example,
- // during init callers expect 0x0, but Gtk layout enforces a min size of 1x1.
- *out = GetClientAreaScreenBounds();
-
- gfx::Size size;
- WidgetGtk::GetRequestedSize(&size);
- out->set_size(size);
-}
-
-void TabContentsViewGtk::StartDragging(const WebDropData& drop_data,
- WebDragOperationsMask ops,
- const SkBitmap& image,
- const gfx::Point& image_offset) {
- drag_source_->StartDragging(drop_data, ops, &last_mouse_down_,
- image, image_offset);
-}
-
-void TabContentsViewGtk::SetPageTitle(const std::wstring& title) {
- // Set the window name to include the page title so it's easier to spot
- // when debugging (e.g. via xwininfo -tree).
- gfx::NativeView content_view = GetContentNativeView();
- if (content_view && content_view->window)
- gdk_window_set_title(content_view->window, WideToUTF8(title).c_str());
-}
-
-void TabContentsViewGtk::OnTabCrashed(base::TerminationStatus status,
- int /* error_code */) {
- SadTabView::Kind kind =
- status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
- SadTabView::KILLED : SadTabView::CRASHED;
- sad_tab_ = new SadTabView(tab_contents(), kind);
- SetContentsView(sad_tab_);
-}
-
-void TabContentsViewGtk::SizeContents(const gfx::Size& size) {
- // TODO(brettw) this is a hack and should be removed. See tab_contents_view.h.
-
- // We're contained in a fixed. To have the fixed relay us out to |size|, set
- // the size request, which triggers OnSizeAllocate.
- gtk_widget_set_size_request(GetNativeView(), size.width(), size.height());
-
- // We need to send this immediately.
- RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
- if (rwhv)
- rwhv->SetSize(size);
-}
-
-void TabContentsViewGtk::Focus() {
- if (tab_contents()->interstitial_page()) {
- tab_contents()->interstitial_page()->Focus();
- return;
- }
-
- if (tab_contents()->is_crashed() && sad_tab_ != NULL) {
- sad_tab_->RequestFocus();
- return;
- }
-
- if (constrained_windows_.size()) {
- constrained_windows_.back()->FocusConstrainedWindow();
- return;
- }
-
- RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
- gtk_widget_grab_focus(rwhv ? rwhv->GetNativeView() : GetNativeView());
-}
-
-void TabContentsViewGtk::SetInitialFocus() {
- if (tab_contents()->FocusLocationBarByDefault())
- tab_contents()->SetFocusToLocationBar(false);
- else
- Focus();
-}
-
-void TabContentsViewGtk::StoreFocus() {
- views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
-
- if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
- view_storage->RemoveView(last_focused_view_storage_id_);
-
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
- if (focus_manager) {
- // |focus_manager| can be NULL if the tab has been detached but still
- // exists.
- views::View* focused_view = focus_manager->GetFocusedView();
- if (focused_view)
- view_storage->StoreView(last_focused_view_storage_id_, focused_view);
- }
-}
-
-void TabContentsViewGtk::RestoreFocus() {
- views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
- views::View* last_focused_view =
- view_storage->RetrieveView(last_focused_view_storage_id_);
- if (!last_focused_view) {
- SetInitialFocus();
- } else {
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
-
- // If you hit this DCHECK, please report it to Jay (jcampan).
- DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";
-
- if (last_focused_view->IsFocusableInRootView() && focus_manager &&
- focus_manager->ContainsView(last_focused_view)) {
- last_focused_view->RequestFocus();
- } else {
- // The focused view may not belong to the same window hierarchy (e.g.
- // if the location bar was focused and the tab is dragged out), or it may
- // no longer be focusable (e.g. if the location bar was focused and then
- // we switched to fullscreen mode). In that case we default to the
- // default focus.
- SetInitialFocus();
- }
- view_storage->RemoveView(last_focused_view_storage_id_);
- }
-}
-
-void TabContentsViewGtk::GetViewBounds(gfx::Rect* out) const {
- *out = GetWindowScreenBounds();
-}
-
-void TabContentsViewGtk::UpdateDragCursor(WebDragOperation operation) {
- if (drag_dest_.get())
- drag_dest_->UpdateDragStatus(operation);
-}
-
-void TabContentsViewGtk::GotFocus() {
- if (tab_contents()->delegate())
- tab_contents()->delegate()->TabContentsFocused(tab_contents());
-}
-
-void TabContentsViewGtk::TakeFocus(bool reverse) {
- if (tab_contents()->delegate() &&
- !tab_contents()->delegate()->TakeFocus(reverse)) {
-
- views::FocusManager* focus_manager =
- views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
-
- // We may not have a focus manager if the tab has been switched before this
- // message arrived.
- if (focus_manager)
- focus_manager->AdvanceFocus(reverse);
- }
-}
-
-void TabContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) {
- // Allow delegates to handle the context menu operation first.
- if (tab_contents()->delegate()->HandleContextMenu(params))
- return;
-
- context_menu_.reset(new RenderViewContextMenuViews(tab_contents(), params));
- context_menu_->Init();
-
- gfx::Point screen_point(params.x, params.y);
- views::View::ConvertPointToScreen(GetRootView(), &screen_point);
-
- // Enable recursive tasks on the message loop so we can get updates while
- // the context menu is being displayed.
- bool old_state = MessageLoop::current()->NestableTasksAllowed();
- MessageLoop::current()->SetNestableTasksAllowed(true);
- context_menu_->RunMenuAt(screen_point.x(), screen_point.y());
- MessageLoop::current()->SetNestableTasksAllowed(old_state);
-}
-
-void TabContentsViewGtk::ShowPopupMenu(const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<WebMenuItem>& items,
- bool right_aligned) {
- // External popup menus are only used on Mac.
- NOTREACHED();
-}
-
-gboolean TabContentsViewGtk::OnButtonPress(GtkWidget* widget,
- GdkEventButton* event) {
- last_mouse_down_ = *event;
- return views::WidgetGtk::OnButtonPress(widget, event);
-}
-
-void TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget,
- GtkAllocation* allocation) {
- gfx::Size new_size(allocation->width, allocation->height);
-
- // Always call WasSized() to allow checking to make sure the
- // RenderWidgetHostView is the right size.
- WasSized(new_size);
-}
-
-gboolean TabContentsViewGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) {
- if (tab_contents()->render_view_host() &&
- !tab_contents()->render_view_host()->IsRenderViewLive() &&
- sad_tab_) {
- gfx::CanvasSkiaPaint canvas(event);
- sad_tab_->Paint(&canvas);
- }
- return false; // False indicates other widgets should get the event as well.
-}
-
-void TabContentsViewGtk::OnShow(GtkWidget* widget) {
- WasShown();
-}
-
-void TabContentsViewGtk::OnHide(GtkWidget* widget) {
- WasHidden();
-}
-
-void TabContentsViewGtk::WasHidden() {
- tab_contents()->HideContents();
-}
-
-void TabContentsViewGtk::WasShown() {
- tab_contents()->ShowContents();
-}
-
-void TabContentsViewGtk::WasSized(const gfx::Size& size) {
- // We have to check that the RenderWidgetHostView is the proper size.
- // It can be wrong in cases where the renderer has died and the host
- // view needed to be recreated.
- bool needs_resize = size != size_;
-
- if (needs_resize) {
- size_ = size;
- if (tab_contents()->interstitial_page())
- tab_contents()->interstitial_page()->SetSize(size);
- }
-
- RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
- if (rwhv && rwhv->GetViewBounds().size() != size)
- rwhv->SetSize(size);
- if (sad_tab_ && sad_tab_->size() != size)
- sad_tab_->SetSize(size);
-
- if (needs_resize)
- SetFloatingPosition(size);
-}
-
-void TabContentsViewGtk::SetFloatingPosition(const gfx::Size& size) {
- // Place each ConstrainedWindow in the center of the view.
- int half_view_width = size.width() / 2;
-
- typedef std::vector<ConstrainedWindowGtk*>::iterator iterator;
-
- for (iterator f = constrained_windows_.begin(),
- l = constrained_windows_.end(); f != l; ++f) {
- GtkWidget* widget = (*f)->widget();
-
- GtkRequisition requisition;
- gtk_widget_size_request(widget, &requisition);
-
- int child_x = std::max(half_view_width - (requisition.width / 2), 0);
- PositionChild(widget, child_x, 0, 0, 0);
- }
-}
-
-// Called when the mouse moves within the widget. We notify SadTabView if it's
-// not NULL, else our delegate.
-gboolean TabContentsViewGtk::OnMouseMove(GtkWidget* widget,
- GdkEventMotion* event) {
- if (sad_tab_ != NULL)
- WidgetGtk::OnMotionNotify(widget, event);
- else if (tab_contents()->delegate())
- tab_contents()->delegate()->ContentsMouseEvent(
- tab_contents(), views::Screen::GetCursorScreenPoint(), true);
- return FALSE;
-}

Powered by Google App Engine
This is Rietveld 408576698