diff options
author | jcivelli@google.com <jcivelli@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 23:12:33 +0000 |
---|---|---|
committer | jcivelli@google.com <jcivelli@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 23:12:33 +0000 |
commit | cfe5c1375a0dafe47ffb4b9223d33253fc01e8fa (patch) | |
tree | 15e23a948bbec2ee6b20d9a95645a477279e7bf9 | |
parent | ddf8a4b03ca007cc55ead2000aa6b54d0319cd56 (diff) | |
download | chromium_src-cfe5c1375a0dafe47ffb4b9223d33253fc01e8fa.zip chromium_src-cfe5c1375a0dafe47ffb4b9223d33253fc01e8fa.tar.gz chromium_src-cfe5c1375a0dafe47ffb4b9223d33253fc01e8fa.tar.bz2 |
Porting the app launcher to Windows, and adding an experimental flag
so the app launcher shows when you open a new tab.
Also removing the graying-out of the browser when the app launcher is showng for now, as
it is not clear how to make it cross-platform.
BUG=None
TEST=Start Chrome with --app-launcher-new-tab. Opening a new tab
should bring the app launcher (still a prototype at this point).
Review URL: http://codereview.chromium.org/1145001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42280 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/app_launcher.cc | 495 | ||||
-rw-r--r-- | chrome/browser/chromeos/frame/browser_view.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/frame/browser_view.h | 6 | ||||
-rw-r--r-- | chrome/browser/views/app_launcher.cc | 520 | ||||
-rw-r--r-- | chrome/browser/views/app_launcher.h (renamed from chrome/browser/chromeos/app_launcher.h) | 153 | ||||
-rw-r--r-- | chrome/browser/views/info_bubble.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.cc | 18 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.h | 7 | ||||
-rwxr-xr-x | chrome/chrome_browser.gypi | 6 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 |
12 files changed, 595 insertions, 632 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index f2779af..d384107 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -98,6 +98,7 @@ #include "chrome/browser/task_manager.h" #include "chrome/browser/user_data_manager.h" #include "chrome/browser/view_ids.h" +#include "chrome/browser/views/app_launcher.h" #include "chrome/browser/views/location_bar_view.h" #endif // OS_WIN @@ -1028,6 +1029,13 @@ void Browser::CloseWindow() { void Browser::NewTab() { UserMetrics::RecordAction("NewTab", profile_); +#if defined(OS_WIN) + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAppLauncherForNewTab)) { + AppLauncher::Show(this); + return; + } +#endif if (type() == TYPE_NORMAL) { AddBlankTab(true); } else { diff --git a/chrome/browser/chromeos/app_launcher.cc b/chrome/browser/chromeos/app_launcher.cc deleted file mode 100644 index d3e3fef..0000000 --- a/chrome/browser/chromeos/app_launcher.cc +++ /dev/null @@ -1,495 +0,0 @@ -// Copyright (c) 2010 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/chromeos/app_launcher.h" - -#include <string> -#include <vector> - -#include "app/gfx/canvas.h" -#include "app/resource_bundle.h" -#include "base/command_line.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "chrome/browser/autocomplete/autocomplete_edit.h" -#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/bubble_positioner.h" -#include "chrome/browser/chromeos/frame/browser_view.h" -#include "chrome/browser/chromeos/status/status_area_view.h" -#include "chrome/browser/chromeos/wm_ipc.h" -#include "chrome/browser/in_process_webkit/dom_storage_context.h" -#include "chrome/browser/in_process_webkit/webkit_context.h" -#include "chrome/browser/profile.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/renderer_preferences_util.h" -#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/views/bubble_border.h" -#include "gfx/insets.h" -#include "gfx/point.h" -#include "grit/app_resources.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "views/background.h" -#include "views/controls/native/native_view_host.h" -#include "views/painter.h" -#include "views/screen.h" -#include "views/widget/root_view.h" -#include "views/widget/widget_gtk.h" - -namespace { - -// Padding & margins for the navigation entry. -const int kNavigationEntryPadding = 2; -const int kNavigationEntryXMargin = 3; -const int kNavigationEntryYMargin = 1; - -// NavigationBar size. -const int kNavigationBarHeight = 25; - -// Padding for the bubble info window. -const int kBubbleWindowXPadding = 6; -const int kBubbleWindowYPadding = 16; - -// Command line switch for specifying url of the page. -const wchar_t kURLSwitch[] = L"main-menu-url"; - -// Command line switch for specifying the size of the main menu. The default is -// full screen. -const wchar_t kMenuSizeSwitch[] = L"main-menu-size"; - -// URL of the page to load. This is ignored if kURLSwitch is specified. -const char kMenuURL[] = "http://goto.ext.google.com/crux-home"; - -// Returns the URL of the menu. -static GURL GetMenuURL() { - std::wstring url_string = - CommandLine::ForCurrentProcess()->GetSwitchValue(kURLSwitch); - if (!url_string.empty()) - return GURL(WideToUTF8(url_string)); - return GURL(kMenuURL); -} - -// RenderWidgetHostViewGtk propagates the mouse press events (see -// render_widget_host_view_gtk.cc). We subclass to stop the propagation here, -// as if the click event was propagated it would reach the TopContainer view and -// it would close the popup. -class RWHVNativeViewHost : public views::NativeViewHost { - public: - RWHVNativeViewHost() {} - - virtual bool OnMousePressed(const views::MouseEvent& event) { return true; } - - private: - DISALLOW_COPY_AND_ASSIGN(RWHVNativeViewHost); -}; - -} // namspace - -namespace chromeos { - -//////////////////////////////////////////////////////////////////////////////// -// NavigationBar -// -// A navigation bar that is shown in the app launcher in compact navigation bar -// mode. - -class NavigationBar : public views::View, - public AutocompleteEditController, - public BubblePositioner { - public: - explicit NavigationBar(AppLauncher* app_launcher) - : views::View(), - app_launcher_(app_launcher), - location_entry_view_(NULL) { - SetFocusable(true); - location_entry_view_ = new views::NativeViewHost; - AddChildView(location_entry_view_); - } - - virtual ~NavigationBar() { - if (location_entry_view_->native_view()) - location_entry_view_->Detach(); - } - - // views::View overrides. - virtual void Focus() { - location_entry_->SetFocus(); - location_entry_->SelectAll(true); - } - - virtual void Layout() { - gfx::Rect bounds = GetLocalBounds(false); - - const int vertical_margin = - kNavigationEntryPadding + kNavigationEntryYMargin; - - location_entry_view_->SetBounds( - bounds.x() + kNavigationEntryXMargin + kNavigationEntryPadding, - bounds.y() + vertical_margin, - bounds.width() - 2 * (kNavigationEntryPadding + - kNavigationEntryXMargin), - bounds.height() - vertical_margin * 2); - } - - virtual void Paint(gfx::Canvas* canvas) { - const int padding = kNavigationEntryPadding; - canvas->FillRectInt(SK_ColorWHITE, 0, 0, width(), height()); - // Draw border around the entry. - gfx::Rect bounds = location_entry_view_->GetBounds( - views::View::APPLY_MIRRORING_TRANSFORMATION); - canvas->DrawRectInt(SK_ColorGRAY, - bounds.x() - padding, - bounds.y() - padding, - bounds.width() + padding * 2, - bounds.height() + padding * 2); - } - - // BubblePositioner implementation. - virtual gfx::Rect GetLocationStackBounds() const { - gfx::Rect bounds = location_entry_view_->GetBounds( - views::View::APPLY_MIRRORING_TRANSFORMATION); - gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding); - views::View::ConvertPointToScreen(this, &origin); - gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0)); - if (UILayoutIsRightToLeft()) { - // Align the window to the right side of the entry view when - // UI is RTL mode. - rect.set_x(rect.x() - (rect.width() - location_entry_view_->width())); - } - return rect; - } - - // AutocompleteController implementation. - virtual void OnAutocompleteAccept(const GURL& url, - WindowOpenDisposition disposition, - PageTransition::Type transition, - const GURL& alternate_nav_url) { - app_launcher_->AddTabWithURL(url, transition); - app_launcher_->Hide(); - } - virtual void OnChanged() {} - virtual void OnInputInProgress(bool in_progress) {} - virtual void OnKillFocus() {} - virtual void OnSetFocus() { - views::FocusManager* focus_manager = GetFocusManager(); - if (!focus_manager) { - NOTREACHED(); - return; - } - focus_manager->SetFocusedView(this); - } - virtual SkBitmap GetFavIcon() const { - return SkBitmap(); - } - virtual std::wstring GetTitle() const { - return std::wstring(); - } - - // AutocompleteEditView depends on the browser instance. - // Create new one when the browser instance changes. - void Update(Browser* browser) { - // Detach the native view if any. - if (location_entry_view_ && location_entry_view_->native_view()) - location_entry_view_->Detach(); - - location_entry_.reset(new AutocompleteEditViewGtk( - this, browser->toolbar_model(), browser->profile(), - browser->command_updater(), false, this)); - location_entry_->Init(); - gtk_widget_show_all(location_entry_->widget()); - gtk_widget_hide(location_entry_->widget()); - - location_entry_view_->set_focus_view(this); - location_entry_view_->Attach(location_entry_->widget()); - } - - private: - AppLauncher* app_launcher_; - views::NativeViewHost* location_entry_view_; - scoped_ptr<AutocompleteEditViewGtk> location_entry_; - - DISALLOW_COPY_AND_ASSIGN(NavigationBar); -}; - -//////////////////////////////////////////////////////////////////////////////// -// TopContainer -// -// A view that grays-out the browser and contains the navigation bar and -// renderer view. - -AppLauncher::TopContainer::TopContainer(AppLauncher* app_launcher) - : app_launcher_(app_launcher) { - // Use a transparent black background so the browser appears grayed-out. - set_background(views::Background::CreateSolidBackground(0, 0, 0, 100)); -} - -void AppLauncher::TopContainer::Layout() { - if (bounds().IsEmpty()) - return; - - // We only expect to contain the BubbleContents. - DCHECK(GetChildViewCount() == 1); - GetChildViewAt(0)->SetBounds(kBubbleWindowXPadding, kBubbleWindowYPadding, - width() * 2 / 3, height() * 4 / 5); -} - -bool AppLauncher::TopContainer::OnMousePressed(const views::MouseEvent& event) { - // Clicking outside the bubble closes the bubble. - app_launcher_->Hide(); - return false; -} - -//////////////////////////////////////////////////////////////////////////////// -// BubbleContainer -// -// The view that contains the navigation bar and render view. It has a bubble -// border. - -AppLauncher::BubbleContainer::BubbleContainer(AppLauncher* app_launcher) - : app_launcher_(app_launcher) { - BubbleBorder* bubble_border = new BubbleBorder(); - bubble_border->set_arrow_location(BubbleBorder::TOP_LEFT); - set_border(bubble_border); - set_background(new BubbleBackground(bubble_border)); -} - -void AppLauncher::BubbleContainer::Layout() { - if (bounds().IsEmpty() || GetChildViewCount() == 0) - return; - - gfx::Rect bounds = GetLocalBounds(false); - // TODO(jcampan): figure-out why we need to inset for the contained view not - // to paint over the bubble border. - bounds.Inset(2, 2); - - app_launcher_->navigation_bar_->SetBounds(bounds.x(), bounds.y(), - bounds.width(), - kNavigationBarHeight); - int render_y = app_launcher_->navigation_bar_->bounds().bottom(); - gfx::Size rwhv_size = - gfx::Size(bounds.width(), - std::max(0, bounds.height() - render_y + bounds.y())); - app_launcher_->render_view_container_->SetBounds(bounds.x(), render_y, - rwhv_size.width(), - rwhv_size.height()); - app_launcher_->rwhv_->SetSize(rwhv_size); -} - -//////////////////////////////////////////////////////////////////////////////// -// AppLauncher - -AppLauncher::AppLauncher(Browser* browser) - : browser_(browser), - popup_(NULL), - site_instance_(NULL), - contents_rvh_(NULL), - rwhv_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)), - ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), - top_container_(NULL), - bubble_container_(NULL), - navigation_bar_(NULL), - render_view_container_(NULL), - has_shown_(false) { - popup_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); - // The background image has transparency, so we make the window transparent. - popup_->MakeTransparent(); - popup_->Init(NULL, gfx::Rect()); - WmIpc::instance()->SetWindowType( - popup_->GetNativeView(), - WmIpc::WINDOW_TYPE_CHROME_INFO_BUBBLE, - NULL); - - // Register Esc as an accelerator for closing the app launcher. - views::FocusManager* focus_manager = popup_->GetFocusManager(); - focus_manager->RegisterAccelerator(views::Accelerator(base::VKEY_ESCAPE, - false, false, false), - this); - - top_container_ = new TopContainer(this); - popup_->SetContentsView(top_container_); - - bubble_container_ = new BubbleContainer(this); - top_container_->AddChildView(bubble_container_); - navigation_bar_ = new NavigationBar(this); - bubble_container_->AddChildView(navigation_bar_); - - GURL menu_url(GetMenuURL()); - DCHECK(BrowserList::begin() != BrowserList::end()); - // TODO(sky): this shouldn't pick a random profile to use. - Profile* profile = (*BrowserList::begin())->profile(); - int64 session_storage_namespace_id = profile->GetWebKitContext()-> - dom_storage_context()->AllocateSessionStorageNamespaceId(); - site_instance_ = SiteInstance::CreateSiteInstanceForURL(profile, menu_url); - contents_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE, - session_storage_namespace_id); - - rwhv_ = new RenderWidgetHostViewGtk(contents_rvh_); - rwhv_->InitAsChild(); - contents_rvh_->CreateRenderView(profile->GetRequestContext()); - - render_view_container_ = new RWHVNativeViewHost; - bubble_container_->AddChildView(render_view_container_); - render_view_container_->Attach(rwhv_->GetNativeView()); - contents_rvh_->NavigateToURL(menu_url); - - navigation_bar_->Update(browser); - // Set the transient window so that ChromeOS WM treat this - // as if a popup window. - gtk_window_set_transient_for( - GTK_WINDOW(popup_->GetNativeView()), - GTK_WINDOW(browser_->window()->GetNativeHandle())); - - ActiveWindowWatcherX::AddObserver(this); -} - -AppLauncher::~AppLauncher() { - contents_rvh_->Shutdown(); - popup_->CloseNow(); - ActiveWindowWatcherX::RemoveObserver(this); -} - -void AppLauncher::Update() { - popup_->SetBounds(browser_->window()->GetRestoredBounds()); - top_container_->Layout(); -} - -void AppLauncher::Show() { - Cleanup(); - - Update(); - popup_->Show(); - - GtkWidget* rwhv_widget = rwhv_->GetNativeView(); - if (!has_shown_) { - has_shown_ = true; - gtk_widget_realize(rwhv_widget); - } -} - -void AppLauncher::ActiveWindowChanged(GdkWindow* active_window) { - if (!popup_->IsActive()) - Hide(); - else - navigation_bar_->RequestFocus(); -} - -bool AppLauncher::AcceleratorPressed(const views::Accelerator& accelerator) { - DCHECK(accelerator.GetKeyCode() == base::VKEY_ESCAPE); - popup_->Hide(); - return true; -} - -void AppLauncher::Hide() { - popup_->Hide(); - // The stack may have pending_contents_ on it. Delay deleting the - // pending_contents_ as TabContents doesn't deal well with being deleted - // while on the stack. - MessageLoop::current()->PostTask(FROM_HERE, - method_factory_.NewRunnableMethod(&AppLauncher::Cleanup)); -} - -void AppLauncher::Cleanup() { - pending_contents_.reset(NULL); - method_factory_.RevokeAll(); -} - -void AppLauncher::RequestMove(const gfx::Rect& new_bounds) { - // Invoking PositionChild results in a gtk signal that triggers attempting to - // to resize the window. We need to set the size request so that it resizes - // correctly when this happens. - gtk_widget_set_size_request(popup_->GetNativeView(), - new_bounds.width(), new_bounds.height()); - popup_->SetBounds(new_bounds); -} - -RendererPreferences AppLauncher::GetRendererPrefs(Profile* profile) const { - RendererPreferences preferences; - renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); - return preferences; -} - -void AppLauncher::AddTabWithURL(const GURL& url, - PageTransition::Type transition) { - switch (StatusAreaView::GetOpenTabsMode()) { - case StatusAreaView::OPEN_TABS_ON_LEFT: { - // Add the new tab at the first non-pinned location. - int index = browser_->tabstrip_model()->IndexOfFirstNonMiniTab(); - browser_->AddTabWithURL(url, GURL(), transition, - true, index, true, NULL); - break; - } - case StatusAreaView::OPEN_TABS_CLOBBER: { - browser_->GetSelectedTabContents()->controller().LoadURL( - url, GURL(), transition); - break; - } - case StatusAreaView::OPEN_TABS_ON_RIGHT: { - browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); - break; - } - } -} - -void AppLauncher::CreateNewWindow(int route_id) { - if (pending_contents_.get()) { - NOTREACHED(); - return; - } - - helper_.CreateNewWindow(route_id, browser_->profile(), site_instance_, - DOMUIFactory::GetDOMUIType(GURL(GetMenuURL())), - NULL); - pending_contents_.reset(helper_.GetCreatedWindow(route_id)); - pending_contents_->set_delegate(&tab_contents_delegate_); -} - -void AppLauncher::ShowCreatedWindow(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - if (disposition == NEW_POPUP) { - pending_contents_->set_delegate(NULL); - browser_->GetSelectedTabContents()->AddNewContents( - pending_contents_.release(), disposition, initial_pos, user_gesture); - Hide(); - } -} - -void AppLauncher::StartDragging(const WebDropData& drop_data, - WebKit::WebDragOperationsMask allowed_ops, - const SkBitmap& image, - const gfx::Point& image_offset) { - // We're not going to do any drag & drop, but we have to tell the renderer the - // drag & drop ended, othewise the renderer thinks the drag operation is - // underway and mouse events won't work. - contents_rvh_->DragSourceSystemDragEnded(); -} - -AppLauncher::TabContentsDelegateImpl::TabContentsDelegateImpl( - AppLauncher* app_launcher) - : app_launcher_(app_launcher) { -} - -void AppLauncher::TabContentsDelegateImpl::OpenURLFromTab( - TabContents* source, - const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - app_launcher_->browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB, - PageTransition::LINK); - app_launcher_->Hide(); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc index f5cd791..a8040ad0 100644 --- a/chrome/browser/chromeos/frame/browser_view.cc +++ b/chrome/browser/chromeos/frame/browser_view.cc @@ -11,7 +11,6 @@ #include "app/menus/simple_menu_model.h" #include "app/theme_provider.h" #include "chrome/app/chrome_dll_resource.h" -#include "chrome/browser/chromeos/app_launcher.h" #include "chrome/browser/chromeos/compact_location_bar_host.h" #include "chrome/browser/chromeos/compact_navigation_bar.h" #include "chrome/browser/chromeos/frame/panel_browser_view.h" @@ -20,6 +19,7 @@ #include "chrome/browser/chromeos/status/status_area_button.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "chrome/browser/view_ids.h" +#include "chrome/browser/views/app_launcher.h" #include "chrome/browser/views/frame/browser_extender.h" #include "chrome/browser/views/frame/browser_frame_gtk.h" #include "chrome/browser/views/frame/browser_view.h" @@ -338,7 +338,6 @@ class BrowserViewLayout : public ::BrowserViewLayout { BrowserView::BrowserView(Browser* browser) : ::BrowserView(browser), - main_menu_(NULL), main_menu_button_(NULL), status_area_(NULL), compact_navigation_bar_(NULL), @@ -458,10 +457,7 @@ void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { // views::ButtonListener overrides. void BrowserView::ButtonPressed(views::Button* sender, const views::Event& event) { - if (!main_menu_.get()) { - main_menu_.reset(new AppLauncher(browser())); - } - main_menu_->Show(); + AppLauncher::Show(browser()); } // views::ContextMenuController overrides. diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h index 44a4ccd..7f38d95 100644 --- a/chrome/browser/chromeos/frame/browser_view.h +++ b/chrome/browser/chromeos/frame/browser_view.h @@ -28,13 +28,12 @@ class BrowserStatusAreaView; class CompactLocationBar; class CompactLocationBarHost; class CompactNavigationBar; -class AppLauncher; class StatusAreaButton; // chromeos::BrowserView adds ChromeOS specific controls and menus to a // BrowserView created with Browser::TYPE_NORMAL. This extender adds controls // to the title bar as follows: -// ____ __ __ +// ____ __ __ // [AppLauncher] / \ \ \ [StatusArea] // // and adds the system context menu to the remaining arae of the titlebar. @@ -96,9 +95,6 @@ class BrowserView : public ::BrowserView, private: void InitSystemMenu(); - // AppLauncher instance. - scoped_ptr<AppLauncher> main_menu_; - // AppLauncher button. views::ImageButton* main_menu_button_; diff --git a/chrome/browser/views/app_launcher.cc b/chrome/browser/views/app_launcher.cc new file mode 100644 index 0000000..d787f16 --- /dev/null +++ b/chrome/browser/views/app_launcher.cc @@ -0,0 +1,520 @@ +// Copyright (c) 2010 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/views/app_launcher.h" + +#include <string> +#include <vector> + +#include "app/resource_bundle.h" +#include "base/command_line.h" +#include "base/message_loop.h" +#include "base/string_util.h" +#include "base/task.h" +#include "chrome/browser/autocomplete/autocomplete_edit.h" +#include "chrome/browser/autocomplete/autocomplete_edit_view.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/bubble_positioner.h" +#include "chrome/browser/in_process_webkit/webkit_context.h" +#include "chrome/browser/profile.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/site_instance.h" +#include "chrome/browser/renderer_preferences_util.h" +#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/views/info_bubble.h" +#include "chrome/browser/views/frame/browser_view.h" +#include "views/controls/native/native_view_host.h" +#include "views/widget/root_view.h" +#include "views/widget/widget.h" + +#if defined(OS_WIN) +#include "chrome/browser/autocomplete/autocomplete_edit_view_win.h" +#include "chrome/browser/renderer_host/render_widget_host_view_win.h" +#elif defined(OS_LINUX) +#include "chrome/browser/autocomplete/autocomplete_edit_view_gtk.h" +#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" +#endif +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/status/status_area_view.h" +#endif + +namespace { + +// Padding & margins for the navigation entry. +const int kNavigationEntryPadding = 2; +const int kNavigationEntryXMargin = 3; +const int kNavigationEntryYMargin = 1; + +// NavigationBar size. +const int kNavigationBarHeight = 25; + +// The delta applied to the default font size for the omnibox. +const int kAutocompleteEditFontDelta = 3; + +// Command line switch for specifying url of the page. +const wchar_t kURLSwitch[] = L"main-menu-url"; + +// URL of the page to load. This is ignored if kURLSwitch is specified. +const char kMenuURL[] = "http://goto.ext.google.com/crux-home"; + +// Returns the URL of the menu. +static GURL GetMenuURL() { + std::wstring url_string = + CommandLine::ForCurrentProcess()->GetSwitchValue(kURLSwitch); + if (!url_string.empty()) + return GURL(WideToUTF8(url_string)); + return GURL(kMenuURL); +} + +// RenderWidgetHostViewGtk propagates the mouse press events (see +// render_widget_host_view_gtk.cc). We subclass to stop the propagation here, +// as if the click event was propagated it would reach the TopContainer view and +// it would close the popup. +class RWHVNativeViewHost : public views::NativeViewHost { + public: + RWHVNativeViewHost() {} + + virtual bool OnMousePressed(const views::MouseEvent& event) { return true; } + + private: + DISALLOW_COPY_AND_ASSIGN(RWHVNativeViewHost); +}; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// TabContentsDelegateImpl +// +// 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(AppLauncher* app_launcher); + + // 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: + AppLauncher* app_launcher_; + + DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl); +}; + +TabContentsDelegateImpl::TabContentsDelegateImpl(AppLauncher* app_launcher) + : app_launcher_(app_launcher) { +} + +void TabContentsDelegateImpl::OpenURLFromTab(TabContents* source, + const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + app_launcher_->browser()->OpenURL(url, referrer, NEW_FOREGROUND_TAB, + PageTransition::LINK); + app_launcher_->Hide(); +} + +//////////////////////////////////////////////////////////////////////////////// +// NavigationBar +// +// A navigation bar that is shown in the app launcher in compact navigation bar +// mode. + +class NavigationBar : public views::View, + public AutocompleteEditController, + public BubblePositioner { + public: + explicit NavigationBar(AppLauncher* app_launcher) + : app_launcher_(app_launcher), + location_entry_view_(NULL) { + SetFocusable(true); + location_entry_view_ = new views::NativeViewHost; + AddChildView(location_entry_view_); + set_border(views::Border::CreateSolidBorder(1, SK_ColorGRAY)); + } + + virtual ~NavigationBar() { + if (location_entry_view_->native_view()) + location_entry_view_->Detach(); + } + + // views::View overrides. + virtual void Focus() { + location_entry_->SetFocus(); + location_entry_->SelectAll(true); + } + + virtual void ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child) { + if (!is_add || child != this) + return; + + DCHECK(!location_entry_.get()); + + Browser* browser = app_launcher_->browser(); +#if defined (OS_WIN) + gfx::Font font; + font = font.DeriveFont(kAutocompleteEditFontDelta); + AutocompleteEditViewWin* autocomplete_view = + new AutocompleteEditViewWin(font, this, browser->toolbar_model(), + this, GetWidget()->GetNativeView(), + browser->profile(), + browser->command_updater(), false, this); + location_entry_.reset(autocomplete_view); + autocomplete_view->Update(NULL); + // The Update call above sets the autocomplete text to the current one in + // the location bar, make sure to clear it. + autocomplete_view->SetUserText(std::wstring()); +#elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) + AutocompleteEditViewGtk* autocomplete_view = + new AutocompleteEditViewGtk(this, browser->toolbar_model(), + browser->profile(), + browser->command_updater(), false, this); + autocomplete_view->Init(); + gtk_widget_show_all(autocomplete_view->widget()); + gtk_widget_hide(autocomplete_view->widget()); + location_entry_.reset(autocomplete_view); +#else + NOTIMPLEMENTED(); +#endif + location_entry_view_->set_focus_view(this); + location_entry_view_->Attach(location_entry_->GetNativeView()); + } + + virtual void Layout() { + gfx::Rect bounds = GetLocalBounds(false); + location_entry_view_->SetBounds( + bounds.x() + kNavigationEntryXMargin + kNavigationEntryPadding, + bounds.y() + kNavigationEntryYMargin, + bounds.width() - 2 * (kNavigationEntryPadding + + kNavigationEntryXMargin), + bounds.height() - kNavigationEntryYMargin * 2); + } + + // BubblePositioner implementation. + virtual gfx::Rect GetLocationStackBounds() const { + gfx::Rect bounds = location_entry_view_->GetBounds( + views::View::APPLY_MIRRORING_TRANSFORMATION); + gfx::Point origin(bounds.x(), bounds.bottom() + kNavigationEntryPadding); + views::View::ConvertPointToScreen(this, &origin); + gfx::Rect rect = gfx::Rect(origin, gfx::Size(500, 0)); + if (UILayoutIsRightToLeft()) { + // Align the window to the right side of the entry view when + // UI is RTL mode. + rect.set_x(rect.x() - (rect.width() - location_entry_view_->width())); + } + return rect; + } + + // AutocompleteController implementation. + virtual void OnAutocompleteAccept(const GURL& url, + WindowOpenDisposition disposition, + PageTransition::Type transition, + const GURL& alternate_nav_url) { + app_launcher_->AddTabWithURL(url, transition); + app_launcher_->Hide(); + } + virtual void OnChanged() {} + virtual void OnInputInProgress(bool in_progress) {} + virtual void OnKillFocus() {} + virtual void OnSetFocus() { + views::FocusManager* focus_manager = GetFocusManager(); + if (!focus_manager) { + NOTREACHED(); + return; + } + focus_manager->SetFocusedView(this); + } + virtual SkBitmap GetFavIcon() const { + return SkBitmap(); + } + virtual std::wstring GetTitle() const { + return std::wstring(); + } + + private: + AppLauncher* app_launcher_; + views::NativeViewHost* location_entry_view_; +#if defined(OS_WIN) + scoped_ptr<AutocompleteEditViewWin> location_entry_; +#elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS) + scoped_ptr<AutocompleteEditViewGtk> location_entry_; +#else + NOTIMPLEMENTED(); +#endif + + DISALLOW_COPY_AND_ASSIGN(NavigationBar); +}; + +//////////////////////////////////////////////////////////////////////////////// +// InfoBubbleContentsView +// +// The view that contains the navigation bar and render view. +// It is displayed in an info-bubble. + +class InfoBubbleContentsView : public views::View { + public: + explicit InfoBubbleContentsView(AppLauncher* app_launcher); + ~InfoBubbleContentsView(); + + // Sets the initial focus. + // Should be called when the bubble that contains us is shown. + void BubbleShown(); + + // views::View override: + virtual gfx::Size GetPreferredSize(); + virtual void Layout(); + virtual void ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child); + + private: + // The application launcher displaying this info bubble. + AppLauncher* app_launcher_; + + // The navigation bar. + NavigationBar* navigation_bar_; + + // The view containing the renderer view. + views::NativeViewHost* render_view_container_; + + DISALLOW_COPY_AND_ASSIGN(InfoBubbleContentsView); +}; + +InfoBubbleContentsView::InfoBubbleContentsView(AppLauncher* app_launcher) + : app_launcher_(app_launcher), + navigation_bar_(NULL), + render_view_container_(NULL) { +} + +InfoBubbleContentsView::~InfoBubbleContentsView() { +} + +void InfoBubbleContentsView::BubbleShown() { + navigation_bar_->RequestFocus(); +} + +void InfoBubbleContentsView::ViewHierarchyChanged( + bool is_add, views::View* parent, views::View* child) { + if (!is_add || child != this) + return; + + DCHECK(!render_view_container_); + render_view_container_ = new RWHVNativeViewHost; + AddChildView(render_view_container_); +#if defined(OS_WIN) + RenderWidgetHostViewWin* view_win = + static_cast<RenderWidgetHostViewWin*>(app_launcher_->rwhv_); + // Create the HWND now that we are parented. + HWND hwnd = view_win->Create(GetWidget()->GetNativeView()); + view_win->ShowWindow(SW_SHOW); +#endif + render_view_container_->Attach(app_launcher_->rwhv_->GetNativeView()); + + navigation_bar_ = new NavigationBar(app_launcher_); + AddChildView(navigation_bar_); +} + +gfx::Size InfoBubbleContentsView::GetPreferredSize() { + gfx::Rect bounds = app_launcher_->browser()->window()->GetRestoredBounds(); + return gfx::Size(bounds.width() * 2 / 3, bounds.width() * 4 / 5); +} + +void InfoBubbleContentsView::Layout() { + if (bounds().IsEmpty() || GetChildViewCount() == 0) + return; + + int navigation_bar_height = + kNavigationBarHeight + kNavigationEntryYMargin * 2; + const views::Border* border = navigation_bar_->border(); + if (border) { + gfx::Insets insets; + border->GetInsets(&insets); + navigation_bar_height += insets.height(); + } + navigation_bar_->SetBounds(x(), y(), width(), navigation_bar_height); + int render_y = navigation_bar_->bounds().bottom(); + gfx::Size rwhv_size = + gfx::Size(width(), std::max(0, height() - render_y + y())); + render_view_container_->SetBounds(x(), render_y, + rwhv_size.width(), rwhv_size.height()); + app_launcher_->rwhv_->SetSize(rwhv_size); +} + +//////////////////////////////////////////////////////////////////////////////// +// AppLauncher + +AppLauncher::AppLauncher(Browser* browser) + : browser_(browser), + info_bubble_(NULL), + site_instance_(NULL), + contents_rvh_(NULL), + rwhv_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST( + tab_contents_delegate_(new TabContentsDelegateImpl(this))) { + info_bubble_content_ = new InfoBubbleContentsView(this); + + Profile* profile = browser_->profile(); + int64 session_storage_namespace_id = profile->GetWebKitContext()-> + dom_storage_context()->AllocateSessionStorageNamespaceId(); + site_instance_ = SiteInstance::CreateSiteInstanceForURL(profile, + GetMenuURL()); + contents_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE, + session_storage_namespace_id); + rwhv_ = RenderWidgetHostView::CreateViewForWidget(contents_rvh_); + contents_rvh_->set_view(rwhv_); + + // On Windows, we'll create the RWHV HWND once we are attached as we need + // to be parented for CreateWindow to work. +#if defined(OS_LINUX) + RenderWidgetHostViewGtk* view_gtk = + static_cast<RenderWidgetHostViewGtk*>(rwhv_); + view_gtk->InitAsChild(); +#endif + + contents_rvh_->CreateRenderView(profile->GetRequestContext()); + DCHECK(contents_rvh_->IsRenderViewLive()); + contents_rvh_->NavigateToURL(GetMenuURL()); +} + +AppLauncher::~AppLauncher() { + contents_rvh_->Shutdown(); +} + +// static +AppLauncher* AppLauncher::Show(Browser* browser) { + AppLauncher* app_launcher = new AppLauncher(browser); + + BrowserView* browser_view = static_cast<BrowserView*>(browser->window()); + TabStrip* tabstrip = browser_view->tabstrip()->AsTabStrip(); + if (!tabstrip) { + delete app_launcher; + return NULL; + } + gfx::Rect bounds = tabstrip->GetNewTabButtonBounds(); + gfx::Point origin = bounds.origin(); + views::RootView::ConvertPointToScreen(tabstrip, &origin); + bounds.set_origin(origin); + app_launcher->info_bubble_ = + InfoBubble::Show(browser_view->frame()->GetWindow(), bounds, + app_launcher->info_bubble_content_, app_launcher); + app_launcher->info_bubble_content_->BubbleShown(); + return app_launcher; +} + +void AppLauncher::Hide() { + info_bubble_->Close(); +} + +void AppLauncher::InfoBubbleClosing(InfoBubble* info_bubble, + bool closed_by_escape) { + // The stack may have pending_contents_ on it. Delay deleting the + // pending_contents_ as TabContents doesn't deal well with being deleted + // while on the stack. + MessageLoop::current()->PostTask(FROM_HERE, + new DeleteTask<AppLauncher>(this)); +} + +void AppLauncher::RequestMove(const gfx::Rect& new_bounds) { +#if defined(OS_LINUX) + // Invoking PositionChild results in a gtk signal that triggers attempting to + // to resize the window. We need to set the size request so that it resizes + // correctly when this happens. + gtk_widget_set_size_request(info_bubble_->GetNativeView(), + new_bounds.width(), new_bounds.height()); + info_bubble_->SetBounds(new_bounds); +#endif +} + +RendererPreferences AppLauncher::GetRendererPrefs(Profile* profile) const { + RendererPreferences preferences; + renderer_preferences_util::UpdateFromSystemSettings(&preferences, profile); + return preferences; +} + +void AppLauncher::CreateNewWindow(int route_id) { + if (pending_contents_.get()) { + NOTREACHED(); + return; + } + + helper_.CreateNewWindow(route_id, browser_->profile(), site_instance_, + DOMUIFactory::GetDOMUIType(GURL(GetMenuURL())), + NULL); + pending_contents_.reset(helper_.GetCreatedWindow(route_id)); + pending_contents_->set_delegate(tab_contents_delegate_.get()); +} + +void AppLauncher::ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + if (disposition == NEW_POPUP) { + pending_contents_->set_delegate(NULL); + browser_->GetSelectedTabContents()->AddNewContents( + pending_contents_.release(), disposition, initial_pos, user_gesture); + Hide(); + } +} + +void AppLauncher::StartDragging(const WebDropData& drop_data, + WebKit::WebDragOperationsMask allowed_ops, + const SkBitmap& image, + const gfx::Point& image_offset) { + // We're not going to do any drag & drop, but we have to tell the renderer the + // drag & drop ended, othewise the renderer thinks the drag operation is + // underway and mouse events won't work. + contents_rvh_->DragSourceSystemDragEnded(); +} + +void AppLauncher::AddTabWithURL(const GURL& url, + PageTransition::Type transition) { +#if defined(OS_CHROMEOS) + switch (chromeos::StatusAreaView::GetOpenTabsMode()) { + case chromeos::StatusAreaView::OPEN_TABS_ON_LEFT: { + // Add the new tab at the first non-pinned location. + int index = browser_->tabstrip_model()->IndexOfFirstNonMiniTab(); + browser_->AddTabWithURL(url, GURL(), transition, + true, index, true, NULL); + break; + } + case chromeos::StatusAreaView::OPEN_TABS_CLOBBER: { + browser_->GetSelectedTabContents()->controller().LoadURL( + url, GURL(), transition); + break; + } + case chromeos::StatusAreaView::OPEN_TABS_ON_RIGHT: { + browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); + break; + } + } +#else + browser_->AddTabWithURL(url, GURL(), transition, true, -1, true, NULL); +#endif +} diff --git a/chrome/browser/chromeos/app_launcher.h b/chrome/browser/views/app_launcher.h index f2a8145..c641988 100644 --- a/chrome/browser/chromeos/app_launcher.h +++ b/chrome/browser/views/app_launcher.h @@ -2,27 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_CHROMEOS_APP_LAUNCHER_H_ -#define CHROME_BROWSER_CHROMEOS_APP_LAUNCHER_H_ +#ifndef CHROME_BROWSER_VIEWS_APP_LAUNCHER_H_ +#define CHROME_BROWSER_VIEWS_APP_LAUNCHER_H_ -#include <gtk/gtk.h> - -#include "app/active_window_watcher_x.h" #include "base/scoped_ptr.h" -#include "base/task.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" +#include "chrome/browser/views/info_bubble.h" #include "chrome/common/renderer_preferences.h" #include "views/view.h" class Browser; -class RenderWidgetHostViewGtk; class SiteInstance; -class SkBitmap; namespace gfx { -class Point; class Size; } namespace views { @@ -31,9 +25,9 @@ class View; class WidgetGtk; } -namespace chromeos { - +class InfoBubbleContentsView; class NavigationBar; +class TabContentsDelegateImpl; // AppLauncher manages showing the application launcher and optionally the // navigation bar in compact navigation bar mode. The app launcher is @@ -57,94 +51,25 @@ class NavigationBar; // // When a new url is opened, or the user clicks outsides the bounds of the // widget the app launcher is closed. -class AppLauncher : public RenderViewHostDelegate, - public RenderViewHostDelegate::View, - public ActiveWindowWatcherX::Observer, - public views::AcceleratorTarget { +class AppLauncher : public InfoBubbleDelegate, + public RenderViewHostDelegate, + public RenderViewHostDelegate::View { public: - AppLauncher(Browser* browser); - ~AppLauncher(); - - // Shows the menu. - void Show(); + // Shows an application launcher bubble pointing to the new tab button. + // The caller DOES NOT OWN the AppLauncher returned. It is deleted + // automatically when the AppLauncher is closed. + static AppLauncher* Show(Browser* browser); - 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(AppLauncher* app_launcher); - - // 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: - AppLauncher* app_launcher_; - - DISALLOW_COPY_AND_ASSIGN(TabContentsDelegateImpl); - }; - - class TopContainer : public views::View { - public: - explicit TopContainer(AppLauncher* app_launcher); - virtual ~TopContainer() {} - - // views::View overrides. - virtual void Layout(); - virtual bool OnMousePressed(const views::MouseEvent& event); - - private: - AppLauncher* app_launcher_; - - DISALLOW_COPY_AND_ASSIGN(TopContainer); - }; - - class BubbleContainer : public views::View { - public: - explicit BubbleContainer(AppLauncher* app_launcher); - - // views::View overrides. - virtual void Layout(); - - private: - AppLauncher* app_launcher_; - - DISALLOW_COPY_AND_ASSIGN(BubbleContainer); - }; - - friend class BubbleContainer; - friend class NavigationBar; - friend class TabContentsDelegateImpl; - friend class TopContainer; + // Returns the browser this AppLauncher is associated with. + Browser* browser() const { return browser_; } // Hides the app launcher. void Hide(); - // Cleans up state. This is invoked before showing and after a delay when - // hidden. - void Cleanup(); - - // Updates the app launcher's state. - void Update(); + // InfoBubbleDelegate overrides. + virtual void InfoBubbleClosing(InfoBubble* info_bubble, + bool closed_by_escape); + virtual bool CloseOnEscape() { return true; } // RenderViewHostDelegate overrides. virtual int GetBrowserWindowID() const { @@ -185,58 +110,44 @@ class AppLauncher : public RenderViewHostDelegate, virtual void HandleMouseLeave() {} virtual void UpdatePreferredSize(const gfx::Size& pref_size) {} - // ActiveWindowWatcherX::Observer implementation. - virtual void ActiveWindowChanged(GdkWindow* active_window); + private: + friend class DeleteTask<AppLauncher>; + friend class NavigationBar; + friend class InfoBubbleContentsView; - // views::AcceleratorTarget implementation: - virtual bool AcceleratorPressed(const views::Accelerator& accelerator); + explicit AppLauncher(Browser* browser); + ~AppLauncher(); void AddTabWithURL(const GURL& url, PageTransition::Type transition); // The currently active browser. We use this to open urls. Browser* browser_; - // The widget displaying the rwvh_. - views::WidgetGtk* popup_; + // The InfoBubble displaying the omnibox and app contents. + InfoBubble* info_bubble_; // SiteInstance for the RenderViewHosts we create. - SiteInstance* site_instance_; + scoped_refptr<SiteInstance> site_instance_; // RenderViewHost for the contents. RenderViewHost* contents_rvh_; // RenderWidgetHostView from the contents_rvh_. - RenderWidgetHostViewGtk* rwhv_; + RenderWidgetHostView* rwhv_; // Handles creating the child TabContents. RenderViewHostDelegateViewHelper helper_; // Delegate of the TabContents created by helper_. - TabContentsDelegateImpl tab_contents_delegate_; + scoped_ptr<TabContentsDelegateImpl> tab_contents_delegate_; // TabContents created when the user clicks a link. scoped_ptr<TabContents> pending_contents_; - ScopedRunnableMethodFactory<AppLauncher> method_factory_; - - // Container of the background, NavigationBar and Renderer. - views::View* top_container_; - - // Container of the NavigationBar and Renderer (shown in a bubble). - views::View* bubble_container_; - - // The navigation bar. Only shown in compact navigation bar mode. - NavigationBar* navigation_bar_; - - // The view containing the renderer view. - views::NativeViewHost* render_view_container_; - - // True if the popup has ever been shown. - bool has_shown_; + // The view with the navigation bar and render view, shown in the info-bubble. + InfoBubbleContentsView* info_bubble_content_; DISALLOW_COPY_AND_ASSIGN(AppLauncher); }; -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_APP_LAUNCHER_H_ +#endif // CHROME_BROWSER_VIEWS_APP_LAUNCHER_H_ diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc index 7f21bca..e1bb401 100644 --- a/chrome/browser/views/info_bubble.cc +++ b/chrome/browser/views/info_bubble.cc @@ -264,7 +264,7 @@ void InfoBubble::Init(views::Window* parent, // Calculate and set the bounds for all windows and views. gfx::Rect window_bounds; - bool prefer_arrow_on_right = + bool prefer_arrow_on_right = delegate && (contents->UILayoutIsRightToLeft() == delegate->PreferOriginSideAnchor()); #if defined(OS_WIN) diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index ec15794..ccfc31a 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -10,7 +10,9 @@ #include "app/os_exchange_data.h" #include "app/resource_bundle.h" #include "app/slide_animation.h" +#include "base/command_line.h" #include "base/stl_util-inl.h" +#include "chrome/browser/browser.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/defaults.h" #include "chrome/browser/metrics/user_metrics.h" @@ -19,8 +21,10 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/view_ids.h" +#include "chrome/browser/views/app_launcher.h" #include "chrome/browser/views/tabs/dragged_tab_controller.h" #include "chrome/browser/views/tabs/tab.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "gfx/path.h" #include "gfx/size.h" @@ -818,6 +822,10 @@ bool TabStrip::IsCompatibleWith(TabStrip* other) const { return model_->profile() == other->model()->profile(); } +gfx::Rect TabStrip::GetNewTabButtonBounds() { + return newtab_button_->bounds(); +} + //////////////////////////////////////////////////////////////////////////////// // TabStrip, BaseTabStrip implementation: @@ -1399,6 +1407,16 @@ bool TabStrip::HasAvailableDragActions() const { void TabStrip::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == newtab_button_) { + // TODO(jcampan): if we decide to keep the app launcher as the default + // behavior for the new tab button, we should add a method + // on the TabStripDelegate to do so. + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAppLauncherForNewTab)) { + NavigationController& controller = + model_->GetSelectedTabContents()->controller(); + AppLauncher::Show(Browser::GetBrowserForController(&controller, NULL)); + return; + } UserMetrics::RecordAction("NewTab_Button", model_->profile()); model_->delegate()->AddBlankTab(true); } diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index 6285e1d..73e89c8 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -61,19 +61,22 @@ class TabStrip : public BaseTabStrip, // Removes the drag source Tab from this TabStrip, and deletes it. void DestroyDraggedSourceTab(Tab* tab); - // Retrieve the ideal bounds for the Tab at the specified index. + // Retrieves the ideal bounds for the Tab at the specified index. gfx::Rect GetIdealBounds(int index); // Returns the currently selected tab. Tab* GetSelectedTab() const; - // Create the new tab button. + // Creates the new tab button. void InitTabStripButtons(); // Return true if this tab strip is compatible with the provided tab strip. // Compatible tab strips can transfer tabs during drag and drop. bool IsCompatibleWith(TabStrip* other) const; + // Returns the bounds of the new tab button. + gfx::Rect GetNewTabButtonBounds(); + // BaseTabStrip implementation: virtual int GetPreferredHeight(); virtual void SetBackgroundOffset(const gfx::Point& offset); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index acbd591..bebf2c8 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -304,8 +304,6 @@ 'browser/chrome_plugin_host.h', 'browser/chrome_thread.cc', 'browser/chrome_thread.h', - 'browser/chromeos/app_launcher.h', - 'browser/chromeos/app_launcher.cc', 'browser/chromeos/notifications/balloon_collection_impl.h', 'browser/chromeos/notifications/balloon_collection_impl.cc', 'browser/chromeos/notifications/balloon_view.h', @@ -2042,6 +2040,8 @@ 'browser/views/accelerator_table_gtk.h', 'browser/views/accessible_toolbar_view.cc', 'browser/views/accessible_toolbar_view.h', + 'browser/views/app_launcher.cc', + 'browser/views/app_launcher.h', 'browser/views/appcache_info_view.cc', 'browser/views/appcache_info_view.h', 'browser/views/autocomplete/autocomplete_popup_contents_view.cc', @@ -2678,6 +2678,8 @@ ['include', '^browser/views/accelerator_table_gtk.h'], ['include', '^browser/views/accessible_toolbar_view.cc'], ['include', '^browser/views/accessible_toolbar_view.h'], + ['include', '^browser/views/app_launcher.cc'], + ['include', '^browser/views/app_launcher.h'], ['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.cc'], ['include', '^browser/views/autocomplete/autocomplete_popup_contents_view.h'], ['include', '^browser/views/autocomplete/autocomplete_popup_gtk.cc'], diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 07e9433..cb93cbc 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -39,6 +39,9 @@ const char kAppId[] = "app-id"; // panel window. const char kAppLaunchAsPanel[] = "app-launch-as-panel"; +// Makes the app launcher popup when a new tab is created. +const char kAppLauncherForNewTab[] = "app-launcher-new-tab"; + // Authentication white list for servers const char kAuthServerWhitelist[] = "auth-server-whitelist"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index e6c541e..27a53d2 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -26,6 +26,7 @@ extern const char kAlwaysEnableDevTools[]; extern const char kApp[]; extern const char kAppId[]; extern const char kAppLaunchAsPanel[]; +extern const char kAppLauncherForNewTab[]; extern const char kAuthServerWhitelist[]; extern const char kAutomationClientChannelID[]; extern const char kBookmarkMenu[]; |