diff options
27 files changed, 432 insertions, 173 deletions
diff --git a/ash/wm/frame_painter.cc b/ash/wm/frame_painter.cc index 419cd39..d859c12 100644 --- a/ash/wm/frame_painter.cc +++ b/ash/wm/frame_painter.cc @@ -66,9 +66,6 @@ const int kCloseButtonOffsetY = 0; // The size and close buttons are designed to slightly overlap in order // to do fancy hover highlighting. const int kSizeButtonOffsetX = -1; -// Space between size and immersive buttons. -// TODO(jamescook): Adjust for final art. -const int kImmersiveButtonOffsetX = 2; // In the pre-Ash era the web content area had a frame along the left edge, so // user-generated theme images for the new tab page assume they are shifted // right relative to the header. Now that we have removed the left edge frame @@ -142,7 +139,6 @@ FramePainter::FramePainter() window_icon_(NULL), size_button_(NULL), close_button_(NULL), - immersive_button_(NULL), window_(NULL), button_separator_(NULL), top_left_corner_(NULL), @@ -233,12 +229,6 @@ void FramePainter::UpdateSoloWindowHeader(RootWindow* root_window) { UpdateSoloWindowInRoot(root_window, NULL /* ignorable_window */); } -void FramePainter::AddImmersiveButton(views::ToggleImageButton* button) { - DCHECK(button); - immersive_button_ = button; - immersive_button_->SetVisible(frame_->IsMaximized()); -} - gfx::Rect FramePainter::GetBoundsForClientView( int top_height, const gfx::Rect& window_bounds) const { @@ -303,10 +293,6 @@ int FramePainter::NonClientHitTest(views::NonClientFrameView* view, if (size_button_->visible() && size_button_->GetMirroredBounds().Contains(point)) return HTMAXBUTTON; - if (immersive_button_ && - immersive_button_->visible() && - immersive_button_->GetMirroredBounds().Contains(point)) - return HTCLIENT; // No special constant, but cannot be HTCAPTION. // Caption is a safe default. return HTCAPTION; @@ -322,8 +308,6 @@ gfx::Size FramePainter::GetMinimumSize(views::NonClientFrameView* view) { int title_width = GetTitleOffsetX() + size_button_->width() + kSizeButtonOffsetX + close_button_->width() + kCloseButtonOffsetX; - if (immersive_button_ && immersive_button_->visible()) - title_width += immersive_button_->width() + kImmersiveButtonOffsetX; if (title_width > min_size.width()) min_size.set_width(title_width); return min_size; @@ -338,10 +322,6 @@ int FramePainter::GetRightInset() const { gfx::Size size_button_size = size_button_->GetPreferredSize(); int inset = close_size.width() + kCloseButtonOffsetX + size_button_size.width() + kSizeButtonOffsetX; - if (immersive_button_ && immersive_button_->visible()) { - gfx::Size immersive_size = immersive_button_->GetPreferredSize(); - inset += immersive_size.width() + kImmersiveButtonOffsetX; - } return inset; } @@ -520,8 +500,10 @@ void FramePainter::PaintTitleBar(views::NonClientFrameView* view, void FramePainter::LayoutHeader(views::NonClientFrameView* view, bool shorter_layout) { - // The new assets only make sense if the window is actually maximized. - if (shorter_layout && frame_->IsMaximized() && + // The new assets only make sense if the window is actually maximized or + // fullscreen. + if (shorter_layout && + (frame_->IsMaximized() || frame_->IsFullscreen()) && GetTrackedByWorkspace(frame_->GetNativeWindow())) { SetButtonImages(close_button_, IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, @@ -559,17 +541,6 @@ void FramePainter::LayoutHeader(views::NonClientFrameView* view, IDR_AURA_WINDOW_MAXIMIZE_P); } - if (immersive_button_) { - SetButtonImages(immersive_button_, - IDR_AURA_WINDOW_IMMERSIVE_ENTER, - IDR_AURA_WINDOW_IMMERSIVE_ENTER_H, - IDR_AURA_WINDOW_IMMERSIVE_ENTER_P); - SetToggledButtonImages(immersive_button_, - IDR_AURA_WINDOW_IMMERSIVE_EXIT, - IDR_AURA_WINDOW_IMMERSIVE_EXIT_H, - IDR_AURA_WINDOW_IMMERSIVE_EXIT_P); - } - gfx::Size close_size = close_button_->GetPreferredSize(); close_button_->SetBounds( view->width() - close_size.width() - kCloseButtonOffsetX, @@ -584,16 +555,6 @@ void FramePainter::LayoutHeader(views::NonClientFrameView* view, size_button_size.width(), size_button_size.height()); - if (immersive_button_) { - gfx::Size immersive_size = immersive_button_->GetPreferredSize(); - // TODO(jamescook): Fix layout when we have real art. - immersive_button_->SetBounds( - size_button_->x() - immersive_size.width() - kImmersiveButtonOffsetX, - size_button_->y(), - immersive_size.width(), - immersive_size.height()); - } - if (window_icon_) { window_icon_->SetBoundsRect( gfx::Rect(kIconOffsetX, kIconOffsetY, kIconSize, kIconSize)); @@ -633,10 +594,6 @@ void FramePainter::OnWindowPropertyChanged(aura::Window* window, gfx::Insets(kResizeInsideBoundsSize, kResizeInsideBoundsSize, kResizeInsideBoundsSize, kResizeInsideBoundsSize)); } - - // Immersive button only shows in maximized windows. - if (immersive_button_) - immersive_button_->SetVisible(frame_->IsMaximized()); } void FramePainter::OnWindowVisibilityChanged(aura::Window* window, diff --git a/ash/wm/frame_painter.h b/ash/wm/frame_painter.h index 2f7b5d0..e02ca04 100644 --- a/ash/wm/frame_painter.h +++ b/ash/wm/frame_painter.h @@ -76,9 +76,6 @@ class ASH_EXPORT FramePainter : public aura::WindowObserver, // using frame painters across all root windows. static void UpdateSoloWindowHeader(aura::RootWindow* root_window); - // Adds an "immersive mode" button to the layout. Does not take ownership. - void AddImmersiveButton(views::ToggleImageButton* button); - // Helpers for views::NonClientFrameView implementations. gfx::Rect GetBoundsForClientView(int top_height, const gfx::Rect& window_bounds) const; @@ -144,7 +141,6 @@ class ASH_EXPORT FramePainter : public aura::WindowObserver, private: FRIEND_TEST_ALL_PREFIXES(FramePainterTest, Basics); - FRIEND_TEST_ALL_PREFIXES(FramePainterTest, ImmersiveButton); FRIEND_TEST_ALL_PREFIXES(FramePainterTest, CreateAndDeleteSingleWindow); FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeader); FRIEND_TEST_ALL_PREFIXES(FramePainterTest, UseSoloWindowHeaderMultiDisplay); @@ -213,7 +209,6 @@ class ASH_EXPORT FramePainter : public aura::WindowObserver, views::View* window_icon_; // May be NULL. views::ImageButton* size_button_; views::ImageButton* close_button_; - views::ToggleImageButton* immersive_button_; // May be NULL. aura::Window* window_; // Window frame header/caption parts. diff --git a/ash/wm/frame_painter_unittest.cc b/ash/wm/frame_painter_unittest.cc index ecd87f2..4fab97b 100644 --- a/ash/wm/frame_painter_unittest.cc +++ b/ash/wm/frame_painter_unittest.cc @@ -16,18 +16,36 @@ #include "ui/aura/root_window.h" #include "ui/aura/window_observer.h" #include "ui/base/hit_test.h" +#include "ui/base/theme_provider.h" #include "ui/gfx/screen.h" +#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/window/non_client_view.h" -using views::Widget; +using ui::ThemeProvider; +using views::Button; using views::ImageButton; +using views::NonClientFrameView; using views::ToggleImageButton; +using views::Widget; namespace { +bool ImagesMatch(ImageButton* button, + int normal_image_id, + int hovered_image_id, + int pressed_image_id) { + ThemeProvider* theme = button->GetWidget()->GetThemeProvider(); + gfx::ImageSkia* normal = theme->GetImageSkiaNamed(normal_image_id); + gfx::ImageSkia* hovered = theme->GetImageSkiaNamed(hovered_image_id); + gfx::ImageSkia* pressed = theme->GetImageSkiaNamed(pressed_image_id); + return button->GetImage(Button::STATE_NORMAL).BackedBySameObjectAs(*normal) && + button->GetImage(Button::STATE_HOVERED).BackedBySameObjectAs(*hovered) && + button->GetImage(Button::STATE_PRESSED).BackedBySameObjectAs(*pressed); +} + class ResizableWidgetDelegate : public views::WidgetDelegate { public: ResizableWidgetDelegate(views::Widget* widget) { @@ -132,37 +150,6 @@ TEST_F(FramePainterTest, Basics) { EXPECT_EQ(0u, FramePainter::instances_->size()); } -// Ensure that the immersive button is created and visible when it should be. -TEST_F(FramePainterTest, ImmersiveButton) { - scoped_ptr<Widget> widget(CreateTestWidget()); - views::NonClientFrameView* frame = widget->non_client_view()->frame_view(); - FramePainter painter; - ImageButton size(NULL); - ImageButton close(NULL); - painter.Init( - widget.get(), NULL, &size, &close, FramePainter::SIZE_BUTTON_MAXIMIZES); - - // No immersive button by default. - EXPECT_EQ(NULL, painter.immersive_button_); - - // Add an immersive button. - ToggleImageButton immersive(NULL); - painter.AddImmersiveButton(&immersive); - - // Immersive button starts invisible. - widget->Show(); - EXPECT_FALSE(immersive.visible()); - - // Maximizing the window makes it visible. - widget->Maximize(); - EXPECT_TRUE(immersive.visible()); - - // A point in the button is treated as client area, so button can be clicked. - painter.LayoutHeader(frame, false); - gfx::Point point = immersive.bounds().CenterPoint(); - EXPECT_EQ(HTCLIENT, painter.NonClientHitTest(frame, point)); -} - TEST_F(FramePainterTest, CreateAndDeleteSingleWindow) { // Ensure that creating/deleting a window works well and doesn't cause // crashes. See crbug.com/155634 @@ -197,6 +184,69 @@ TEST_F(FramePainterTest, CreateAndDeleteSingleWindow) { root->GetProperty(internal::kSoloWindowFramePainterKey)); } +TEST_F(FramePainterTest, LayoutHeader) { + scoped_ptr<Widget> widget(CreateTestWidget()); + ImageButton size_button(NULL); + ImageButton close_button(NULL); + NonClientFrameView* frame_view = widget->non_client_view()->frame_view(); + frame_view->AddChildView(&size_button); + frame_view->AddChildView(&close_button); + scoped_ptr<FramePainter> painter(new FramePainter); + painter->Init(widget.get(), + NULL, + &size_button, + &close_button, + FramePainter::SIZE_BUTTON_MAXIMIZES); + widget->Show(); + + // Basic layout. + painter->LayoutHeader(frame_view, false); + EXPECT_TRUE(ImagesMatch(&close_button, + IDR_AURA_WINDOW_CLOSE, + IDR_AURA_WINDOW_CLOSE_H, + IDR_AURA_WINDOW_CLOSE_P)); + EXPECT_TRUE(ImagesMatch(&size_button, + IDR_AURA_WINDOW_MAXIMIZE, + IDR_AURA_WINDOW_MAXIMIZE_H, + IDR_AURA_WINDOW_MAXIMIZE_P)); + + // Shorter layout. + painter->LayoutHeader(frame_view, true); + EXPECT_TRUE(ImagesMatch(&close_button, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE_H, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE_P)); + EXPECT_TRUE(ImagesMatch(&size_button, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE_H, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE_P)); + + // Maximized shorter layout. + widget->Maximize(); + painter->LayoutHeader(frame_view, true); + EXPECT_TRUE(ImagesMatch(&close_button, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P)); + EXPECT_TRUE(ImagesMatch(&size_button, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P)); + + // Fullscreen can show the buttons during an immersive reveal, so it should + // use the same images as maximized. + widget->SetFullscreen(true); + painter->LayoutHeader(frame_view, true); + EXPECT_TRUE(ImagesMatch(&close_button, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_H, + IDR_AURA_WINDOW_MAXIMIZED_CLOSE2_P)); + EXPECT_TRUE(ImagesMatch(&size_button, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_H, + IDR_AURA_WINDOW_MAXIMIZED_RESTORE2_P)); +} + TEST_F(FramePainterTest, UseSoloWindowHeader) { // Create a widget and a painter for it. scoped_ptr<Widget> w1(CreateTestWidget()); diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index fc1bf57..5699754 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc @@ -85,22 +85,25 @@ void ChromeShellDelegate::NewWindow(bool is_incognito) { } void ChromeShellDelegate::ToggleMaximized() { + // Only toggle if the user has a window open. aura::Window* window = ash::wm::GetActiveWindow(); if (!window) return; + + // TODO(jamescook): If immersive mode replaces fullscreen, rename this + // function and the interface to ToggleFullscreen. + if (CommandLine::ForCurrentProcess()-> + HasSwitch(ash::switches::kAshImmersiveMode)) { + chrome::ToggleFullscreenMode(GetTargetBrowser()); + return; + } + // Get out of fullscreen when in fullscreen mode. if (ash::wm::IsWindowFullscreen(window)) { chrome::ToggleFullscreenMode(GetTargetBrowser()); return; } ash::wm::ToggleMaximizedWindow(window); - if (CommandLine::ForCurrentProcess()-> - HasSwitch(ash::switches::kAshImmersiveMode)) { - // Experiment with automatically entering immersive mode when the user - // presses the F4 maximize key. - window->SetProperty(ash::internal::kImmersiveModeKey, - ash::wm::IsWindowMaximized(window)); - } } void ChromeShellDelegate::RestoreTab() { diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index edc857f..53e1589 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -2167,12 +2167,9 @@ void Browser::UpdateBookmarkBarState(BookmarkBarStateChangeReason reason) { } bool Browser::ShouldHideUIForFullscreen() const { - // On Mac, fullscreen mode has most normal things (in a slide-down panel). On - // other platforms, we hide some controls when in fullscreen mode. -#if defined(OS_MACOSX) - return false; -#endif - return window_ && window_->IsFullscreen(); + // Windows and GTK remove the top controls in fullscreen, but Mac and Ash + // keep the controls in a slide-down panel. + return window_ && window_->ShouldHideUIForFullscreen(); } bool Browser::MaybeCreateBackgroundContents(int route_id, diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index a8ffedc..4eb144b 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc @@ -786,12 +786,9 @@ void BrowserCommandController::TabRestoreServiceDestroyed( //////////////////////////////////////////////////////////////////////////////// // BrowserCommandController, private: -bool BrowserCommandController::IsShowingMainUI(bool is_fullscreen) { -#if !defined(OS_MACOSX) - return browser_->is_type_tabbed() && !is_fullscreen; -#else - return browser_->is_type_tabbed(); -#endif +bool BrowserCommandController::IsShowingMainUI() { + bool should_hide_ui = window() && window()->ShouldHideUIForFullscreen(); + return browser_->is_type_tabbed() && !should_hide_ui; } void BrowserCommandController::InitCommandState() { @@ -973,9 +970,7 @@ void BrowserCommandController::UpdateSharedCommandsForIncognitoAvailability( void BrowserCommandController::UpdateCommandsForIncognitoAvailability() { UpdateSharedCommandsForIncognitoAvailability(&command_updater_, profile()); - const bool show_main_ui = - IsShowingMainUI(window() && window()->IsFullscreen()); - if (!show_main_ui) { + if (!IsShowingMainUI()) { command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, false); command_updater_.UpdateCommandEnabled(IDC_OPTIONS, false); } @@ -1072,12 +1067,10 @@ void BrowserCommandController::UpdateCommandsForBookmarkEditing() { } void BrowserCommandController::UpdateCommandsForBookmarkBar() { - const bool show_main_ui = - IsShowingMainUI(window() && window()->IsFullscreen()); command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR, browser_defaults::bookmarks_enabled && !profile()->GetPrefs()->IsManagedPreference(prefs::kShowBookmarkBar) && - show_main_ui); + IsShowingMainUI()); } void BrowserCommandController::UpdateCommandsForFileSelectionDialogs() { @@ -1087,8 +1080,7 @@ void BrowserCommandController::UpdateCommandsForFileSelectionDialogs() { void BrowserCommandController::UpdateCommandsForFullscreenMode( FullScreenMode fullscreen_mode) { - const bool show_main_ui = - IsShowingMainUI(fullscreen_mode != FULLSCREEN_DISABLED); + bool show_main_ui = IsShowingMainUI(); bool main_not_fullscreen = show_main_ui && (fullscreen_mode == FULLSCREEN_DISABLED); @@ -1155,8 +1147,7 @@ void BrowserCommandController::UpdateCommandsForFullscreenMode( } void BrowserCommandController::UpdateCommandsForMultipleProfiles() { - bool show_main_ui = IsShowingMainUI(window() && window()->IsFullscreen()); - bool enable = show_main_ui && + bool enable = IsShowingMainUI() && !profile()->IsOffTheRecord() && profile_manager_ && AvatarMenuModel::ShouldShowAvatarMenu(); diff --git a/chrome/browser/ui/browser_command_controller.h b/chrome/browser/ui/browser_command_controller.h index e9fa627..543b841 100644 --- a/chrome/browser/ui/browser_command_controller.h +++ b/chrome/browser/ui/browser_command_controller.h @@ -131,7 +131,7 @@ class BrowserCommandController : public CommandUpdaterDelegate, // not the single-tab one) is shown. Used for updating window command states // only. Consider using SupportsWindowFeature if you need the mentioned // functionality anywhere else. - bool IsShowingMainUI(bool is_fullscreen); + bool IsShowingMainUI(); // Initialize state for all browser commands. void InitCommandState(); diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc index 7188a95..5f412bf 100644 --- a/chrome/browser/ui/browser_command_controller_unittest.cc +++ b/chrome/browser/ui/browser_command_controller_unittest.cc @@ -11,6 +11,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window_state.h" #include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -178,3 +179,142 @@ TEST_F(BrowserCommandControllerTest, AvatarMenuDisabledWhenOnlyOneProfile) { testing_profile_manager.DeleteTestingProfile("p2"); } + +////////////////////////////////////////////////////////////////////////////// + +// A test browser window that can toggle fullscreen state. +class FullscreenTestBrowserWindow : public TestBrowserWindow { + public: + FullscreenTestBrowserWindow() : fullscreen_(false) {} + virtual ~FullscreenTestBrowserWindow() {} + + // TestBrowserWindow overrides: + virtual bool ShouldHideUIForFullscreen() const { + return fullscreen_; + } + virtual bool IsFullscreen() const OVERRIDE { + return fullscreen_; + } + virtual void EnterFullscreen( + const GURL& url, FullscreenExitBubbleType type) OVERRIDE { + fullscreen_ = true; + } + virtual void ExitFullscreen() OVERRIDE { + fullscreen_ = false; + } + + private: + bool fullscreen_; + + DISALLOW_COPY_AND_ASSIGN(FullscreenTestBrowserWindow); +}; + +// Test that uses FullscreenTestBrowserWindow for its window. +class BrowserCommandControllerFullscreenTest + : public BrowserWithTestWindowTest { + public: + BrowserCommandControllerFullscreenTest() {} + virtual ~BrowserCommandControllerFullscreenTest() {} + + // BrowserWithTestWindowTest overrides: + virtual void SetUp() { + // Must be set before base SetUp() is called. + set_window(new FullscreenTestBrowserWindow); + BrowserWithTestWindowTest::SetUp(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(BrowserCommandControllerFullscreenTest); +}; + +TEST_F(BrowserCommandControllerFullscreenTest, + UpdateCommandsForFullscreenMode) { + // Defaults for a tabbed browser. + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_AS_TAB)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_TOOLBAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_SEARCH)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_MENU_BAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_NEXT_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_PREVIOUS_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_BOOKMARKS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEVELOPER_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FEEDBACK)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_EDIT_SEARCH_ENGINES)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_VIEW_PASSWORDS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_APP_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); + + // Simulate going fullscreen. + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser()->window()->IsFullscreen()); + browser()->command_controller()->FullscreenStateChanged(); +#if defined(OS_MACOS) + // Mac leaves things enabled in fullscreen. + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_AS_TAB)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_TOOLBAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_SEARCH)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_MENU_BAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_NEXT_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_PREVIOUS_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_BOOKMARKS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEVELOPER_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FEEDBACK)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_EDIT_SEARCH_ENGINES)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_VIEW_PASSWORDS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_APP_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); +#else + // Windows and GTK disable most commands in fullscreen. + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_AS_TAB)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_TOOLBAR)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_SEARCH)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_MENU_BAR)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_NEXT_PANE)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_PREVIOUS_PANE)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_BOOKMARKS)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_DEVELOPER_MENU)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FEEDBACK)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_EDIT_SEARCH_ENGINES)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_VIEW_PASSWORDS)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_APP_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); +#endif // defined(OS_MACOS) + + // Exit fullscreen. + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser()->window()->IsFullscreen()); + browser()->command_controller()->FullscreenStateChanged(); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_AS_TAB)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_TOOLBAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_LOCATION)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_SEARCH)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_MENU_BAR)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_NEXT_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_PREVIOUS_PANE)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FOCUS_BOOKMARKS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_DEVELOPER_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FEEDBACK)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_EDIT_SEARCH_ENGINES)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_VIEW_PASSWORDS)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_SHOW_APP_MENU)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); +} diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index fea45d9..65e4802 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h @@ -120,6 +120,10 @@ class BrowserWindow : public BaseWindow { const GURL& url, FullscreenExitBubbleType bubble_type) = 0; + // Windows and GTK remove the top controls in fullscreen, but Mac and Ash + // keep the controls in a slide-down panel. + virtual bool ShouldHideUIForFullscreen() const = 0; + // Returns true if the fullscreen bubble is visible. virtual bool IsFullscreenBubbleVisible() const = 0; diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index 59095c3..8ce489a0 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -72,6 +72,7 @@ class BrowserWindowCocoa : virtual void UpdateFullscreenExitBubbleContent( const GURL& url, FullscreenExitBubbleType bubble_type) OVERRIDE; + virtual bool ShouldHideUIForFullscreen() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; virtual bool IsFullscreenBubbleVisible() const OVERRIDE; virtual LocationBar* GetLocationBar() const OVERRIDE; diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index fe0670f..ba96f4c 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -355,6 +355,11 @@ void BrowserWindowCocoa::UpdateFullscreenExitBubbleContent( [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type]; } +bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const { + // On Mac, fullscreen mode has most normal things (in a slide-down panel). + return false; +} + bool BrowserWindowCocoa::IsFullscreen() const { if ([controller_ inPresentationMode]) CHECK([controller_ isFullscreen]); // Presentation mode must be fullscreen. diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc index 631e480..5f73598 100644 --- a/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc @@ -45,6 +45,7 @@ class FullscreenControllerTestWindow : public TestBrowserWindow { FullscreenExitBubbleType type) OVERRIDE; virtual void EnterFullscreen(); virtual void ExitFullscreen() OVERRIDE; + virtual bool ShouldHideUIForFullscreen() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; #if defined(OS_WIN) virtual void SetMetroSnapMode(bool enable) OVERRIDE; @@ -106,6 +107,10 @@ void FullscreenControllerTestWindow::ExitFullscreen() { } } +bool FullscreenControllerTestWindow::ShouldHideUIForFullscreen() const { + return IsFullscreen(); +} + bool FullscreenControllerTestWindow::IsFullscreen() const { #if defined(OS_MACOSX) return state_ == FULLSCREEN || state_ == TO_FULLSCREEN; diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc index b268fba..d120d84 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.cc +++ b/chrome/browser/ui/gtk/browser_window_gtk.cc @@ -858,6 +858,10 @@ void BrowserWindowGtk::ExitFullscreen() { gtk_window_maximize(window_); } +bool BrowserWindowGtk::ShouldHideUIForFullscreen() const { + return IsFullscreen(); +} + bool BrowserWindowGtk::IsFullscreen() const { return (state_ & GDK_WINDOW_STATE_FULLSCREEN); } diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h index aad6e17..d227e23 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.h +++ b/chrome/browser/ui/gtk/browser_window_gtk.h @@ -106,6 +106,7 @@ class BrowserWindowGtk virtual void UpdateFullscreenExitBubbleContent( const GURL& url, FullscreenExitBubbleType bubble_type) OVERRIDE; + virtual bool ShouldHideUIForFullscreen() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; virtual bool IsFullscreenBubbleVisible() const OVERRIDE; virtual LocationBar* GetLocationBar() const OVERRIDE; diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 11639c4..6aa4cd3 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc @@ -77,7 +77,6 @@ BrowserNonClientFrameViewAsh::BrowserNonClientFrameViewAsh( : BrowserNonClientFrameView(frame, browser_view), size_button_(NULL), close_button_(NULL), - immersive_button_(NULL), window_icon_(NULL), frame_painter_(new ash::FramePainter), size_button_minimizes_(false) { @@ -120,19 +119,6 @@ void BrowserNonClientFrameViewAsh::Init() { // Frame painter handles layout of these buttons. frame_painter_->Init(frame(), window_icon_, size_button_, close_button_, size_button_behavior); - - if (CommandLine::ForCurrentProcess()->HasSwitch(kAshImmersiveMode)) { - // Button to toggle immersive mode. - immersive_button_ = new views::ToggleImageButton(this); - immersive_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_IMMERSIVE)); - immersive_button_->SetTooltipText( - l10n_util::GetStringUTF16(IDS_TOOLTIP_IMMERSIVE)); - immersive_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, - views::ImageButton::ALIGN_BOTTOM); - AddChildView(immersive_button_); - frame_painter_->AddImmersiveButton(immersive_button_); - } } /////////////////////////////////////////////////////////////////////////////// @@ -211,12 +197,9 @@ void BrowserNonClientFrameViewAsh::ResetWindowControls() { browser_view()->immersive_mode_controller(); if (controller->enabled()) { bool revealed = controller->IsRevealed(); - immersive_button_->SetVisible(revealed); size_button_->SetVisible(revealed); close_button_->SetVisible(revealed); } else { - // Only show immersive button for maximized windows. - immersive_button_->SetVisible(frame()->IsMaximized()); size_button_->SetVisible(true); close_button_->SetVisible(true); } @@ -240,8 +223,8 @@ void BrowserNonClientFrameViewAsh::UpdateWindowTitle() { // views::View overrides: void BrowserNonClientFrameViewAsh::OnPaint(gfx::Canvas* canvas) { - if (frame()->IsFullscreen()) - return; // Nothing visible, don't paint. + if (!ShouldPaint()) + return; // The primary header image changes based on window activation state and // theme, so we look it up for each paint. frame_painter_->PaintHeader( @@ -320,6 +303,8 @@ void BrowserNonClientFrameViewAsh::ButtonPressed(views::Button* sender, ResetWindowControls(); if (size_button_minimizes_) frame()->Minimize(); + else if (frame()->IsFullscreen()) // Can be clicked in immersive mode. + frame()->SetFullscreen(false); else if (frame()->IsMaximized()) frame()->Restore(); else @@ -327,14 +312,6 @@ void BrowserNonClientFrameViewAsh::ButtonPressed(views::Button* sender, // |this| may be deleted - some windows delete their frames on maximize. } else if (sender == close_button_) { frame()->Close(); - } else if (CommandLine::ForCurrentProcess()->HasSwitch(kAshImmersiveMode) && - sender == immersive_button_) { - // Toggle immersive mode. - ImmersiveModeController* controller = - browser_view()->immersive_mode_controller(); - bool enable = !controller->enabled(); - controller->SetEnabled(enable); - immersive_button_->SetToggled(enable); } if (event.IsShiftDown()) @@ -383,13 +360,14 @@ int BrowserNonClientFrameViewAsh::NonClientTopBorderHeight( bool BrowserNonClientFrameViewAsh::UseShortHeader() const { // Restored browser -> tall header // Maximized browser -> short header + // Fullscreen browser (header shows with immersive reveal) -> short header // Popup&App window -> tall header // Panel -> short header // Dialogs use short header and are handled via CustomFrameViewAsh. Browser* browser = browser_view()->browser(); switch (browser->type()) { case Browser::TYPE_TABBED: - return frame()->IsMaximized(); + return frame()->IsMaximized() || frame()->IsFullscreen(); case Browser::TYPE_POPUP: return false; case Browser::TYPE_PANEL: @@ -417,6 +395,12 @@ void BrowserNonClientFrameViewAsh::LayoutAvatar() { avatar_button()->SetBoundsRect(avatar_bounds); } +bool BrowserNonClientFrameViewAsh::ShouldPaint() const { + // Immersive mode windows are fullscreen, but need to paint during a reveal. + return !frame()->IsFullscreen() || + browser_view()->immersive_mode_controller()->IsRevealed(); +} + void BrowserNonClientFrameViewAsh::PaintToolbarBackground(gfx::Canvas* canvas) { gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds()); if (toolbar_bounds.IsEmpty()) diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 445dab9..4fa5871 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h @@ -79,7 +79,10 @@ class BrowserNonClientFrameViewAsh // Layout the incognito icon. void LayoutAvatar(); - void PaintTitleBar(gfx::Canvas* canvas); + // Returns true if there is anything to paint. Some fullscreen windows do not + // need their frames painted. + bool ShouldPaint() const; + void PaintToolbarBackground(gfx::Canvas* canvas); // Windows without a toolbar need to draw their own line under the header, @@ -96,9 +99,6 @@ class BrowserNonClientFrameViewAsh views::ImageButton* size_button_; views::ImageButton* close_button_; - // Optional button to toggle immersive UI. May be NULL. - views::ToggleImageButton* immersive_button_; - // For popups, the window icon. TabIconView* window_icon_; diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index 3248fbf..f5dc9c0 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc @@ -96,34 +96,42 @@ IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveMode) { static_cast<BrowserNonClientFrameViewAsh*>( widget->non_client_view()->frame_view()); - // Normal window does not have immersive mode button. - EXPECT_FALSE(frame_view->immersive_button_->visible()); + // Immersive mode starts disabled. + EXPECT_FALSE(browser_view->immersive_mode_controller()->enabled()); - // Maximized window shows immersive mode button. - widget->Maximize(); - EXPECT_TRUE(frame_view->immersive_button_->visible()); + // Frame paints by default. + EXPECT_TRUE(frame_view->ShouldPaint()); + + // Going fullscreen enables immersive mode. + browser_view->EnterFullscreen(GURL(), FEB_TYPE_NONE); + EXPECT_TRUE(browser_view->immersive_mode_controller()->enabled()); - // Entering immersive mode hides the caption buttons. - browser_view->immersive_mode_controller()->SetEnabled(true); - EXPECT_FALSE(frame_view->immersive_button_->visible()); + // Entering immersive mode hides the caption buttons and the frame. EXPECT_FALSE(frame_view->size_button_->visible()); EXPECT_FALSE(frame_view->close_button_->visible()); + EXPECT_FALSE(frame_view->ShouldPaint()); - // An immersive reveal shows the buttons. + // Frame abuts top of window. + EXPECT_EQ(0, frame_view->NonClientTopBorderHeight(false)); + + // An immersive reveal shows the buttons and the top of the frame. browser_view->immersive_mode_controller()->StartRevealForTest(); - EXPECT_TRUE(frame_view->immersive_button_->visible()); EXPECT_TRUE(frame_view->size_button_->visible()); EXPECT_TRUE(frame_view->close_button_->visible()); + EXPECT_TRUE(frame_view->ShouldPaint()); // Ending reveal hides them again. browser_view->immersive_mode_controller()->CancelReveal(); - EXPECT_FALSE(frame_view->immersive_button_->visible()); EXPECT_FALSE(frame_view->size_button_->visible()); EXPECT_FALSE(frame_view->close_button_->visible()); + EXPECT_FALSE(frame_view->ShouldPaint()); + + // Exiting fullscreen exits immersive mode. + browser_view->ExitFullscreen(); + EXPECT_FALSE(browser_view->immersive_mode_controller()->enabled()); - // Exiting immersive mode makes them visible again. - browser_view->immersive_mode_controller()->SetEnabled(false); - EXPECT_TRUE(frame_view->immersive_button_->visible()); + // Exiting immersive mode makes controls and frame visible again. EXPECT_TRUE(frame_view->size_button_->visible()); EXPECT_TRUE(frame_view->close_button_->visible()); + EXPECT_TRUE(frame_view->ShouldPaint()); } diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index f00cff7..56ed5a4 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -122,6 +122,7 @@ #include "ui/views/window/dialog_delegate.h" #if defined(USE_ASH) +#include "ash/ash_switches.h" #include "ash/launcher/launcher.h" #include "ash/launcher/launcher_model.h" #include "ash/shell.h" @@ -194,6 +195,19 @@ bool ShouldSaveOrRestoreWindowPos() { return true; } +// Returns whether immersive mode should replace fullscreen, which should only +// occur for "browser-fullscreen" and not for "tab-fullscreen" (which has a URL +// for the tab entering fullscreen). +bool UseImmersiveFullscreen(const GURL& url) { +#if defined(USE_ASH) + bool is_browser_fullscreen = url.is_empty(); + return is_browser_fullscreen && + CommandLine::ForCurrentProcess()->HasSwitch( + ash::switches::kAshImmersiveMode); +#endif + return false; +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -759,7 +773,10 @@ void BrowserView::ExitFullscreen() { void BrowserView::UpdateFullscreenExitBubbleContent( const GURL& url, FullscreenExitBubbleType bubble_type) { - if (bubble_type == FEB_TYPE_NONE) { + // Immersive mode has no exit bubble because it has a visible strip at the + // top that gives the user a hover target. + // TODO(jamescook): Figure out what to do with mouse-lock. + if (bubble_type == FEB_TYPE_NONE || UseImmersiveFullscreen(url)) { fullscreen_bubble_.reset(); } else if (fullscreen_bubble_.get()) { fullscreen_bubble_->UpdateContent(url, bubble_type); @@ -769,6 +786,14 @@ void BrowserView::UpdateFullscreenExitBubbleContent( } } +bool BrowserView::ShouldHideUIForFullscreen() const { +#if defined(USE_ASH) + // Immersive mode needs UI for the slide-down top panel. + return IsFullscreen() && !immersive_mode_controller_->enabled(); +#endif + return IsFullscreen(); +} + bool BrowserView::IsFullscreen() const { return frame_->IsFullscreen(); } @@ -2272,10 +2297,16 @@ void BrowserView::ProcessFullscreen(bool fullscreen, frame_->SetFullscreen(fullscreen); } + // Enable immersive before the browser refreshes its list of enabled commands. + if (UseImmersiveFullscreen(url)) + immersive_mode_controller_->SetEnabled(fullscreen); + browser_->WindowFullscreenStateChanged(); if (fullscreen) { - if (!chrome::IsRunningInAppMode() && type != FOR_METRO) { + if (!chrome::IsRunningInAppMode() && + type != FOR_METRO && + !UseImmersiveFullscreen(url)) { fullscreen_bubble_.reset(new FullscreenExitBubbleViews( GetWidget(), browser_.get(), url, bubble_type)); } diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index d6c3f20..dedbba1 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -287,6 +287,7 @@ class BrowserView : public BrowserWindow, virtual void UpdateFullscreenExitBubbleContent( const GURL& url, FullscreenExitBubbleType bubble_type) OVERRIDE; + virtual bool ShouldHideUIForFullscreen() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; #if defined(OS_WIN) virtual void SetMetroSnapMode(bool enable) OVERRIDE; diff --git a/chrome/browser/ui/views/immersive_mode_controller.cc b/chrome/browser/ui/views/immersive_mode_controller.cc index a532c55..6caffd0 100644 --- a/chrome/browser/ui/views/immersive_mode_controller.cc +++ b/chrome/browser/ui/views/immersive_mode_controller.cc @@ -245,8 +245,8 @@ class ImmersiveModeController::WindowObserver : public aura::WindowObserver { intptr_t old) OVERRIDE { using aura::client::kShowStateKey; if (key == kShowStateKey) { - // Disable immersive mode when leaving the maximized state. - if (window->GetProperty(kShowStateKey) != ui::SHOW_STATE_MAXIMIZED) + // Disable immersive mode when leaving the fullscreen state. + if (window->GetProperty(kShowStateKey) != ui::SHOW_STATE_FULLSCREEN) controller_->SetEnabled(false); return; } diff --git a/chrome/browser/ui/views/immersive_mode_controller_browsertest.cc b/chrome/browser/ui/views/immersive_mode_controller_browsertest.cc index 1de703d..8a3b232 100644 --- a/chrome/browser/ui/views/immersive_mode_controller_browsertest.cc +++ b/chrome/browser/ui/views/immersive_mode_controller_browsertest.cc @@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/immersive_mode_controller.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h" @@ -31,8 +33,9 @@ gfx::Rect GetRectInWidget(views::View* view) { typedef InProcessBrowserTest ImmersiveModeControllerTest; -// TODO(linux_aura) http://crbug.com/163931 -#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) +// TODO(jamescook): If immersive mode becomes popular on Ash, consider porting +// it to other Aura platforms (win_aura, linux_aura). http://crbug.com/163931 +#if !defined(USE_ASH) #define MAYBE_ImmersiveMode DISABLED_ImmersiveMode #else #define MAYBE_ImmersiveMode ImmersiveMode @@ -45,7 +48,6 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { ImmersiveModeController* controller = browser_view->immersive_mode_controller(); views::View* contents_view = browser_view->GetTabContentsContainerView(); - browser_view->GetWidget()->Maximize(); // Immersive mode is not on by default. EXPECT_FALSE(controller->enabled()); @@ -55,9 +57,16 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { EXPECT_TRUE(browser_view->IsTabStripVisible()); EXPECT_TRUE(browser_view->IsToolbarVisible()); + // Usual commands are enabled. + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); + // Turning immersive mode on sets the toolbar to immersive style and hides // the top-of-window views while leaving the tab strip visible. controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); EXPECT_TRUE(controller->enabled()); EXPECT_TRUE(controller->ShouldHideTopViews()); EXPECT_FALSE(controller->IsRevealed()); @@ -68,6 +77,11 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { EXPECT_EQ(GetRectInWidget(browser_view).y() + Tab::GetImmersiveHeight(), GetRectInWidget(contents_view).y()); + // Commands are still enabled (usually fullscreen disables these). + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPEN_CURRENT_URL)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_ABOUT)); + EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_FULLSCREEN)); + // Trigger a reveal keeps us in immersive mode, but top-of-window views // become visible. controller->StartRevealForTest(); @@ -95,6 +109,8 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { // Disabling immersive mode puts us back to the beginning. controller->SetEnabled(false); + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser_view->IsFullscreen()); EXPECT_FALSE(controller->enabled()); EXPECT_FALSE(controller->ShouldHideTopViews()); EXPECT_FALSE(controller->IsRevealed()); @@ -105,8 +121,12 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { // Disabling immersive mode while we are revealed should take us back to // the beginning. controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); controller->StartRevealForTest(); controller->SetEnabled(false); + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser_view->IsFullscreen()); EXPECT_FALSE(controller->enabled()); EXPECT_FALSE(controller->ShouldHideTopViews()); EXPECT_FALSE(controller->IsRevealed()); @@ -116,9 +136,10 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { // When hiding the tab indicators, content is at the top of the browser view // both before and during reveal. - controller->SetEnabled(false); controller->SetHideTabIndicatorsForTest(true); controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); EXPECT_FALSE(browser_view->IsTabStripVisible()); EXPECT_EQ(GetRectInWidget(browser_view).y(), GetRectInWidget(contents_view).y()); @@ -130,10 +151,14 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { EXPECT_EQ(GetRectInWidget(browser_view).y(), GetRectInWidget(contents_view).y()); controller->SetEnabled(false); + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser_view->IsFullscreen()); controller->SetHideTabIndicatorsForTest(false); // Reveal ends when the mouse moves out of the reveal view. controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); controller->StartRevealForTest(); controller->OnRevealViewLostMouseForTest(); EXPECT_FALSE(controller->IsRevealed()); @@ -168,6 +193,7 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { // Restoring the window exits immersive mode. controller->SetEnabled(true); browser_view->GetWidget()->Restore(); + ASSERT_FALSE(browser_view->IsFullscreen()); EXPECT_FALSE(controller->enabled()); EXPECT_FALSE(controller->ShouldHideTopViews()); EXPECT_FALSE(controller->IsRevealed()); @@ -177,8 +203,10 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, MAYBE_ImmersiveMode) { #endif // defined(USE_AURA) && !defined(OS_WIN) // Don't crash if we exit the test during a reveal. - browser_view->GetWidget()->Maximize(); controller->SetEnabled(true); + if (!browser_view->IsFullscreen()) + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); controller->StartRevealForTest(); } @@ -195,7 +223,6 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, ImmersiveAsh) { BrowserView* browser_view = static_cast<BrowserView*>(browser()->window()); ImmersiveModeController* immersive_controller = browser_view->immersive_mode_controller(); - browser_view->GetWidget()->Maximize(); // Shelf is visible when the test starts. ash::internal::ShelfLayoutManager* shelf = @@ -204,10 +231,14 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, ImmersiveAsh) { // Turning immersive mode on sets the shelf to auto-hide. immersive_controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); // Disabling immersive mode puts it back. immersive_controller->SetEnabled(false); + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser_view->IsFullscreen()); EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state()); // The user could toggle the launcher behavior. @@ -216,13 +247,18 @@ IN_PROC_BROWSER_TEST_F(ImmersiveModeControllerTest, ImmersiveAsh) { // Enabling immersive mode keeps auto-hide. immersive_controller->SetEnabled(true); + chrome::ToggleFullscreenMode(browser()); + ASSERT_TRUE(browser_view->IsFullscreen()); EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); // Disabling immersive mode maintains the user's auto-hide selection. immersive_controller->SetEnabled(false); + chrome::ToggleFullscreenMode(browser()); + ASSERT_FALSE(browser_view->IsFullscreen()); EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state()); // Setting the window property directly toggles immersive mode. + // TODO(jamescook): Is this functionality still needed? aura::Window* window = browser_view->GetWidget()->GetNativeWindow(); window->SetProperty(ash::internal::kImmersiveModeKey, true); EXPECT_TRUE(immersive_controller->enabled()); diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 9b70dec..ac77cd4 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc @@ -313,7 +313,7 @@ class NewTabButton : public views::ImageButton { ui::ScaleFactor scale_factor) const; gfx::ImageSkia GetImageForState(views::CustomButton::ButtonState state, ui::ScaleFactor scale_factor) const; - gfx::ImageSkia GetImage(ui::ScaleFactor scale_factor) const; + gfx::ImageSkia GetImageForScale(ui::ScaleFactor scale_factor) const; // Tab strip that contains this button. TabStrip* tab_strip_; @@ -374,7 +374,7 @@ void NewTabButton::OnMouseReleased(const ui::MouseEvent& event) { #endif void NewTabButton::OnPaint(gfx::Canvas* canvas) { - gfx::ImageSkia image = GetImage(canvas->scale_factor()); + gfx::ImageSkia image = GetImageForScale(canvas->scale_factor()); canvas->DrawImageInt(image, 0, height() - image.height()); } @@ -497,7 +497,8 @@ gfx::ImageSkia NewTabButton::GetImageForState( return gfx::ImageSkia(canvas.ExtractImageRep()); } -gfx::ImageSkia NewTabButton::GetImage(ui::ScaleFactor scale_factor) const { +gfx::ImageSkia NewTabButton::GetImageForScale( + ui::ScaleFactor scale_factor) const { if (!hover_animation_->is_animating()) return GetImageForState(state(), scale_factor); return gfx::ImageSkiaOperations::CreateBlendedImage( diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc index a5a95ec..22a208c 100644 --- a/chrome/test/base/test_browser_window.cc +++ b/chrome/test/base/test_browser_window.cc @@ -50,6 +50,10 @@ bool TestBrowserWindow::IsMinimized() const { return false; } +bool TestBrowserWindow::ShouldHideUIForFullscreen() const { + return false; +} + bool TestBrowserWindow::IsFullscreen() const { return false; } diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index c7dca87..a440dd9 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -59,6 +59,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void UpdateFullscreenExitBubbleContent( const GURL& url, FullscreenExitBubbleType bubble_type) OVERRIDE {} + virtual bool ShouldHideUIForFullscreen() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; #if defined(OS_WIN) virtual void SetMetroSnapMode(bool enable) OVERRIDE {} diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc index a93a1dc..c93e559 100644 --- a/ui/views/controls/button/image_button.cc +++ b/ui/views/controls/button/image_button.cc @@ -32,6 +32,10 @@ ImageButton::ImageButton(ButtonListener* listener) ImageButton::~ImageButton() { } +const gfx::ImageSkia& ImageButton::GetImage(ButtonState state) const { + return images_[state]; +} + void ImageButton::SetImage(ButtonState state, const gfx::ImageSkia* image) { images_[state] = image ? *image : gfx::ImageSkia(); PreferredSizeChanged(); @@ -175,6 +179,12 @@ void ToggleImageButton::SetToggledTooltipText(const string16& tooltip) { //////////////////////////////////////////////////////////////////////////////// // ToggleImageButton, ImageButton overrides: +const gfx::ImageSkia& ToggleImageButton::GetImage(ButtonState state) const { + if (toggled_) + return alternate_images_[state]; + return images_[state]; +} + void ToggleImageButton::SetImage(ButtonState state, const gfx::ImageSkia* image) { if (toggled_) { diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h index 180ead0..e61975f 100644 --- a/ui/views/controls/button/image_button.h +++ b/ui/views/controls/button/image_button.h @@ -35,6 +35,9 @@ class VIEWS_EXPORT ImageButton : public CustomButton { explicit ImageButton(ButtonListener* listener); virtual ~ImageButton(); + // Returns the image for a given |state|. + virtual const gfx::ImageSkia& GetImage(ButtonState state) const; + // Set the image the button should use for the provided state. virtual void SetImage(ButtonState state, const gfx::ImageSkia* image); @@ -116,6 +119,7 @@ class VIEWS_EXPORT ToggleImageButton : public ImageButton { void SetToggledTooltipText(const string16& tooltip); // Overridden from ImageButton: + virtual const gfx::ImageSkia& GetImage(ButtonState state) const OVERRIDE; virtual void SetImage(ButtonState state, const gfx::ImageSkia* image) OVERRIDE; diff --git a/ui/views/controls/button/image_button_unittest.cc b/ui/views/controls/button/image_button_unittest.cc index 2bdc446..e4331b5 100644 --- a/ui/views/controls/button/image_button_unittest.cc +++ b/ui/views/controls/button/image_button_unittest.cc @@ -80,6 +80,32 @@ TEST_F(ImageButtonTest, Basics) { EXPECT_TRUE(button.overlay_image_.isNull()); } +TEST_F(ImageButtonTest, SetAndGetImage) { + ImageButton button(NULL); + + // Images start as null. + EXPECT_TRUE(button.GetImage(Button::STATE_NORMAL).isNull()); + EXPECT_TRUE(button.GetImage(Button::STATE_HOVERED).isNull()); + EXPECT_TRUE(button.GetImage(Button::STATE_PRESSED).isNull()); + EXPECT_TRUE(button.GetImage(Button::STATE_DISABLED).isNull()); + + // Setting images works as expected. + gfx::ImageSkia image1 = CreateTestImage(10, 11); + gfx::ImageSkia image2 = CreateTestImage(20, 21); + button.SetImage(Button::STATE_NORMAL, &image1); + button.SetImage(Button::STATE_HOVERED, &image2); + EXPECT_TRUE( + button.GetImage(Button::STATE_NORMAL).BackedBySameObjectAs(image1)); + EXPECT_TRUE( + button.GetImage(Button::STATE_HOVERED).BackedBySameObjectAs(image2)); + EXPECT_TRUE(button.GetImage(Button::STATE_PRESSED).isNull()); + EXPECT_TRUE(button.GetImage(Button::STATE_DISABLED).isNull()); + + // ImageButton supports NULL image pointers. + button.SetImage(Button::STATE_NORMAL, NULL); + EXPECT_TRUE(button.GetImage(Button::STATE_NORMAL).isNull()); +} + TEST_F(ImageButtonTest, ImagePositionWithBorder) { ImageButton button(NULL); gfx::ImageSkia image = CreateTestImage(20, 30); |