summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 13:40:00 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-25 13:40:00 +0000
commitf119a6358337a5efeb51b66ec5918338c17ed8e6 (patch)
treeb35f6603ec4a43dd79df6cb28df6fe5ce0430fae
parent9b4735c21892765929ca69d1a4a122ca1e1e4ca5 (diff)
downloadchromium_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.cc87
-rw-r--r--chrome/browser/chromeos/main_menu.h82
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.cc2
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"