| 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;
|
| -}
|
|
|