This source file includes following definitions.
- OnLeaveNotify
- OnMouseMove
- OnMouseScroll
- CreateWebContentsView
- delegate_
- GetNativeView
- GetContentNativeView
- GetTopLevelNativeWindow
- GetContainerBounds
- OnTabCrashed
- Focus
- SetInitialFocus
- StoreFocus
- RestoreFocus
- GetDropData
- GetViewBounds
- CreateView
- CreateViewForWidget
- CreateViewForPopupWidget
- SetPageTitle
- SizeContents
- RenderViewCreated
- RenderViewSwappedIn
- SetOverscrollControllerEnabled
- web_contents
- UpdateDragCursor
- GotFocus
- TakeFocus
- InsertIntoContentArea
- UpdateDragDest
- OnFocus
- ShowContextMenu
- StartDragging
- OnChildSizeRequest
- OnSizeAllocate
#include "content/browser/web_contents/web_contents_view_gtk.h"
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <algorithm>
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_gtk.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_drag_dest_gtk.h"
#include "content/browser/web_contents/web_drag_source_gtk.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view_delegate.h"
#include "content/public/common/drop_data.h"
#include "ui/base/gtk/gtk_expanded_container.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
using blink::WebDragOperation;
using blink::WebDragOperationsMask;
namespace content {
namespace {
gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event,
WebContentsImpl* web_contents) {
if (web_contents->GetDelegate())
web_contents->GetDelegate()->ContentsMouseEvent(
web_contents, gfx::Point(event->x_root, event->y_root), false);
return FALSE;
}
gboolean OnMouseMove(GtkWidget* widget, GdkEventMotion* event,
WebContentsImpl* web_contents) {
if (web_contents->GetDelegate())
web_contents->GetDelegate()->ContentsMouseEvent(
web_contents, gfx::Point(event->x_root, event->y_root), true);
return FALSE;
}
gboolean OnMouseScroll(GtkWidget* widget, GdkEventScroll* event,
WebContentsImpl* web_contents) {
if ((event->state & gtk_accelerator_get_default_mod_mask()) !=
GDK_CONTROL_MASK) {
return FALSE;
}
WebContentsDelegate* delegate = web_contents->GetDelegate();
if (!delegate)
return FALSE;
if (!(event->direction == GDK_SCROLL_DOWN ||
event->direction == GDK_SCROLL_UP)) {
return FALSE;
}
delegate->ContentsZoomChange(event->direction == GDK_SCROLL_UP);
return TRUE;
}
}
WebContentsViewPort* CreateWebContentsView(
WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate,
RenderViewHostDelegateView** render_view_host_delegate_view) {
WebContentsViewGtk* rv = new WebContentsViewGtk(web_contents, delegate);
*render_view_host_delegate_view = rv;
return rv;
}
WebContentsViewGtk::WebContentsViewGtk(
WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
expanded_(gtk_expanded_container_new()),
delegate_(delegate) {
gtk_widget_set_name(expanded_.get(), "chrome-web-contents-view");
g_signal_connect(expanded_.get(), "size-allocate",
G_CALLBACK(OnSizeAllocateThunk), this);
g_signal_connect(expanded_.get(), "child-size-request",
G_CALLBACK(OnChildSizeRequestThunk), this);
gtk_widget_show(expanded_.get());
drag_source_.reset(new WebDragSourceGtk(web_contents));
if (delegate_)
delegate_->Initialize(expanded_.get(), &focus_store_);
}
WebContentsViewGtk::~WebContentsViewGtk() {
expanded_.Destroy();
}
gfx::NativeView WebContentsViewGtk::GetNativeView() const {
if (delegate_)
return delegate_->GetNativeView();
return expanded_.get();
}
gfx::NativeView WebContentsViewGtk::GetContentNativeView() const {
RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
if (!rwhv)
return NULL;
return rwhv->GetNativeView();
}
gfx::NativeWindow WebContentsViewGtk::GetTopLevelNativeWindow() const {
GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
return window ? GTK_WINDOW(window) : NULL;
}
void WebContentsViewGtk::GetContainerBounds(gfx::Rect* out) const {
int x = 0;
int y = 0;
GdkWindow* expanded_window = gtk_widget_get_window(expanded_.get());
if (expanded_window)
gdk_window_get_origin(expanded_window, &x, &y);
GtkAllocation allocation;
gtk_widget_get_allocation(expanded_.get(), &allocation);
out->SetRect(x + allocation.x, y + allocation.y,
requested_size_.width(), requested_size_.height());
}
void WebContentsViewGtk::OnTabCrashed(base::TerminationStatus status,
int error_code) {
}
void WebContentsViewGtk::Focus() {
if (web_contents_->ShowingInterstitialPage()) {
web_contents_->GetInterstitialPage()->Focus();
} else if (delegate_) {
delegate_->Focus();
}
}
void WebContentsViewGtk::SetInitialFocus() {
if (web_contents_->FocusLocationBarByDefault())
web_contents_->SetFocusToLocationBar(false);
else
Focus();
}
void WebContentsViewGtk::StoreFocus() {
focus_store_.Store(GetNativeView());
}
void WebContentsViewGtk::RestoreFocus() {
if (focus_store_.widget())
gtk_widget_grab_focus(focus_store_.widget());
else
SetInitialFocus();
}
DropData* WebContentsViewGtk::GetDropData() const {
if (!drag_dest_)
return NULL;
return drag_dest_->current_drop_data();
}
gfx::Rect WebContentsViewGtk::GetViewBounds() const {
gfx::Rect rect;
GdkWindow* window = gtk_widget_get_window(GetNativeView());
if (!window) {
rect.SetRect(0, 0, requested_size_.width(), requested_size_.height());
return rect;
}
int x = 0, y = 0, w, h;
gdk_window_get_geometry(window, &x, &y, &w, &h, NULL);
rect.SetRect(x, y, w, h);
return rect;
}
void WebContentsViewGtk::CreateView(
const gfx::Size& initial_size, gfx::NativeView context) {
requested_size_ = initial_size;
}
RenderWidgetHostView* WebContentsViewGtk::CreateViewForWidget(
RenderWidgetHost* render_widget_host) {
if (render_widget_host->GetView()) {
DCHECK(RenderViewHostFactory::has_factory());
return render_widget_host->GetView();
}
RenderWidgetHostView* view =
RenderWidgetHostView::CreateViewForWidget(render_widget_host);
view->InitAsChild(NULL);
gfx::NativeView content_view = view->GetNativeView();
g_signal_connect(content_view, "focus", G_CALLBACK(OnFocusThunk), this);
g_signal_connect(content_view, "leave-notify-event",
G_CALLBACK(OnLeaveNotify), web_contents_);
g_signal_connect(content_view, "motion-notify-event",
G_CALLBACK(OnMouseMove), web_contents_);
g_signal_connect(content_view, "scroll-event",
G_CALLBACK(OnMouseScroll), web_contents_);
gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
InsertIntoContentArea(content_view);
if (render_widget_host->IsRenderView()) {
RenderViewHost* rvh = RenderViewHost::From(render_widget_host);
if (rvh == web_contents_->GetRenderViewHost()) {
UpdateDragDest(rvh);
}
}
return view;
}
RenderWidgetHostView* WebContentsViewGtk::CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) {
return RenderWidgetHostViewPort::CreateViewForWidget(render_widget_host);
}
void WebContentsViewGtk::SetPageTitle(const base::string16& title) {
gfx::NativeView content_view = GetContentNativeView();
if (content_view) {
GdkWindow* content_window = gtk_widget_get_window(content_view);
if (content_window) {
gdk_window_set_title(content_window, base::UTF16ToUTF8(title).c_str());
}
}
}
void WebContentsViewGtk::SizeContents(const gfx::Size& size) {
requested_size_ = size;
RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetSize(size);
}
void WebContentsViewGtk::RenderViewCreated(RenderViewHost* host) {
}
void WebContentsViewGtk::RenderViewSwappedIn(RenderViewHost* host) {
UpdateDragDest(host);
}
void WebContentsViewGtk::SetOverscrollControllerEnabled(bool enabled) {
}
WebContents* WebContentsViewGtk::web_contents() {
return web_contents_;
}
void WebContentsViewGtk::UpdateDragCursor(WebDragOperation operation) {
if (!drag_dest_)
return;
drag_dest_->UpdateDragStatus(operation);
}
void WebContentsViewGtk::GotFocus() {
}
void WebContentsViewGtk::TakeFocus(bool reverse) {
if (!web_contents_->GetDelegate())
return;
if (!web_contents_->GetDelegate()->TakeFocus(web_contents_, reverse) &&
GetTopLevelNativeWindow()) {
gtk_widget_child_focus(GTK_WIDGET(GetTopLevelNativeWindow()),
reverse ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
}
}
void WebContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) {
gtk_container_add(GTK_CONTAINER(expanded_.get()), widget);
}
void WebContentsViewGtk::UpdateDragDest(RenderViewHost* host) {
if (host->GetProcess() && host->GetProcess()->IsGuest()) {
DCHECK(!drag_dest_);
return;
}
gfx::NativeView content_view = host->GetView()->GetNativeView();
if (drag_dest_.get() && drag_dest_->widget() == content_view)
return;
drag_dest_.reset();
drag_dest_.reset(new WebDragDestGtk(web_contents_, content_view));
if (delegate_)
drag_dest_->set_delegate(delegate_->GetDragDestDelegate());
}
gboolean WebContentsViewGtk::OnFocus(GtkWidget* widget,
GtkDirectionType focus) {
if (delegate_) {
gboolean return_value = FALSE;
if (delegate_->OnNativeViewFocusEvent(widget, focus, &return_value))
return return_value;
}
if (gtk_widget_is_focus(widget))
return FALSE;
gtk_widget_grab_focus(widget);
bool reverse = focus == GTK_DIR_TAB_BACKWARD;
web_contents_->FocusThroughTabTraversal(reverse);
return TRUE;
}
void WebContentsViewGtk::ShowContextMenu(RenderFrameHost* render_frame_host,
const ContextMenuParams& params) {
if (delegate_)
delegate_->ShowContextMenu(render_frame_host, params);
else
DLOG(ERROR) << "Cannot show context menus without a delegate.";
}
void WebContentsViewGtk::StartDragging(const DropData& drop_data,
WebDragOperationsMask ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const DragEventSourceInfo& event_info) {
DCHECK(GetContentNativeView());
RenderWidgetHostViewGtk* view_gtk = static_cast<RenderWidgetHostViewGtk*>(
web_contents_->GetRenderWidgetHostView());
if (!view_gtk || !view_gtk->GetLastMouseDown() ||
!drag_source_->StartDragging(drop_data, ops, view_gtk->GetLastMouseDown(),
*image.bitmap(), image_offset)) {
web_contents_->SystemDragEnded();
}
}
void WebContentsViewGtk::OnChildSizeRequest(GtkWidget* widget,
GtkWidget* child,
GtkRequisition* requisition) {
if (web_contents_->GetDelegate()) {
requisition->height +=
web_contents_->GetDelegate()->GetExtraRenderViewHeight();
}
}
void WebContentsViewGtk::OnSizeAllocate(GtkWidget* widget,
GtkAllocation* allocation) {
int width = allocation->width;
int height = allocation->height;
if (web_contents_->GetDelegate())
height += web_contents_->GetDelegate()->GetExtraRenderViewHeight();
gfx::Size size(width, height);
requested_size_ = size;
RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetSize(size);
if (web_contents_->GetInterstitialPage())
web_contents_->GetInterstitialPage()->SetSize(size);
}
}