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

Side by Side Diff: content/browser/tab_contents/tab_contents_view_gtk.cc

Issue 10031044: TabContents -> WebContentsImpl, part 5. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase (fixed) Created 8 years, 8 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/tab_contents/tab_contents_view_gtk.h"
6
7 #include <gdk/gdk.h>
8 #include <gdk/gdkkeysyms.h>
9 #include <gtk/gtk.h>
10
11 #include <algorithm>
12
13 #include "base/string_util.h"
14 #include "base/utf_string_conversions.h"
15 #include "build/build_config.h"
16 #include "content/browser/renderer_host/render_view_host_factory.h"
17 #include "content/browser/renderer_host/render_view_host_impl.h"
18 #include "content/browser/renderer_host/render_widget_host_view_gtk.h"
19 #include "content/browser/tab_contents/tab_contents.h"
20 #include "content/browser/web_contents/interstitial_page_impl.h"
21 #include "content/browser/web_contents/web_drag_dest_gtk.h"
22 #include "content/browser/web_contents/web_drag_source_gtk.h"
23 #include "content/public/browser/web_contents_delegate.h"
24 #include "content/public/browser/web_contents_view_delegate.h"
25 #include "ui/base/gtk/gtk_expanded_container.h"
26 #include "ui/gfx/point.h"
27 #include "ui/gfx/rect.h"
28 #include "ui/gfx/size.h"
29 #include "webkit/glue/webdropdata.h"
30
31 using WebKit::WebDragOperation;
32 using WebKit::WebDragOperationsMask;
33 using content::RenderWidgetHost;
34 using content::WebContents;
35
36 namespace {
37
38 // Called when the mouse leaves the widget. We notify our delegate.
39 gboolean OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event,
40 TabContents* tab_contents) {
41 if (tab_contents->GetDelegate())
42 tab_contents->GetDelegate()->ContentsMouseEvent(
43 tab_contents, gfx::Point(event->x_root, event->y_root), false);
44 return FALSE;
45 }
46
47 // Called when the mouse moves within the widget. We notify our delegate.
48 gboolean OnMouseMove(GtkWidget* widget, GdkEventMotion* event,
49 TabContents* tab_contents) {
50 if (tab_contents->GetDelegate())
51 tab_contents->GetDelegate()->ContentsMouseEvent(
52 tab_contents, gfx::Point(event->x_root, event->y_root), true);
53 return FALSE;
54 }
55
56 // See tab_contents_view_views.cc for discussion of mouse scroll zooming.
57 gboolean OnMouseScroll(GtkWidget* widget, GdkEventScroll* event,
58 TabContents* tab_contents) {
59 if ((event->state & gtk_accelerator_get_default_mod_mask()) !=
60 GDK_CONTROL_MASK) {
61 return FALSE;
62 }
63
64 content::WebContentsDelegate* delegate = tab_contents->GetDelegate();
65 if (!delegate)
66 return FALSE;
67
68 if (!(event->direction == GDK_SCROLL_DOWN ||
69 event->direction == GDK_SCROLL_UP)) {
70 return FALSE;
71 }
72
73 delegate->ContentsZoomChange(event->direction == GDK_SCROLL_UP);
74 return TRUE;
75 }
76
77 } // namespace
78
79 namespace content {
80
81 TabContentsViewGtk::TabContentsViewGtk(
82 TabContents* tab_contents,
83 content::WebContentsViewDelegate* delegate)
84 : tab_contents_(tab_contents),
85 expanded_(gtk_expanded_container_new()),
86 delegate_(delegate) {
87 gtk_widget_set_name(expanded_.get(), "chrome-tab-contents-view");
88 g_signal_connect(expanded_.get(), "size-allocate",
89 G_CALLBACK(OnSizeAllocateThunk), this);
90 g_signal_connect(expanded_.get(), "child-size-request",
91 G_CALLBACK(OnChildSizeRequestThunk), this);
92
93 gtk_widget_show(expanded_.get());
94 drag_source_.reset(new content::WebDragSourceGtk(tab_contents));
95
96 if (delegate_.get())
97 delegate_->Initialize(expanded_.get(), &focus_store_);
98 }
99
100 TabContentsViewGtk::~TabContentsViewGtk() {
101 expanded_.Destroy();
102 }
103
104 void TabContentsViewGtk::CreateView(const gfx::Size& initial_size) {
105 requested_size_ = initial_size;
106 }
107
108 RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget(
109 RenderWidgetHost* render_widget_host) {
110 if (render_widget_host->GetView()) {
111 // During testing, the view will already be set up in most cases to the
112 // test view, so we don't want to clobber it with a real one. To verify that
113 // this actually is happening (and somebody isn't accidentally creating the
114 // view twice), we check for the RVH Factory, which will be set when we're
115 // making special ones (which go along with the special views).
116 DCHECK(RenderViewHostFactory::has_factory());
117 return render_widget_host->GetView();
118 }
119
120 RenderWidgetHostView* view =
121 RenderWidgetHostView::CreateViewForWidget(render_widget_host);
122 view->InitAsChild(NULL);
123 gfx::NativeView content_view = view->GetNativeView();
124 g_signal_connect(content_view, "focus", G_CALLBACK(OnFocusThunk), this);
125 g_signal_connect(content_view, "leave-notify-event",
126 G_CALLBACK(OnLeaveNotify), tab_contents_);
127 g_signal_connect(content_view, "motion-notify-event",
128 G_CALLBACK(OnMouseMove), tab_contents_);
129 g_signal_connect(content_view, "scroll-event",
130 G_CALLBACK(OnMouseScroll), tab_contents_);
131 gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK |
132 GDK_POINTER_MOTION_MASK);
133 InsertIntoContentArea(content_view);
134
135 // Renderer target DnD.
136 drag_dest_.reset(new content::WebDragDestGtk(tab_contents_, content_view));
137
138 if (delegate_.get())
139 drag_dest_->set_delegate(delegate_->GetDragDestDelegate());
140
141 return view;
142 }
143
144 gfx::NativeView TabContentsViewGtk::GetNativeView() const {
145 if (delegate_.get())
146 return delegate_->GetNativeView();
147
148 return expanded_.get();
149 }
150
151 gfx::NativeView TabContentsViewGtk::GetContentNativeView() const {
152 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
153 if (!rwhv)
154 return NULL;
155 return rwhv->GetNativeView();
156 }
157
158 gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const {
159 GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
160 return window ? GTK_WINDOW(window) : NULL;
161 }
162
163 void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const {
164 // This is used for positioning the download shelf arrow animation,
165 // as well as sizing some other widgets in Windows. In GTK the size is
166 // managed for us, so it appears to be only used for the download shelf
167 // animation.
168 int x = 0;
169 int y = 0;
170 GdkWindow* expanded_window = gtk_widget_get_window(expanded_.get());
171 if (expanded_window)
172 gdk_window_get_origin(expanded_window, &x, &y);
173
174 GtkAllocation allocation;
175 gtk_widget_get_allocation(expanded_.get(), &allocation);
176 out->SetRect(x + allocation.x, y + allocation.y,
177 requested_size_.width(), requested_size_.height());
178 }
179
180 void TabContentsViewGtk::SetPageTitle(const string16& title) {
181 // Set the window name to include the page title so it's easier to spot
182 // when debugging (e.g. via xwininfo -tree).
183 gfx::NativeView content_view = GetContentNativeView();
184 if (content_view) {
185 GdkWindow* content_window = gtk_widget_get_window(content_view);
186 if (content_window) {
187 gdk_window_set_title(content_window, UTF16ToUTF8(title).c_str());
188 }
189 }
190 }
191
192 void TabContentsViewGtk::OnTabCrashed(base::TerminationStatus status,
193 int error_code) {
194 }
195
196 void TabContentsViewGtk::SizeContents(const gfx::Size& size) {
197 // We don't need to manually set the size of of widgets in GTK+, but we do
198 // need to pass the sizing information on to the RWHV which will pass the
199 // sizing information on to the renderer.
200 requested_size_ = size;
201 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
202 if (rwhv)
203 rwhv->SetSize(size);
204 }
205
206 void TabContentsViewGtk::RenderViewCreated(content::RenderViewHost* host) {
207 }
208
209 void TabContentsViewGtk::Focus() {
210 if (tab_contents_->ShowingInterstitialPage()) {
211 tab_contents_->GetInterstitialPage()->Focus();
212 } else if (delegate_.get()) {
213 delegate_->Focus();
214 }
215 }
216
217 void TabContentsViewGtk::SetInitialFocus() {
218 if (tab_contents_->FocusLocationBarByDefault())
219 tab_contents_->SetFocusToLocationBar(false);
220 else
221 Focus();
222 }
223
224 void TabContentsViewGtk::StoreFocus() {
225 focus_store_.Store(GetNativeView());
226 }
227
228 void TabContentsViewGtk::RestoreFocus() {
229 if (focus_store_.widget())
230 gtk_widget_grab_focus(focus_store_.widget());
231 else
232 SetInitialFocus();
233 }
234
235 bool TabContentsViewGtk::IsDoingDrag() const {
236 return false;
237 }
238
239 void TabContentsViewGtk::CancelDragAndCloseTab() {
240 }
241
242 bool TabContentsViewGtk::IsEventTracking() const {
243 return false;
244 }
245
246 void TabContentsViewGtk::CloseTabAfterEventTracking() {
247 }
248
249 void TabContentsViewGtk::GetViewBounds(gfx::Rect* out) const {
250 GdkWindow* window = gtk_widget_get_window(GetNativeView());
251 if (!window) {
252 out->SetRect(0, 0, requested_size_.width(), requested_size_.height());
253 return;
254 }
255 int x = 0, y = 0, w, h;
256 gdk_window_get_geometry(window, &x, &y, &w, &h, NULL);
257 out->SetRect(x, y, w, h);
258 }
259
260 WebContents* TabContentsViewGtk::web_contents() {
261 return tab_contents_;
262 }
263
264 void TabContentsViewGtk::UpdateDragCursor(WebDragOperation operation) {
265 drag_dest_->UpdateDragStatus(operation);
266 }
267
268 void TabContentsViewGtk::GotFocus() {
269 // This is only used in the views FocusManager stuff but it bleeds through
270 // all subclasses. http://crbug.com/21875
271 }
272
273 // This is called when the renderer asks us to take focus back (i.e., it has
274 // iterated past the last focusable element on the page).
275 void TabContentsViewGtk::TakeFocus(bool reverse) {
276 if (!tab_contents_->GetDelegate())
277 return;
278 if (!tab_contents_->GetDelegate()->TakeFocus(reverse)) {
279 gtk_widget_child_focus(GTK_WIDGET(GetTopLevelNativeWindow()),
280 reverse ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
281 }
282 }
283
284 void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) {
285 gtk_container_add(GTK_CONTAINER(expanded_.get()), widget);
286 }
287
288 // Called when the content view gtk widget is tabbed to, or after the call to
289 // gtk_widget_child_focus() in TakeFocus(). We return true
290 // and grab focus if we don't have it. The call to
291 // FocusThroughTabTraversal(bool) forwards the "move focus forward" effect to
292 // webkit.
293 gboolean TabContentsViewGtk::OnFocus(GtkWidget* widget,
294 GtkDirectionType focus) {
295 // Give our view wrapper first chance at this event.
296 if (delegate_.get()) {
297 gboolean return_value = FALSE;
298 if (delegate_->OnNativeViewFocusEvent(widget, focus, &return_value))
299 return return_value;
300 }
301
302 // If we already have focus, let the next widget have a shot at it. We will
303 // reach this situation after the call to gtk_widget_child_focus() in
304 // TakeFocus().
305 if (gtk_widget_is_focus(widget))
306 return FALSE;
307
308 gtk_widget_grab_focus(widget);
309 bool reverse = focus == GTK_DIR_TAB_BACKWARD;
310 tab_contents_->FocusThroughTabTraversal(reverse);
311 return TRUE;
312 }
313
314 void TabContentsViewGtk::CreateNewWindow(
315 int route_id,
316 const ViewHostMsg_CreateWindow_Params& params) {
317 tab_contents_view_helper_.CreateNewWindow(tab_contents_, route_id, params);
318 }
319
320 void TabContentsViewGtk::CreateNewWidget(
321 int route_id, WebKit::WebPopupType popup_type) {
322 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
323 route_id,
324 false,
325 popup_type);
326 }
327
328 void TabContentsViewGtk::CreateNewFullscreenWidget(int route_id) {
329 tab_contents_view_helper_.CreateNewWidget(tab_contents_,
330 route_id,
331 true,
332 WebKit::WebPopupTypeNone);
333 }
334
335 void TabContentsViewGtk::ShowCreatedWindow(int route_id,
336 WindowOpenDisposition disposition,
337 const gfx::Rect& initial_pos,
338 bool user_gesture) {
339 tab_contents_view_helper_.ShowCreatedWindow(
340 tab_contents_, route_id, disposition, initial_pos, user_gesture);
341 }
342
343 void TabContentsViewGtk::ShowCreatedWidget(
344 int route_id, const gfx::Rect& initial_pos) {
345 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
346 route_id,
347 false,
348 initial_pos);
349 }
350
351 void TabContentsViewGtk::ShowCreatedFullscreenWidget(int route_id) {
352 tab_contents_view_helper_.ShowCreatedWidget(tab_contents_,
353 route_id,
354 true,
355 gfx::Rect());
356 }
357
358 void TabContentsViewGtk::ShowContextMenu(
359 const content::ContextMenuParams& params) {
360 // Allow delegates to handle the context menu operation first.
361 if (web_contents()->GetDelegate() &&
362 web_contents()->GetDelegate()->HandleContextMenu(params)) {
363 return;
364 }
365
366 if (delegate_.get())
367 delegate_->ShowContextMenu(params);
368 else
369 DLOG(ERROR) << "Cannot show context menus without a delegate.";
370 }
371
372 void TabContentsViewGtk::ShowPopupMenu(const gfx::Rect& bounds,
373 int item_height,
374 double item_font_size,
375 int selected_item,
376 const std::vector<WebMenuItem>& items,
377 bool right_aligned) {
378 // We are not using external popup menus on Linux, they are rendered by
379 // WebKit.
380 NOTREACHED();
381 }
382
383 // Render view DnD -------------------------------------------------------------
384
385 void TabContentsViewGtk::StartDragging(const WebDropData& drop_data,
386 WebDragOperationsMask ops,
387 const SkBitmap& image,
388 const gfx::Point& image_offset) {
389 DCHECK(GetContentNativeView());
390
391 RenderWidgetHostViewGtk* view_gtk = static_cast<RenderWidgetHostViewGtk*>(
392 tab_contents_->GetRenderWidgetHostView());
393 if (!view_gtk || !view_gtk->GetLastMouseDown())
394 return;
395
396 drag_source_->StartDragging(drop_data, ops, view_gtk->GetLastMouseDown(),
397 image, image_offset);
398 }
399
400 // -----------------------------------------------------------------------------
401
402 void TabContentsViewGtk::OnChildSizeRequest(GtkWidget* widget,
403 GtkWidget* child,
404 GtkRequisition* requisition) {
405 if (tab_contents_->GetDelegate()) {
406 requisition->height +=
407 tab_contents_->GetDelegate()->GetExtraRenderViewHeight();
408 }
409 }
410
411 void TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget,
412 GtkAllocation* allocation) {
413 int width = allocation->width;
414 int height = allocation->height;
415 // |delegate()| can be NULL here during browser teardown.
416 if (tab_contents_->GetDelegate())
417 height += tab_contents_->GetDelegate()->GetExtraRenderViewHeight();
418 gfx::Size size(width, height);
419 requested_size_ = size;
420
421 // We manually tell our RWHV to resize the renderer content. This avoids
422 // spurious resizes from GTK+.
423 RenderWidgetHostView* rwhv = tab_contents_->GetRenderWidgetHostView();
424 if (rwhv)
425 rwhv->SetSize(size);
426 if (tab_contents_->GetInterstitialPage())
427 tab_contents_->GetInterstitialPage()->SetSize(size);
428 }
429
430 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698