diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:01:26 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:01:26 +0000 |
commit | fa5c9a0393065b41c2b81fc20e12ff232cafb17b (patch) | |
tree | e23686f952a7e2e16c5954f05b5028ffde30970b /chrome | |
parent | 12b5d06ea959032da7288b8b2b435adfc2c2cea3 (diff) | |
download | chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.zip chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.tar.gz chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.tar.bz2 |
Add a TabContentsContainerGtk to remove the current hack that inserts the
RenderViewHostGtk native_view() into the widget heiarchy.
(Now we're crashing on cross site instance navigation because it
looks like we aren't updating some internal reference to the new renderer.)
Review URL: http://codereview.chromium.org/21517
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10045 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.scons | 1 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 61 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 26 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.cc | 112 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.h | 59 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_gtk.cc | 3 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_contents.h | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_contents_view_gtk.cc | 9 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_contents_view_gtk.h | 8 |
9 files changed, 254 insertions, 27 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index eedc096..1061973 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -784,6 +784,7 @@ if env.Bit('linux'): 'gtk/nine_box.cc', 'gtk/standard_menus.cc', 'gtk/status_bubble_gtk.cc', + 'gtk/tab_contents_container_gtk.cc', 'process_singleton_linux.cc', 'renderer_host/render_widget_host_view_gtk.cc', 'tab_contents/web_contents_view_gtk.cc', diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index a1fa41e..86bbfa4 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -11,6 +11,7 @@ #include "chrome/browser/gtk/nine_box.h" #include "chrome/browser/gtk/browser_toolbar_view_gtk.h" #include "chrome/browser/gtk/status_bubble_gtk.h" +#include "chrome/browser/gtk/tab_contents_container_gtk.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" #include "chrome/browser/tab_contents/web_contents.h" @@ -57,14 +58,16 @@ gfx::Rect GetInitialWindowBounds(GtkWindow* window) { } // namespace BrowserWindowGtk::BrowserWindowGtk(Browser* browser) - : content_area_(NULL), - browser_(browser), - custom_frame_(false) // TODO(port): make this a pref. -{ + : browser_(browser), + // TODO(port): make this a pref. + custom_frame_(false) { Init(); + browser_->tabstrip_model()->AddObserver(this); } BrowserWindowGtk::~BrowserWindowGtk() { + browser_->tabstrip_model()->RemoveObserver(this); + Close(); } @@ -81,8 +84,8 @@ gboolean BrowserWindowGtk::OnContentAreaExpose(GtkWidget* widget, const int kFramePixels = 2; GdkPixbuf* pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, // alpha - 8, // bit depth + gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, // alpha + 8, // bit depth widget->allocation.width, BrowserToolbarGtk::kToolbarHeight + kFramePixels); @@ -141,6 +144,9 @@ void BrowserWindowGtk::Init() { toolbar_->Init(browser_->profile()); toolbar_->AddToolbarToBox(vbox_); + contents_container_.reset(new TabContentsContainerGtk()); + contents_container_->AddContainerToBox(vbox_); + // Note that calling this the first time is necessary to get the // proper control layout. // TODO(port): make this a pref. @@ -152,15 +158,6 @@ void BrowserWindowGtk::Init() { } void BrowserWindowGtk::Show() { - // TODO(estade): fix this block. As it stands, it is a temporary hack to get - // the browser displaying something. - if (content_area_ == NULL) { - WebContents* contents = (WebContents*)(browser_->GetTabContentsAt(0)); - content_area_ = ((RenderWidgetHostViewGtk*)contents-> - render_view_host()->view())->native_view(); - gtk_box_pack_start(GTK_BOX(vbox_), content_area_, TRUE, TRUE, 0); - } - gtk_widget_show_all(GTK_WIDGET(window_)); } @@ -318,6 +315,40 @@ void BrowserWindowGtk::ShowHTMLDialog(HtmlDialogContentsDelegate* delegate, NOTIMPLEMENTED(); } +void BrowserWindowGtk::TabDetachedAt(TabContents* contents, int index) { + // We use index here rather than comparing |contents| because by this time + // the model has already removed |contents| from its list, so + // browser_->GetSelectedTabContents() will return NULL or something else. + if (index == browser_->tabstrip_model()->selected_index()) { + // TODO(port): Uncoment this line when we get infobars. + // infobar_container_->ChangeTabContents(NULL); + contents_container_->SetTabContents(NULL); + } +} + +void BrowserWindowGtk::TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture) { + DCHECK(old_contents != new_contents); + + // Update various elements that are interested in knowing the current + // TabContents. + // TOOD(port): Un-comment this line when we get infobars. + // infobar_container_->ChangeTabContents(new_contents); + contents_container_->SetTabContents(new_contents); + + new_contents->DidBecomeSelected(); + + // Update all the UI bits. + UpdateTitleBar(); + toolbar_->SetProfile(new_contents->profile()); + UpdateToolbar(new_contents, true); +} + +void BrowserWindowGtk::TabStripEmpty() { +} + void BrowserWindowGtk::DestroyBrowser() { browser_.reset(); } diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 6ff3ce0..70ed990 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -2,24 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_WINDOW_GTK_H_ -#define CHROME_BROWSER_WINDOW_GTK_H_ +#ifndef CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ +#define CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ #include <gtk/gtk.h> #include "base/gfx/rect.h" #include "base/scoped_ptr.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/tabs/tab_strip_model.h" class BrowserToolbarGtk; class NineBox; class StatusBubbleGtk; +class TabContentsContainerGtk; // An implementation of BrowserWindow for GTK. // Cross-platform code will interact with this object when // it needs to manipulate the window. -class BrowserWindowGtk : public BrowserWindow { +class BrowserWindowGtk : public BrowserWindow, + public TabStripModelObserver { public: explicit BrowserWindowGtk(Browser* browser); virtual ~BrowserWindowGtk(); @@ -64,6 +67,14 @@ class BrowserWindowGtk : public BrowserWindow { virtual void ShowHTMLDialog(HtmlDialogContentsDelegate* delegate, void* parent_window); + // Overridden from TabStripModelObserver: + virtual void TabDetachedAt(TabContents* contents, int index); + virtual void TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture); + virtual void TabStripEmpty(); + void OnBoundsChanged(const gfx::Rect& bounds); void OnStateChanged(GdkWindowState state); @@ -71,7 +82,6 @@ class BrowserWindowGtk : public BrowserWindow { virtual void DestroyBrowser(); GtkWindow* window_; GtkWidget* vbox_; - GtkWidget* content_area_; scoped_ptr<Browser> browser_; @@ -96,11 +106,17 @@ class BrowserWindowGtk : public BrowserWindow { // Whether we're drawing the custom Chrome frame (including title bar). bool custom_frame_; + // The object that manages all of the widgets in the toolbar. scoped_ptr<BrowserToolbarGtk> toolbar_; // The status bubble manager. Always non-NULL. scoped_ptr<StatusBubbleGtk> status_bubble_; + + // A container that manages the GtkWidget*s that are the webpage display + // (along with associated infobars, shelves, and other things that are part + // of the content area). + scoped_ptr<TabContentsContainerGtk> contents_container_; }; -#endif // CHROME_BROWSER_WINDOW_GTK_H_ +#endif // CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ diff --git a/chrome/browser/gtk/tab_contents_container_gtk.cc b/chrome/browser/gtk/tab_contents_container_gtk.cc new file mode 100644 index 0000000..9f07b66 --- /dev/null +++ b/chrome/browser/gtk/tab_contents_container_gtk.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2009 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/gtk/tab_contents_container_gtk.h" + +#include "base/gfx/native_widget_types.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" +#include "chrome/common/notification_service.h" + + +TabContentsContainerGtk::TabContentsContainerGtk() + : tab_contents_(NULL), + vbox_(gtk_vbox_new(FALSE, 0)) { +} + +TabContentsContainerGtk::~TabContentsContainerGtk() { + if (tab_contents_) + RemoveObservers(); +} + +void TabContentsContainerGtk::AddContainerToBox(GtkWidget* box) { + gtk_box_pack_start(GTK_BOX(box), vbox_, TRUE, TRUE, 0); +} + +void TabContentsContainerGtk::SetTabContents(TabContents* tab_contents) { + if (tab_contents_) { + gfx::NativeView widget = tab_contents_->GetNativeView(); + if (widget) { + gtk_container_remove(GTK_CONTAINER(vbox_), widget); + } + + tab_contents_->WasHidden(); + + RemoveObservers(); + } + + tab_contents_ = tab_contents; + + // When detaching the last tab of the browser SetTabContents is invoked + // with NULL. Don't attempt to do anything in that case. + if (tab_contents_) { + AddObservers(); + + gfx::NativeView widget = tab_contents_->GetNativeView(); + if (widget) { + gtk_box_pack_start(GTK_BOX(vbox_), widget, TRUE, TRUE, 0); + } + } +} + +void TabContentsContainerGtk::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::RENDER_VIEW_HOST_CHANGED) { + RenderViewHostSwitchedDetails* switched_details = + Details<RenderViewHostSwitchedDetails>(details).ptr(); + RenderViewHostChanged(switched_details->old_host, + switched_details->new_host); + } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { + TabContentsDestroyed(Source<TabContents>(source).ptr()); + } else { + NOTREACHED(); + } +} + +void TabContentsContainerGtk::AddObservers() { + DCHECK(tab_contents_); + if (tab_contents_->AsWebContents()) { + // WebContents can change their RenderViewHost and hence the GtkWidget that + // is shown. I'm not entirely sure that we need to observe this event under + // GTK, but am putting a stub implementation and a comment saying that if + // we crash after that NOTIMPLEMENTED(), we'll need it. + NotificationService::current()->AddObserver( + this, NotificationType::RENDER_VIEW_HOST_CHANGED, + Source<NavigationController>(tab_contents_->controller())); + } + NotificationService::current()->AddObserver( + this, + NotificationType::TAB_CONTENTS_DESTROYED, + Source<TabContents>(tab_contents_)); +} + +void TabContentsContainerGtk::RemoveObservers() { + DCHECK(tab_contents_); + if (tab_contents_->AsWebContents()) { + NotificationService::current()->RemoveObserver( + this, + NotificationType::RENDER_VIEW_HOST_CHANGED, + Source<NavigationController>(tab_contents_->controller())); + } + NotificationService::current()->RemoveObserver( + this, + NotificationType::TAB_CONTENTS_DESTROYED, + Source<TabContents>(tab_contents_)); +} + +void TabContentsContainerGtk::RenderViewHostChanged(RenderViewHost* old_host, + RenderViewHost* new_host) { + // If you find a crash right after this NOTIMPLEMENTED(), we'll need to + // switch out some widgets like in SetTabContents(). + NOTIMPLEMENTED(); +} + +void TabContentsContainerGtk::TabContentsDestroyed(TabContents* contents) { + // Sometimes, a TabContents is destroyed before we know about it. This allows + // us to clean up our state in case this happens. + DCHECK(contents == tab_contents_); + SetTabContents(NULL); +} + diff --git a/chrome/browser/gtk/tab_contents_container_gtk.h b/chrome/browser/gtk/tab_contents_container_gtk.h new file mode 100644 index 0000000..927f1f6 --- /dev/null +++ b/chrome/browser/gtk/tab_contents_container_gtk.h @@ -0,0 +1,59 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ +#define CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ + +#include <gtk/gtk.h> + +#include "base/basictypes.h" +#include "chrome/common/notification_observer.h" + +class RenderViewHost; +class TabContents; + +class TabContentsContainerGtk : public NotificationObserver { + public: + TabContentsContainerGtk(); + ~TabContentsContainerGtk(); + + // Inserts our GtkWidget* hierarchy into a GtkBox managed by our owner. + void AddContainerToBox(GtkWidget* widget); + + // Make the specified tab visible. + void SetTabContents(TabContents* tab_contents); + TabContents* GetTabContents() const { return tab_contents_; } + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + // Add or remove observers for events that we care about. + void AddObservers(); + void RemoveObservers(); + + // Called when the RenderViewHost of the hosted TabContents has changed, e.g. + // to show an interstitial page. + void RenderViewHostChanged(RenderViewHost* old_host, + RenderViewHost* new_host); + + // Called when a TabContents is destroyed. This gives us a chance to clean + // up our internal state if the TabContents is somehow destroyed before we + // get notified. + void TabContentsDestroyed(TabContents* contents); + + // The currently visible TabContents. + TabContents* tab_contents_; + + // We keep a GtkVBox which is inserted into this object's owner's GtkWidget + // hierarchy. We then insert and remove WebContents GtkWidgets into this + // vbox_. + GtkWidget* vbox_; + + DISALLOW_EVIL_CONSTRUCTORS(TabContentsContainerGtk); +}; + +#endif // CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 634ac06..0475c43 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -289,6 +289,8 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { damage_rect.height() }; GdkWindow* window = view_->window; + DCHECK(window) << "Trying to impossibly paint object " << view_; + gdk_window_begin_paint_rect(window, &grect); skia::PlatformDeviceLinux &platdev = @@ -299,7 +301,6 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { cairo_set_source_surface(cairo_drawable, bitdev->surface(), 0, 0); cairo_paint(cairo_drawable); cairo_destroy(cairo_drawable); - gdk_window_end_paint(window); } else { NOTIMPLEMENTED(); diff --git a/chrome/browser/tab_contents/web_contents.h b/chrome/browser/tab_contents/web_contents.h index c02292c..52b48fe 100644 --- a/chrome/browser/tab_contents/web_contents.h +++ b/chrome/browser/tab_contents/web_contents.h @@ -400,6 +400,8 @@ class WebContents : public TabContents, friend class WebContentsViewWin; #elif defined(OS_MACOSX) friend class WebContentsViewMac; +#elif defined(OS_LINUX) + friend class WebContentsViewGtk; #endif // So InterstitialPage can access SetIsLoading. diff --git a/chrome/browser/tab_contents/web_contents_view_gtk.cc b/chrome/browser/tab_contents/web_contents_view_gtk.cc index 4add84a..22b450f 100644 --- a/chrome/browser/tab_contents/web_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/web_contents_view_gtk.cc @@ -4,6 +4,8 @@ #include "chrome/browser/tab_contents/web_contents_view_gtk.h" +#include <gtk/gtk.h> + #include "base/gfx/point.h" #include "base/gfx/rect.h" #include "chrome/browser/renderer_host/render_view_host.h" @@ -16,7 +18,8 @@ WebContentsView* WebContentsView::Create(WebContents* web_contents) { } WebContentsViewGtk::WebContentsViewGtk(WebContents* web_contents) - : web_contents_(web_contents) { + : web_contents_(web_contents), + vbox_(gtk_vbox_new(FALSE, 0)) { } WebContentsViewGtk::~WebContentsViewGtk() { @@ -36,12 +39,12 @@ RenderWidgetHostView* WebContentsViewGtk::CreateViewForWidget( RenderWidgetHostViewGtk* view = new RenderWidgetHostViewGtk(render_widget_host); // TODO(port): do we need to do any extra setup? + gtk_box_pack_start(GTK_BOX(vbox_), view->native_view(), TRUE, TRUE, 0); return view; } gfx::NativeView WebContentsViewGtk::GetNativeView() const { - NOTIMPLEMENTED(); - return NULL; + return vbox_; } gfx::NativeView WebContentsViewGtk::GetContentNativeView() const { diff --git a/chrome/browser/tab_contents/web_contents_view_gtk.h b/chrome/browser/tab_contents/web_contents_view_gtk.h index f10df5c..a4273f5 100644 --- a/chrome/browser/tab_contents/web_contents_view_gtk.h +++ b/chrome/browser/tab_contents/web_contents_view_gtk.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_WIN_H_ -#define CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_WIN_H_ +#ifndef CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_GTK_H_ +#define CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_GTK_H_ #include "chrome/browser/tab_contents/web_contents_view.h" @@ -61,8 +61,10 @@ class WebContentsViewGtk : public WebContentsView { private: WebContents* web_contents_; + GtkWidget* vbox_; + DISALLOW_COPY_AND_ASSIGN(WebContentsViewGtk); }; -#endif // CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_WIN_H_ +#endif // CHROME_BROWSER_TAB_CONTENTS_WEB_CONTENTS_VIEW_GTK_H_ |