diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-25 13:40:00 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-25 13:40:00 +0000 |
commit | f119a6358337a5efeb51b66ec5918338c17ed8e6 (patch) | |
tree | b35f6603ec4a43dd79df6cb28df6fe5ce0430fae | |
parent | 9b4735c21892765929ca69d1a4a122ca1e1e4ca5 (diff) | |
download | chromium_src-f119a6358337a5efeb51b66ec5918338c17ed8e6.zip chromium_src-f119a6358337a5efeb51b66ec5918338c17ed8e6.tar.gz chromium_src-f119a6358337a5efeb51b66ec5918338c17ed8e6.tar.bz2 |
Changes the main menu to do the following:
. Creates a TabContents in CreateNewWindow rather than a
RenderViewHost. We want to support the ability to open popups from
this menu, so going with TabContents directly seemed the best
option.
. Showing the menu now does a keyboard grab. This is needed so that
keyboard events go to the menu and focus doesn't remain whever it
was when the menu was shown.
BUG=22954
TEST=see bug
Review URL: http://codereview.chromium.org/219037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27179 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/main_menu.cc | 87 | ||||
-rw-r--r-- | chrome/browser/chromeos/main_menu.h | 82 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_delegate_helper.cc | 2 |
3 files changed, 130 insertions, 41 deletions
diff --git a/chrome/browser/chromeos/main_menu.cc b/chrome/browser/chromeos/main_menu.cc index 08fc0b2..3127a46 100644 --- a/chrome/browser/chromeos/main_menu.cc +++ b/chrome/browser/chromeos/main_menu.cc @@ -5,12 +5,14 @@ #include "chrome/browser/chromeos/main_menu.h" #include "app/resource_bundle.h" +#include "base/message_loop.h" #include "chrome/browser/browser.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.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" #include "chrome/browser/renderer_host/site_instance.h" +#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -31,21 +33,18 @@ void MainMenu::Show(Browser* browser) { (new MainMenu(browser))->ShowImpl(); } +MainMenu::~MainMenu() { + popup_->Close(); + menu_rvh_->Shutdown(); +} + MainMenu::MainMenu(Browser* browser) : browser_(browser), popup_(NULL), site_instance_(NULL), menu_rvh_(NULL), rwhv_(NULL), - child_rvh_(NULL) { -} - -MainMenu::~MainMenu() { - gdk_pointer_ungrab(GDK_CURRENT_TIME); - popup_->Close(); - menu_rvh_->Shutdown(); - if (child_rvh_) - child_rvh_->Shutdown(); + ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)) { } void MainMenu::ShowImpl() { @@ -84,12 +83,33 @@ void MainMenu::ShowImpl() { g_signal_connect(rwhv_widget, "button-press-event", G_CALLBACK(CallButtonPressEvent), this); // Do a mouse grab on the renderer widget host view's widget so that we can - // close the popup if the user clicks anywhere else. + // close the popup if the user clicks anywhere else. And do a keyboard + // grab so that we get all key events. gdk_pointer_grab(rwhv_widget->window, FALSE, static_cast<GdkEventMask>( GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK), NULL, NULL, GDK_CURRENT_TIME); + gdk_keyboard_grab(rwhv_widget->window, FALSE, GDK_CURRENT_TIME); +} + +void MainMenu::Delete(bool now) { + gdk_keyboard_ungrab(GDK_CURRENT_TIME); + gdk_pointer_ungrab(GDK_CURRENT_TIME); + // Hide the popup immediately. We don't close it as it contains the + // renderwidgethostview, which hasn't been shutdown yet. + popup_->Hide(); + if (now) + delete this; + else + MessageLoop::current()->DeleteSoon(FROM_HERE, this); +} + +// static +gboolean MainMenu::CallButtonPressEvent(GtkWidget* widget, + GdkEventButton* event, + MainMenu* menu) { + return menu->OnButtonPressEvent(widget, event); } gboolean MainMenu::OnButtonPressEvent(GtkWidget* widget, @@ -99,27 +119,46 @@ gboolean MainMenu::OnButtonPressEvent(GtkWidget* widget, event->y >= widget->allocation.height) { // The user clicked outside the bounds of the menu, delete the main which // results in closing it. - delete this; + Delete(true); } return FALSE; } -void MainMenu::RequestOpenURL(const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition) { - browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, PageTransition::LINK); - delete this; -} - void MainMenu::CreateNewWindow(int route_id, base::WaitableEvent* modal_dialog_event) { - if (child_rvh_) { - // We should never get here. If we do, it indicates a child render view - // host was created and we didn't get a subsequent RequestOpenURL. + if (pending_contents_.get()) { NOTREACHED(); return; } - DCHECK(!child_rvh_); - child_rvh_ = RenderViewHostFactory::Create( - site_instance_, this, route_id, modal_dialog_event); + + helper_.CreateNewWindow(route_id, modal_dialog_event, browser_->profile(), + site_instance_, + DOMUIFactory::GetDOMUIType(GURL(kMenuURL))); + pending_contents_.reset(helper_.GetCreatedWindow(route_id)); + pending_contents_->set_delegate(&tab_contents_delegate_); +} + +void MainMenu::ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture, + const GURL& creator_url) { + if (disposition == NEW_POPUP) { + pending_contents_->set_delegate(NULL); + browser_->GetSelectedTabContents()->AddNewContents( + pending_contents_.release(), disposition, initial_pos, user_gesture, + creator_url); + Delete(false); + } +} + +void MainMenu::TabContentsDelegateImpl::OpenURLFromTab( + TabContents* source, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + menu_->browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, + PageTransition::LINK); + menu_->Delete(true); } diff --git a/chrome/browser/chromeos/main_menu.h b/chrome/browser/chromeos/main_menu.h index 2d53974..acb6fed 100644 --- a/chrome/browser/chromeos/main_menu.h +++ b/chrome/browser/chromeos/main_menu.h @@ -7,7 +7,10 @@ #include <gtk/gtk.h> +#include "base/scoped_ptr.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" +#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" class Browser; class RenderWidgetHostViewGtk; @@ -25,34 +28,79 @@ class Widget; // // MainMenu creates a RenderViewHost and corresponding RenderWidgetHostView // to display the html page. MainMenu acts as the RenderViewHostDelegate for -// the RenderViewHost. Additionally when the user clicks a link a new window -// is created (child_rvh_). MainMenu is set as the RenderViewHostDelegate of -// the child_rvh_ so that it can receive the request to open the url -// (RequestOpenURL). +// the RenderViewHost. Clicking on a link results in creating a new +// TabContents (assigned to pending_contents_). One of two things can then +// happen: +// . If the page is a popup (ShowCreatedWindow passed NEW_POPUP), the +// TabContents is added to the Browser. +// . If the page requests a URL to be open (OpenURLFromTab), OpenURL is +// invoked on the browser. // // When a new url is opened, or the user clicks outsides the bounds of the // widget the menu is closed. // -// MainMenu manages its own lifetime. +// MainMenu manages its own lifetime. In some cases deletion is delayed because +// the callers can't deal with being deleted while servicing a message from +// the renderer. class MainMenu : public RenderViewHostDelegate, public RenderViewHostDelegate::View { public: // Shows the menu. static void Show(Browser* browser); + ~MainMenu(); + private: + // TabContentsDelegate and RenderViewHostDelegate::View have some methods + // in common (with differing signatures). The TabContentsDelegate methods are + // implemented by this class. + class TabContentsDelegateImpl : public TabContentsDelegate { + public: + explicit TabContentsDelegateImpl(MainMenu* menu) : menu_(menu) {} + + // TabContentsDelegate. + virtual void OpenURLFromTab(TabContents* source, + const GURL& url, const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition); + virtual void NavigationStateChanged(const TabContents* source, + unsigned changed_flags) {} + virtual void AddNewContents(TabContents* source, + TabContents* new_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) {} + virtual void ActivateContents(TabContents* contents) {} + virtual void LoadingStateChanged(TabContents* source) {} + virtual void CloseContents(TabContents* source) {} + virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {} + virtual bool IsPopup(TabContents* source) { return false; } + virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {} + virtual void URLStarredChanged(TabContents* source, bool starred) {} + virtual void UpdateTargetURL(TabContents* source, const GURL& url) {} + + private: + MainMenu* menu_; + + DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl); + }; + + friend class TabContentsDelegateImpl; + explicit MainMenu(Browser* browser); - ~MainMenu(); void ShowImpl(); + // Does cleanup before deletion. If |now| is true delete is invoked + // immediately, otherwise deletion occurs after a delay. See description + // above class as to why we need to delay deletion in some situations. + void Delete(bool now); + // Callback from button presses on the render widget host view. Clicks // outside the widget resulting in closing the menu. static gboolean CallButtonPressEvent(GtkWidget* widget, GdkEventButton* event, - MainMenu* menu) { - return menu->OnButtonPressEvent(widget, event); - } + MainMenu* menu); gboolean OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event); @@ -66,9 +114,6 @@ class MainMenu : public RenderViewHostDelegate, virtual RenderViewHostDelegate::View* GetViewDelegate() { return this; } - virtual void RequestOpenURL(const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition); // RenderViewHostDelegate::View overrides. virtual void CreateNewWindow(int route_id, @@ -78,7 +123,7 @@ class MainMenu : public RenderViewHostDelegate, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, - const GURL& creator_url) {} + const GURL& creator_url); virtual void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos) {} virtual void ShowContextMenu(const ContextMenuParams& params) {} @@ -107,9 +152,14 @@ class MainMenu : public RenderViewHostDelegate, // RenderWidgetHostView from the menu_rvh_. RenderWidgetHostViewGtk* rwhv_; - // If the user clicks an item in the menu a child RenderViewHost is opened. - // This is that child. - RenderViewHost* child_rvh_; + // Handles creating the child TabContents. + RenderViewHostDelegateViewHelper helper_; + + // Delegate of the TabContents created by helper_. + TabContentsDelegateImpl tab_contents_delegate_; + + // TabContents created when the user clicks a link. + scoped_ptr<TabContents> pending_contents_; DISALLOW_COPY_AND_ASSIGN(MainMenu); }; diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc index ac286a7..e61e0f7 100644 --- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc +++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "render_view_host_delegate_helper.h" +#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" #include "base/command_line.h" #include "chrome/browser/browser.h" |