diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-06 18:45:56 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-06 18:45:56 +0000 |
commit | 7b9627d188d04b224f972fae709e7cb4f61ae504 (patch) | |
tree | 4d37368f881c9dae023e5172013e87f0b7c58676 /chrome/browser/tab_contents | |
parent | 72baf67602ab1dbf95c34a5d8301e0ac5f8b8b41 (diff) | |
download | chromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.zip chromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.tar.gz chromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.tar.bz2 |
Render a "sad tab" on tab crash.
Uses the NotificationRegistrar to notice TAB_CONTENTS_[DIS]CONNECTED events. When it disconnects, add a SadTabGtk to the TabContentsView. Delete it when the tab contents reconnects.
BUG=http://www.crbug.com/11081
TEST=Open http://about:crash. Verify that the sad tab renders properly. Navigate to another page to make sure the SadTabGtk is correctly replaced with a new RenderWidgetHostViewGtk.
Review URL: http://codereview.chromium.org/111003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15435 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.cc | 62 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents_view_gtk.h | 21 |
2 files changed, 65 insertions, 18 deletions
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index 9c82b47..a55c8fe 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -11,6 +11,7 @@ #include "base/gfx/point.h" #include "base/gfx/rect.h" #include "chrome/browser/gtk/browser_window_gtk.h" +#include "chrome/browser/gtk/sad_tab_gtk.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_view_host_factory.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" @@ -18,6 +19,8 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/gtk_util.h" +#include "chrome/common/notification_source.h" +#include "chrome/common/notification_type.h" namespace { @@ -62,8 +65,11 @@ TabContentsView* TabContentsView::Create(TabContents* tab_contents) { TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) : TabContentsView(tab_contents), - vbox_(gtk_vbox_new(FALSE, 0)), - content_view_(NULL) { + vbox_(gtk_vbox_new(FALSE, 0)) { + registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, + Source<TabContents>(tab_contents)); + registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED, + Source<TabContents>(tab_contents)); } TabContentsViewGtk::~TabContentsViewGtk() { @@ -89,19 +95,19 @@ RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget( RenderWidgetHostViewGtk* view = new RenderWidgetHostViewGtk(render_widget_host); view->InitAsChild(); - content_view_ = view->native_view(); - g_signal_connect(content_view_, "focus", + gfx::NativeView content_view = view->native_view(); + g_signal_connect(content_view, "focus", G_CALLBACK(OnFocus), tab_contents()); - g_signal_connect(view->native_view(), "leave-notify-event", + g_signal_connect(content_view, "leave-notify-event", G_CALLBACK(OnLeaveNotify), tab_contents()); - g_signal_connect(view->native_view(), "motion-notify-event", + g_signal_connect(content_view, "motion-notify-event", G_CALLBACK(OnMouseMove), tab_contents()); - gtk_widget_add_events(view->native_view(), GDK_LEAVE_NOTIFY_MASK | + gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect(view->native_view(), "button-press-event", + g_signal_connect(content_view, "button-press-event", G_CALLBACK(OnMouseDown), this); gfx::RemoveAllChildren(vbox_.get()); - gtk_box_pack_start(GTK_BOX(vbox_.get()), content_view_, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbox_.get()), content_view, TRUE, TRUE, 0); return view; } @@ -110,9 +116,12 @@ gfx::NativeView TabContentsViewGtk::GetNativeView() const { } gfx::NativeView TabContentsViewGtk::GetContentNativeView() const { - return content_view_; + if (!tab_contents()->render_widget_host_view()) + return NULL; + return tab_contents()->render_widget_host_view()->GetPluginNativeView(); } + gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const { GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW); return window ? GTK_WINDOW(window) : NULL; @@ -135,12 +144,13 @@ void TabContentsViewGtk::OnContentsDestroy() { 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). - if (content_view_ && content_view_->window) - gdk_window_set_title(content_view_->window, WideToUTF8(title).c_str()); + gfx::NativeView content_view = GetContentNativeView(); + if (content_view && content_view->window) + gdk_window_set_title(content_view->window, WideToUTF8(title).c_str()); } void TabContentsViewGtk::Invalidate() { - NOTIMPLEMENTED(); + gtk_widget_queue_draw(sad_tab_->widget()); } void TabContentsViewGtk::SizeContents(const gfx::Size& size) { @@ -173,7 +183,7 @@ void TabContentsViewGtk::SetInitialFocus() { if (tab_contents()->FocusLocationBarByDefault()) tab_contents()->delegate()->SetFocusToLocationBar(); else - gtk_widget_grab_focus(content_view_); + gtk_widget_grab_focus(GetContentNativeView()); } void TabContentsViewGtk::StoreFocus() { @@ -224,6 +234,30 @@ void TabContentsViewGtk::OnFindReply(int request_id, NOTIMPLEMENTED(); } +void TabContentsViewGtk::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::TAB_CONTENTS_CONNECTED: { + // No need to remove the SadTabGtk's widget from the container since + // the new RenderWidgetHostViewGtk instance already removed all the + // vbox's children. + sad_tab_.reset(); + break; + } + case NotificationType::TAB_CONTENTS_DISCONNECTED: { + sad_tab_.reset(new SadTabGtk); + gtk_box_pack_start( + GTK_BOX(vbox_.get()), sad_tab_->widget(), TRUE, TRUE, 0); + gtk_widget_show(sad_tab_->widget()); + break; + } + default: + NOTREACHED() << "Got a notification we didn't register for."; + break; + } +} + void TabContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) { context_menu_.reset(new RenderViewContextMenuGtk(tab_contents(), params, last_mouse_down_time_)); diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h index 6d24598..4137f67 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.h +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h @@ -7,11 +7,15 @@ #include "base/scoped_ptr.h" #include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" #include "chrome/common/owned_widget_gtk.h" class RenderViewContextMenuGtk; +class SadTabGtk; -class TabContentsViewGtk : public TabContentsView { +class TabContentsViewGtk : public TabContentsView, + public NotificationObserver { public: // The corresponding TabContents is passed in the constructor, and manages our // lifetime. This doesn't need to be the case, but is this way currently @@ -55,6 +59,13 @@ class TabContentsViewGtk : public TabContentsView { const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update); + + // NotificationObserver implementation --------------------------------------- + + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + private: // We keep track of the timestamp of the latest mousedown event. static gboolean OnMouseDown(GtkWidget* widget, @@ -63,9 +74,6 @@ class TabContentsViewGtk : public TabContentsView { // The native widget for the tab. OwnedWidgetGtk vbox_; - // The native widget for the contents of the tab. We do not own this widget. - GtkWidget* content_view_; - // The context menu is reset every time we show it, but we keep a pointer to // between uses so that it won't go out of scope before we're done with it. scoped_ptr<RenderViewContextMenuGtk> context_menu_; @@ -74,6 +82,11 @@ class TabContentsViewGtk : public TabContentsView { // show context menus. guint32 last_mouse_down_time_; + // Used to get notifications about renderers coming and going. + NotificationRegistrar registrar_; + + scoped_ptr<SadTabGtk> sad_tab_; + DISALLOW_COPY_AND_ASSIGN(TabContentsViewGtk); }; |