summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/wm/frame_painter.cc51
-rw-r--r--ash/wm/frame_painter.h5
-rw-r--r--ash/wm/frame_painter_unittest.cc114
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate.cc17
-rw-r--r--chrome/browser/ui/browser.cc9
-rw-r--r--chrome/browser/ui/browser_command_controller.cc23
-rw-r--r--chrome/browser/ui/browser_command_controller.h2
-rw-r--r--chrome/browser/ui/browser_command_controller_unittest.cc140
-rw-r--r--chrome/browser/ui/browser_window.h4
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/ui/cocoa/browser_window_cocoa.mm5
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_state_unittest.cc5
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc4
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc40
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h8
-rw-r--r--chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc36
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc35
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h1
-rw-r--r--chrome/browser/ui/views/immersive_mode_controller.cc4
-rw-r--r--chrome/browser/ui/views/immersive_mode_controller_browsertest.cc48
-rw-r--r--chrome/browser/ui/views/tabs/tab_strip.cc7
-rw-r--r--chrome/test/base/test_browser_window.cc4
-rw-r--r--chrome/test/base/test_browser_window.h1
-rw-r--r--ui/views/controls/button/image_button.cc10
-rw-r--r--ui/views/controls/button/image_button.h4
-rw-r--r--ui/views/controls/button/image_button_unittest.cc26
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);