diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-26 04:06:43 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-26 04:06:43 +0000 |
commit | f075fe0a20acba35df51e93e635db8f0b0d89d7b (patch) | |
tree | 68cc0fe76b8897b1f6162f176f1ba62a227929e1 | |
parent | 62cdc5bf2d94c02ef33ebff1ede7e0cde31c7285 (diff) | |
download | chromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.zip chromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.tar.gz chromium_src-f075fe0a20acba35df51e93e635db8f0b0d89d7b.tar.bz2 |
Reland r45520. This adds a new browser type: EXTENSION_APP that
has a larger titlebar and a big icon, along with a tabstrip,
but no titlebar.
Review URL: http://codereview.chromium.org/1774003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45566 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser.cc | 63 | ||||
-rw-r--r-- | chrome/browser/browser.h | 38 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 2 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_tabs_module.cc | 2 | ||||
-rw-r--r-- | chrome/browser/resources/calendar_app/manifest.json | 2 | ||||
-rw-r--r-- | chrome/browser/resources/docs_app/manifest.json | 2 | ||||
-rw-r--r-- | chrome/browser/resources/gmail_app/manifest.json | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 10 | ||||
-rw-r--r-- | chrome/browser/view_ids.h | 4 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.cc | 49 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view.h | 29 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view_layout.cc | 56 | ||||
-rw-r--r-- | chrome/browser/views/frame/browser_view_layout.h | 5 | ||||
-rw-r--r-- | chrome/browser/views/frame/opaque_browser_frame_view.cc | 27 | ||||
-rw-r--r-- | chrome/browser/views/tabs/dragged_tab_controller.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.cc | 10 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab_strip.h | 13 | ||||
-rw-r--r-- | chrome/browser/views/toolbar_view.cc | 3 |
18 files changed, 268 insertions, 52 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 714268c..0ee8753 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -165,7 +165,8 @@ Browser::Browser(Type type, Profile* profile) block_command_execution_(false), last_blocked_command_id_(-1), last_blocked_command_disposition_(CURRENT_TAB), - pending_web_app_action_(NONE) { + pending_web_app_action_(NONE), + extension_app_(NULL) { tabstrip_model_.AddObserver(this); registrar_.Add(this, NotificationType::SSL_VISIBLE_STATE_CHANGED, @@ -255,10 +256,19 @@ Browser* Browser::CreateForPopup(Profile* profile) { // static Browser* Browser::CreateForApp(const std::wstring& app_name, + Extension* extension, Profile* profile, bool is_panel) { - Browser* browser = new Browser(is_panel ? TYPE_APP_PANEL : TYPE_APP, profile); + Browser::Type type = TYPE_APP; + + if (is_panel) + type = TYPE_APP_PANEL; + else if (extension) + type = TYPE_EXTENSION_APP; + + Browser* browser = new Browser(type, profile); browser->app_name_ = app_name; + browser->extension_app_ = extension; browser->CreateBrowserWindow(); return browser; } @@ -410,13 +420,15 @@ bool Browser::OpenApplication(Profile* profile, const std::string& app_id) { } // static -void Browser::OpenApplicationWindow(Profile* profile, const GURL& url, - bool as_panel) { +void Browser::OpenApplicationWindow(Profile* profile, Extension* extension, + const GURL& url, bool as_panel) { std::wstring app_name = web_app::GenerateApplicationNameFromURL(url); RegisterAppPrefs(app_name); - Browser* browser = Browser::CreateForApp(app_name, profile, as_panel); - browser->AddTabWithURL(url, GURL(), PageTransition::START_PAGE, true, -1, + Browser* browser = Browser::CreateForApp(app_name, extension, profile, + as_panel); + browser->AddTabWithURL(extension ? extension->GetFullLaunchURL() : url, + GURL(), PageTransition::START_PAGE, true, -1, false, NULL); TabContents* tab_contents = browser->GetSelectedTabContents(); @@ -440,8 +452,7 @@ void Browser::OpenApplicationWindow(Profile* profile, const GURL& url, // static void Browser::OpenApplicationWindow(Profile* profile, Extension* extension) { - OpenApplicationWindow(profile, - extension->GetFullLaunchURL(), + OpenApplicationWindow(profile, extension, GURL(), (extension->launch_container() == Extension::LAUNCH_PANEL)); } @@ -720,7 +731,7 @@ TabContents* Browser::AddTabWithURL(const GURL& url, SiteInstance* instance, const std::string& app_extension_id) { TabContents* contents = NULL; - if (type_ == TYPE_NORMAL || tabstrip_model()->empty()) { + if (SupportsWindowFeature(FEATURE_TABSTRIP) || tabstrip_model()->empty()) { GURL url_to_load = url; if (url_to_load.is_empty()) url_to_load = GetHomePage(); @@ -1262,11 +1273,18 @@ bool Browser::SupportsWindowFeature(WindowFeature feature) const { hide_ui_for_fullscreen = window_ && window_->IsFullscreen(); #endif if (!hide_ui_for_fullscreen) { - if (type() == TYPE_NORMAL) - features |= FEATURE_TABSTRIP | FEATURE_TOOLBAR; - else + if (type() != TYPE_NORMAL && type() != TYPE_EXTENSION_APP) features |= FEATURE_TITLEBAR; - if ((type() & Browser::TYPE_APP) == 0) + + if (type() == TYPE_NORMAL || type() == TYPE_EXTENSION_APP) + features |= FEATURE_TABSTRIP; + + // Note: the toolbar is collapsed for TYPE_EXTENSION_APP but it is still + // there. + if (type() == TYPE_NORMAL || type() == TYPE_EXTENSION_APP) + features |= FEATURE_TOOLBAR; + + if (type() != TYPE_EXTENSION_APP && (type() & Browser::TYPE_APP) == 0) features |= FEATURE_LOCATIONBAR; } return !!(features & feature); @@ -1904,7 +1922,7 @@ TabContents* Browser::AddBlankTabAt(int index, bool foreground) { Browser* Browser::CreateNewStripWithContents(TabContents* detached_contents, const gfx::Rect& window_bounds, const DockInfo& dock_info) { - DCHECK(type_ == TYPE_NORMAL); + DCHECK(SupportsWindowFeature(FEATURE_TABSTRIP)); gfx::Rect new_window_bounds = window_bounds; bool maximize = false; @@ -1979,7 +1997,8 @@ void Browser::DuplicateContentsAt(int index) { if (type_ & TYPE_APP) { DCHECK((type_ & TYPE_POPUP) == 0); DCHECK(type_ != TYPE_APP_PANEL); - browser = Browser::CreateForApp(app_name_, profile_, false); + browser = Browser::CreateForApp(app_name_, extension_app_, profile_, + false); } else if (type_ == TYPE_POPUP) { browser = Browser::CreateForPopup(profile_); } @@ -2243,9 +2262,9 @@ void Browser::AddNewContents(TabContents* source, DCHECK(disposition != CURRENT_TAB); // Can't create a new contents for the // current tab. - // If this is an application we can only have one tab so we need to process - // this in tabbed browser window. - if (type_ != TYPE_NORMAL && tabstrip_model_.count() > 0 && + // If this is a window with no tabstrip, we can only have one tab so we need + // to process this in tabbed browser window. + if (!SupportsWindowFeature(FEATURE_TABSTRIP) && tabstrip_model_.count() > 0 && disposition != NEW_WINDOW && disposition != NEW_POPUP) { Browser* b = GetOrCreateTabbedBrowser(profile_); DCHECK(b); @@ -2428,7 +2447,7 @@ void Browser::ConvertContentsToApplication(TabContents* contents) { RegisterAppPrefs(app_name); DetachContents(contents); - Browser* browser = Browser::CreateForApp(app_name, profile_, false); + Browser* browser = Browser::CreateForApp(app_name, NULL, profile_, false); browser->tabstrip_model()->AppendTabContents(contents, true); TabContents* tab_contents = browser->GetSelectedTabContents(); tab_contents->GetMutableRendererPrefs()->can_accept_load_drops = false; @@ -3342,9 +3361,9 @@ void Browser::OpenURLAtIndex(TabContents* source, } } - // If this is not a normal window (such as a popup or an application), we can - // only have one tab so a new tab always goes into a tabbed browser window. - if (type_ != TYPE_NORMAL && + // If this browser doeesn't support tabs, we can only have one tab so a new + // tab always goes into a tabbed browser window. + if (!SupportsWindowFeature(FEATURE_TABSTRIP) && disposition != CURRENT_TAB && disposition != NEW_WINDOW) { // If the disposition is OFF_THE_RECORD we don't want to create a new // browser that will itself create another OTR browser. This will result in diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index c293e97f..8c28147 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -55,13 +55,21 @@ class Browser : public TabStripModelDelegate, enum Type { TYPE_NORMAL = 1, TYPE_POPUP = 2, + // The old-style app created via "Create application shortcuts". TYPE_APP = 4, + // The new-style app created by installing a crx. This kinda needs to be + // separate because we require larger icons and an application name that + // are found in the crx. If we ever decide to create this kind of app using + // some other system (eg some web standard), maybe we should generalize this + // name to TYPE_MULTITAB or something. + TYPE_EXTENSION_APP = 8, TYPE_APP_POPUP = TYPE_APP | TYPE_POPUP, - TYPE_DEVTOOLS = TYPE_APP | 8, - TYPE_APP_PANEL = TYPE_APP | 16, + TYPE_DEVTOOLS = TYPE_APP | 16, + TYPE_APP_PANEL = TYPE_APP | 32, TYPE_ANY = TYPE_NORMAL | TYPE_POPUP | TYPE_APP | + TYPE_EXTENSION_APP | TYPE_DEVTOOLS | TYPE_APP_PANEL }; @@ -118,16 +126,22 @@ class Browser : public TabStripModelDelegate, // Like Create, but creates a tabstrip-less popup window. static Browser* CreateForPopup(Profile* profile); - // Like Create, but creates a tabstrip-less and toolbar-less "app" window for - // the specified app. |is_panel| specifies whether the browser should be - // opened in an app panel window. - static Browser* CreateForApp(const std::wstring& app_name, Profile* profile, + // Like Create, but creates a toolbar-less "app" window for the specified + // app. |app_name| is required and is used to identify the window to the + // shell. |extension| is optional. If supplied, we create a window with + // a bigger icon and title text, that supports tabs. + static Browser* CreateForApp(const std::wstring& app_name, + Extension* extension, + Profile* profile, bool is_panel); // Like Create, but creates a tabstrip-less and toolbar-less // DevTools "app" window. static Browser* CreateForDevTools(Profile* profile); + // Returns the extension app associated with this window, if any. + Extension* extension_app() { return extension_app_; } + // Set overrides for the initial window bounds and maximized state. void set_override_bounds(const gfx::Rect& bounds) { override_bounds_ = bounds; @@ -200,10 +214,11 @@ class Browser : public TabStripModelDelegate, // Opens a new application window for the specified url. If |as_panel| // is true, the application will be opened as a Browser::Type::APP_PANEL in - // app panel window, otherwise it will be opened as a Browser::Type::APP, - // a.k.a. "thin frame". - static void OpenApplicationWindow(Profile* profile, const GURL& url, - bool as_panel); + // app panel window, otherwise it will be opened as as either + // Browser::Type::APP a.k.a. "thin frame" (if |extension| is NULL) or + // Browser::Type::EXTENSION_APP (if |extension| is non-NULL). + static void OpenApplicationWindow(Profile* profile, Extension* extension, + const GURL& url, bool as_panel); // Open an application for |extension| in a new application window or panel. static void OpenApplicationWindow(Profile* profile, Extension* extension); @@ -946,6 +961,9 @@ class Browser : public TabStripModelDelegate, // from a TabContents. Currently, only one pending action is allowed. WebAppAction pending_web_app_action_; + // The extension app associated with this window, if any. + Extension* extension_app_; + DISALLOW_COPY_AND_ASSIGN(Browser); }; diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index db5d173..a5e1706 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -595,7 +595,7 @@ bool BrowserInit::LaunchWithProfile::OpenApplicationWindow(Profile* profile) { ChildProcessSecurityPolicy::GetInstance(); if (policy->IsWebSafeScheme(url.scheme()) || url.SchemeIs(chrome::kFileScheme)) { - Browser::OpenApplicationWindow(profile, url, false); + Browser::OpenApplicationWindow(profile, NULL, url, false); return true; } } diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc index 1ac66b7..46e0e89 100644 --- a/chrome/browser/extensions/extension_tabs_module.cc +++ b/chrome/browser/extensions/extension_tabs_module.cc @@ -1096,7 +1096,7 @@ static bool GetTabById(int tab_id, Profile* profile, static std::string GetWindowTypeText(Browser::Type type) { // Note: for app popups, we report "app". - if ((type & Browser::TYPE_APP) != 0) + if ((type & Browser::TYPE_APP) != 0 || type == Browser::TYPE_EXTENSION_APP) return keys::kWindowTypeValueApp; if ((type & Browser::TYPE_POPUP) != 0) return keys::kWindowTypeValuePopup; diff --git a/chrome/browser/resources/calendar_app/manifest.json b/chrome/browser/resources/calendar_app/manifest.json index 4cf0e5b..f04088b 100644 --- a/chrome/browser/resources/calendar_app/manifest.json +++ b/chrome/browser/resources/calendar_app/manifest.json @@ -15,7 +15,7 @@ "paths": [ "calendar" ]
},
"launch": {
- "type": "tab",
+ "container": "tab",
"web_url": "https://www.google.com/calendar/"
}
}
diff --git a/chrome/browser/resources/docs_app/manifest.json b/chrome/browser/resources/docs_app/manifest.json index f4893b5..edb3cc71 100644 --- a/chrome/browser/resources/docs_app/manifest.json +++ b/chrome/browser/resources/docs_app/manifest.json @@ -13,7 +13,7 @@ "origin": "https://docs.google.com/"
},
"launch": {
- "type": "tab",
+ "container": "window",
"web_url": "https://docs.google.com/"
}
}
diff --git a/chrome/browser/resources/gmail_app/manifest.json b/chrome/browser/resources/gmail_app/manifest.json index ec75488..69897d8 100644 --- a/chrome/browser/resources/gmail_app/manifest.json +++ b/chrome/browser/resources/gmail_app/manifest.json @@ -15,7 +15,7 @@ "paths": [ "mail" ]
},
"launch": {
- "type": "tab",
+ "container": "window",
"web_url": "https://mail.google.com/"
}
}
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 9ac90a9..1908aa3 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -2949,6 +2949,16 @@ void TabContents::Observe(NotificationType type, void TabContents::UpdateAppExtensionIcon(Extension* extension) { app_extension_icon_.reset(); + + // We don't show the big icons in tabs for TYPE_EXTENSION_APP windows because + // for those windows, we already have a big icon in the top-left outside any + // tab. Having big tab icons too looks kinda redonk. + if (!delegate_ || + !delegate_->GetBrowser() || + delegate_->GetBrowser()->type() == Browser::TYPE_EXTENSION_APP) { + return; + } + if (extension) { app_extension_image_loader_.reset(new ImageLoadingTracker(this)); app_extension_image_loader_->LoadImage( diff --git a/chrome/browser/view_ids.h b/chrome/browser/view_ids.h index 57943da..74fb526 100644 --- a/chrome/browser/view_ids.h +++ b/chrome/browser/view_ids.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-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. @@ -27,6 +27,8 @@ enum ViewID { VIEW_ID_TAB_9, VIEW_ID_TAB_LAST, + VIEW_ID_EXTENSION_APP_ICON, + VIEW_ID_EXTENSION_APP_TITLE, VIEW_ID_TAB_STRIP, // Toolbar & toolbar elements. diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 614659e..eb9620d 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -98,6 +98,10 @@ static int explicit_show_state = -1; // How round the 'new tab' style bookmarks bar is. static const int kNewtabBarRoundness = 5; + +// The maximum width of the big title shown for extension app windows. +static const int kExtensionAppTitleMaxWidth = 150; + // ------------ // Returned from BrowserView::GetClassName. @@ -384,6 +388,8 @@ BrowserView::BrowserView(Browser* browser) frame_(NULL), browser_(browser), active_bookmark_bar_(NULL), + extension_app_icon_(NULL), + extension_app_title_(NULL), tabstrip_(NULL), toolbar_(NULL), infobar_container_(NULL), @@ -398,7 +404,8 @@ BrowserView::BrowserView(Browser* browser) #endif extension_shelf_(NULL), last_focused_view_storage_id_( - views::ViewStorage::GetSharedInstance()->CreateStorageID()) { + views::ViewStorage::GetSharedInstance()->CreateStorageID()), + extension_app_icon_loader_(this) { browser_->tabstrip_model()->AddObserver(this); } @@ -1639,8 +1646,42 @@ void BrowserView::Init() { LoadAccelerators(); SetAccessibleName(l10n_util::GetString(IDS_PRODUCT_NAME)); + if (browser_->extension_app()) { + extension_app_icon_ = new views::ImageView(); + extension_app_icon_->SetID(VIEW_ID_EXTENSION_APP_ICON); + AddChildView(extension_app_icon_); + + extension_app_title_ = new views::Label(); + extension_app_title_->SetFont( + extension_app_title_->font().DeriveFont(1, gfx::Font::BOLD)); + extension_app_title_->SetColor(SK_ColorWHITE); + extension_app_title_->SetID(VIEW_ID_EXTENSION_APP_TITLE); + AddChildView(extension_app_title_); + + extension_app_icon_loader_.LoadImage( + browser_->extension_app(), + browser_->extension_app()->GetIconPath( + Extension::EXTENSION_ICON_MEDIUM), + gfx::Size(Extension::EXTENSION_ICON_SMALL, + Extension::EXTENSION_ICON_SMALL), + ImageLoadingTracker::CACHE); + + extension_app_title_->SetText( + UTF8ToWide(browser_->extension_app()->name())); + extension_app_title_->SizeToPreferredSize(); + + if (extension_app_title_->width() > kExtensionAppTitleMaxWidth) { + extension_app_title_->SetBounds(extension_app_title_->x(), + extension_app_title_->y(), + kExtensionAppTitleMaxWidth, + extension_app_title_->height()); + } + } + tabstrip_ = CreateTabStrip(browser_->tabstrip_model()); tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP)); + if (browser_->extension_app() && tabstrip_->AsTabStrip()) + tabstrip_->AsTabStrip()->set_new_tab_button_enabled(false); AddChildView(tabstrip_); frame_->TabStripCreated(tabstrip_); @@ -1719,6 +1760,12 @@ void BrowserView::InitSystemMenu() { } #endif +void BrowserView::OnImageLoaded(SkBitmap* image, ExtensionResource resource, + int index) { + if (image) + extension_app_icon_->SetImage(*image); +} + BrowserViewLayout* BrowserView::GetBrowserViewLayout() const { return static_cast<BrowserViewLayout*>(GetLayoutManager()); } diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index 79f9858..10292bf 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -15,6 +15,7 @@ #include "build/build_config.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/extensions/image_loading_tracker.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/views/frame/browser_bubble_host.h" #include "chrome/browser/views/frame/browser_frame.h" @@ -23,6 +24,8 @@ #include "chrome/browser/views/tabs/base_tab_strip.h" #include "chrome/browser/views/unhandled_keyboard_event_handler.h" #include "gfx/native_widget_types.h" +#include "views/controls/image_view.h" +#include "views/controls/label.h" #include "views/window/client_view.h" #include "views/window/window_delegate.h" @@ -81,7 +84,8 @@ class BrowserView : public BrowserBubbleHost, public menus::SimpleMenuModel::Delegate, public views::WindowDelegate, public views::ClientView, - public InfoBarContainer::Delegate { + public InfoBarContainer::Delegate, + public ImageLoadingTracker::Observer { public: // The browser view's class name. static const char kViewClassName[]; @@ -145,6 +149,14 @@ class BrowserView : public BrowserBubbleHost, // offset of IDR_THEME_TOOLBAR. gfx::Rect GetTabStripBounds() const; + // Accessor for the big icon used with TYPE_EXTENSION_APP, or NULL if this + // browser isn't TYPE_EXTENSION_APP. + views::ImageView* extension_app_icon() const { return extension_app_icon_; } + + // Accessor for the big title used with TYPE_EXTENSION_APP, or NULL if this + // browser isn't TYPE_EXTENSION_APP. + views::Label* extension_app_title() const { return extension_app_title_; } + // Accessor for the TabStrip. BaseTabStrip* tabstrip() const { return tabstrip_; } @@ -241,6 +253,10 @@ class BrowserView : public BrowserBubbleHost, BrowserExtender* browser_extender() const { return browser_extender_.get(); } + // Overriden from ImageLoadingTracker::Observer. + virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource, + int index); + // Overridden from BrowserWindow: virtual void Show(); virtual void SetBounds(const gfx::Rect& bounds); @@ -486,6 +502,14 @@ class BrowserView : public BrowserBubbleHost, // or is bookmark_bar_view_ if the bookmark bar is showing. views::View* active_bookmark_bar_; + // The big icon in the top-left if this browser is TYPE_EXTENSION_APP, or + // NULL otherwise. + views::ImageView* extension_app_icon_; + + // The big title text in the top-left if this browser is TYPE_EXTENSION_APP, + // or NULL otherwise. + views::Label* extension_app_title_; + // The TabStrip. BaseTabStrip* tabstrip_; @@ -576,6 +600,9 @@ class BrowserView : public BrowserBubbleHost, scoped_ptr<AccessibleWidgetHelper> accessible_widget_helper_; #endif + // Loads extension_app_icon_ asynchronously on the file thread. + ImageLoadingTracker extension_app_icon_loader_; + DISALLOW_COPY_AND_ASSIGN(BrowserView); }; diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc index 2b0f2e0..505a913 100644 --- a/chrome/browser/views/frame/browser_view_layout.cc +++ b/chrome/browser/views/frame/browser_view_layout.cc @@ -36,6 +36,11 @@ const int kBrowserViewTabStripHorizontalOverlap = 4; // An offset distance between certain toolbars and the toolbar that preceded // them in layout. const int kSeparationLineHeight = 1; +// Spacing between extension app icon and title. +const int kExtensionAppIconTitleSpacing = 4; +// We don't actually display the toolbar in extension app mode, but this is the +// height of the spacing where it usually goes. +const int kExtensionAppToolbarHeight = 7; } // namespace @@ -43,7 +48,9 @@ const int kSeparationLineHeight = 1; // BrowserViewLayout, public: BrowserViewLayout::BrowserViewLayout() - : tabstrip_(NULL), + : extension_app_icon_(NULL), + extension_app_title_(NULL), + tabstrip_(NULL), toolbar_(NULL), contents_split_(NULL), contents_container_(NULL), @@ -206,6 +213,8 @@ void BrowserViewLayout::Installed(views::View* host) { extension_shelf_ = NULL; active_bookmark_bar_ = NULL; tabstrip_ = NULL; + extension_app_icon_ = NULL; + extension_app_title_ = NULL; browser_view_ = static_cast<BrowserView*>(host); } @@ -235,6 +244,12 @@ void BrowserViewLayout::ViewAdded(views::View* host, views::View* view) { case VIEW_ID_TAB_STRIP: tabstrip_ = static_cast<BaseTabStrip*>(view); break; + case VIEW_ID_EXTENSION_APP_ICON: + extension_app_icon_ = static_cast<views::ImageView*>(view); + break; + case VIEW_ID_EXTENSION_APP_TITLE: + extension_app_title_ = static_cast<views::Label*>(view); + break; } } @@ -248,6 +263,7 @@ void BrowserViewLayout::ViewRemoved(views::View* host, views::View* view) { void BrowserViewLayout::Layout(views::View* host) { vertical_layout_rect_ = browser_view_->GetLocalBounds(true); + LayoutExtensionAppIconAndTitle(); int top = LayoutTabStrip(); top = LayoutToolbar(top); top = LayoutBookmarkAndInfoBars(top); @@ -276,6 +292,26 @@ gfx::Size BrowserViewLayout::GetPreferredSize(views::View* host) { ////////////////////////////////////////////////////////////////////////////// // BrowserViewLayout, private: +void BrowserViewLayout::LayoutExtensionAppIconAndTitle() { + if (browser_view_->browser()->type() != Browser::TYPE_EXTENSION_APP) + return; + + extension_app_icon_->SetVisible(true); + extension_app_icon_->SetBounds(0, 0, Extension::EXTENSION_ICON_SMALL, + Extension::EXTENSION_ICON_SMALL); + + extension_app_title_->SetVisible(true); + + // Position the title vertically centered with the icon and slightly to its + // right. + extension_app_title_->SetX( + extension_app_icon_->x() + extension_app_icon_->width() + + kExtensionAppIconTitleSpacing); + extension_app_title_->SetY( + extension_app_icon_->y() + + ((extension_app_icon_->height() - extension_app_title_->height()) / 2)); +} + int BrowserViewLayout::LayoutTabStrip() { if (!browser_view_->IsTabStripVisible()) { tabstrip_->SetVisible(false); @@ -314,8 +350,22 @@ int BrowserViewLayout::LayoutToolbar(int top) { ((visible && browser_view_->IsTabStripVisible()) ? kToolbarTabStripVerticalOverlap : 0); } - int height = visible ? toolbar_->GetPreferredSize().height() : 0; - toolbar_->SetVisible(visible); + int height = 0; + if (visible) { + if (browser_view_->browser()->type() == Browser::TYPE_EXTENSION_APP) { + // TODO(aa): Find a more sensible way to handle this. We want + // OpaqueBroserFrame to continue to paint the area where the toolstrip + // would be, but we don't actually want a toolbar in this case. + toolbar_->SetVisible(false); + height = kExtensionAppToolbarHeight; + } else { + toolbar_->SetVisible(true); + height = toolbar_->GetPreferredSize().height(); + } + } else { + toolbar_->SetVisible(false); + } + toolbar_->SetBounds(vertical_layout_rect_.x(), y, browser_view_width, height); return y + height; } diff --git a/chrome/browser/views/frame/browser_view_layout.h b/chrome/browser/views/frame/browser_view_layout.h index 068d8302..6dc3624 100644 --- a/chrome/browser/views/frame/browser_view_layout.h +++ b/chrome/browser/views/frame/browser_view_layout.h @@ -47,6 +47,9 @@ class BrowserViewLayout : public views::LayoutManager { // for laying out subsequent controls. virtual int LayoutTabStrip(); + // Layout the big icon and title in the top left of extension app windows. + void LayoutExtensionAppIconAndTitle(); + // Layout the following controls, starting at |top|, returns the coordinate // of the bottom of the control, for laying out the next control. int LayoutToolbar(int top); @@ -68,6 +71,8 @@ class BrowserViewLayout : public views::LayoutManager { int LayoutExtensionShelf(int bottom); // Child views that the layout manager manages. + views::ImageView* extension_app_icon_; + views::Label* extension_app_title_; BaseTabStrip* tabstrip_; ToolbarView* toolbar_; views::View* contents_split_; diff --git a/chrome/browser/views/frame/opaque_browser_frame_view.cc b/chrome/browser/views/frame/opaque_browser_frame_view.cc index c91cb51..af74018 100644 --- a/chrome/browser/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/views/frame/opaque_browser_frame_view.cc @@ -95,6 +95,8 @@ const int kNewTabCaptionMaximizedSpacing = 16; // How far to indent the tabstrip from the left side of the screen when there // is no OTR icon. const int kTabStripIndent = 1; +// Spacing between extension app icon/title and tab strip. +const int kExtensionAppTabStripLeftSpacing = 10; } /////////////////////////////////////////////////////////////////////////////// @@ -195,10 +197,27 @@ gfx::Rect OpaqueBrowserFrameView::GetBoundsForTabStrip( int tabstrip_x = browser_view_->ShouldShowOffTheRecordAvatar() ? (otr_avatar_icon_->bounds().right() + kOTRSideSpacing) : NonClientBorderThickness() + kTabStripIndent; + + int tabstrip_y = NonClientTopBorderHeight(); + if (!frame_->GetWindow()->IsMaximized() && + !frame_->GetWindow()->IsFullscreen()) { + tabstrip_y += kNonClientRestoredExtraThickness; + } + int tabstrip_width = minimize_button_->x() - tabstrip_x - (frame_->GetWindow()->IsMaximized() ? kNewTabCaptionMaximizedSpacing : kNewTabCaptionRestoredSpacing); - return gfx::Rect(tabstrip_x, NonClientTopBorderHeight(), + + if (browser_view_->browser()->type() == Browser::TYPE_EXTENSION_APP) { + int tabstrip_offset = browser_view_->extension_app_title()->x() + + browser_view_->extension_app_title()->width() + + kExtensionAppTabStripLeftSpacing; + + tabstrip_x += tabstrip_offset; + tabstrip_width -= tabstrip_offset; + } + + return gfx::Rect(tabstrip_x, tabstrip_y, std::max(0, tabstrip_width), tabstrip->GetPreferredHeight()); } @@ -431,9 +450,7 @@ int OpaqueBrowserFrameView::NonClientTopBorderHeight() const { if (browser_view_->IsTabStripVisible() && window->IsMaximized()) return FrameBorderThickness() - kTabstripTopShadowThickness; - return FrameBorderThickness() + - ((window->IsMaximized() || window->IsFullscreen()) ? - 0 : kNonClientRestoredExtraThickness); + return FrameBorderThickness(); } int OpaqueBrowserFrameView::CaptionButtonY() const { @@ -815,7 +832,7 @@ void OpaqueBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) { client_area_top += browser_view_->GetToolbarBounds().y() + std::min(tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height(), toolbar_bounds.height()); - } else { + } else if (!browser_view_->IsTabStripVisible()) { // The toolbar isn't going to draw a client edge for us, so draw one // ourselves. SkBitmap* top_left = tp->GetBitmapNamed(IDR_APP_TOP_LEFT); diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc index 3521a88..262154f 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ b/chrome/browser/views/tabs/dragged_tab_controller.cc @@ -716,7 +716,8 @@ TabStrip* DraggedTabController::GetTabStripForPoint( BrowserView* browser = BrowserView::GetBrowserViewForNativeWindow(local_window); // We don't allow drops on windows that don't have tabstrips. - if (!browser || !browser->IsBrowserTypeNormal()) + if (!browser || + !browser->browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) return NULL; TabStrip* other_tabstrip = browser->tabstrip()->AsTabStrip(); diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc index e9ccb09..26011b4 100644 --- a/chrome/browser/views/tabs/tab_strip.cc +++ b/chrome/browser/views/tabs/tab_strip.cc @@ -248,7 +248,8 @@ TabStrip::TabStrip(TabStripModel* model) available_width_for_tabs_(-1), animation_container_(new AnimationContainer()), ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)), - animation_type_(ANIMATION_DEFAULT) { + animation_type_(ANIMATION_DEFAULT), + new_tab_button_enabled_(true) { Init(); } @@ -521,7 +522,12 @@ void TabStrip::Layout() { for (int i = 0, tab_count = GetTabCount(); i < tab_count; ++i) tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds); - newtab_button_->SetBounds(newtab_button_bounds_); + if (new_tab_button_enabled_) { + newtab_button_->SetBounds(newtab_button_bounds_); + newtab_button_->SetVisible(true); + } else { + newtab_button_->SetVisible(false); + } SchedulePaint(); } diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index 57724ce..79a3af3 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -61,6 +61,16 @@ class TabStrip : public BaseTabStrip, // Accessors for the model and individual Tabs. TabStripModel* model() const { return model_; } + // Set whether the new tab button is enabled. + void set_new_tab_button_enabled(bool enabled) { + new_tab_button_enabled_ = enabled; + } + + // Returns whether the new tab button is enabled. + bool new_tab_button_enabled() { + return new_tab_button_enabled_; + } + // Destroys the active drag controller. void DestroyDragController(); @@ -458,6 +468,9 @@ class TabStrip : public BaseTabStrip, // Set for special animations. AnimationType animation_type_; + // Whether the new tab button is being displayed. + bool new_tab_button_enabled_; + DISALLOW_COPY_AND_ASSIGN(TabStrip); }; diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index 43d4430..3b2ce98 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -75,7 +75,8 @@ ToolbarView::ToolbarView(Browser* browser) browser_->command_updater()->AddCommandObserver(IDC_FORWARD, this); browser_->command_updater()->AddCommandObserver(IDC_HOME, this); browser_->command_updater()->AddCommandObserver(IDC_RELOAD, this); - if (browser->type() == Browser::TYPE_NORMAL) + + if (browser->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) display_mode_ = DISPLAYMODE_NORMAL; else display_mode_ = DISPLAYMODE_LOCATION; |