diff options
author | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-09 06:10:57 +0000 |
---|---|---|
committer | stevenjb@chromium.org <stevenjb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-09 06:10:57 +0000 |
commit | 68eeede20e63fbb9a8756ed73e482b87dde57c72 (patch) | |
tree | 26d1bd889cbfd7b32131d585a97dcb9b447b8733 | |
parent | c2ff9b4ec2549c5b3b36c11fe2fca7b5495adf9a (diff) | |
download | chromium_src-68eeede20e63fbb9a8756ed73e482b87dde57c72.zip chromium_src-68eeede20e63fbb9a8756ed73e482b87dde57c72.tar.gz chromium_src-68eeede20e63fbb9a8756ed73e482b87dde57c72.tar.bz2 |
Save and restore State for ShellWindows, including panels
This replaces ShellWindow::CreateParams::State with
ui::WindowShowState for simplicty and consistency with
Browser session restore.
BUG=233556
TBR=flackr@chromium.org, skuhne@chromium.org, sky@chromium.org
Original CL: https://codereview.chromium.org/14031021/
+ disabled flakey browser tests on linux
Review URL: https://chromiumcodereview.appspot.com/14663010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199145 0039d316-1c4b-4281-b951-d872f2087c98
38 files changed, 347 insertions, 123 deletions
diff --git a/ash/wm/base_layout_manager.cc b/ash/wm/base_layout_manager.cc index d5bb54f..89e99d9 100644 --- a/ash/wm/base_layout_manager.cc +++ b/ash/wm/base_layout_manager.cc @@ -89,8 +89,8 @@ void BaseLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, if (visible && wm::IsWindowMinimized(child)) { // Attempting to show a minimized window. Unminimize it. child->SetProperty(aura::client::kShowStateKey, - child->GetProperty(internal::kRestoreShowStateKey)); - child->ClearProperty(internal::kRestoreShowStateKey); + child->GetProperty(aura::client::kRestoreShowStateKey)); + child->ClearProperty(aura::client::kRestoreShowStateKey); } } @@ -171,7 +171,7 @@ void BaseLayoutManager::ShowStateChanged(aura::Window* window, ui::WindowShowState last_show_state) { if (wm::IsWindowMinimized(window)) { // Save the previous show state so that we can correctly restore it. - window->SetProperty(internal::kRestoreShowStateKey, last_show_state); + window->SetProperty(aura::client::kRestoreShowStateKey, last_show_state); views::corewm::SetWindowVisibilityAnimationType( window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); diff --git a/ash/wm/window_properties.cc b/ash/wm/window_properties.cc index 21f205a..64d55a7 100644 --- a/ash/wm/window_properties.cc +++ b/ash/wm/window_properties.cc @@ -26,8 +26,6 @@ DEFINE_WINDOW_PROPERTY_KEY(bool, kFullscreenUsesMinimalChromeKey, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kIgnoreSoloWindowFramePainterPolicy, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kIgnoredByShelfKey, false); DEFINE_WINDOW_PROPERTY_KEY(bool, kPanelAttachedKey, true); -DEFINE_WINDOW_PROPERTY_KEY( - ui::WindowShowState, kRestoreShowStateKey, ui::SHOW_STATE_DEFAULT); DEFINE_WINDOW_PROPERTY_KEY(RootWindowController*, kRootWindowControllerKey, NULL); DEFINE_WINDOW_PROPERTY_KEY(bool, kSoloWindowHeaderKey, false); diff --git a/ash/wm/window_properties.h b/ash/wm/window_properties.h index 7847b62..ae30435 100644 --- a/ash/wm/window_properties.h +++ b/ash/wm/window_properties.h @@ -57,10 +57,6 @@ extern const aura::WindowProperty<bool>* const // True if this window is an attached panel. ASH_EXPORT extern const aura::WindowProperty<bool>* const kPanelAttachedKey; -// Used to remember the show state before the window was minimized. -extern const aura::WindowProperty<ui::WindowShowState>* const - kRestoreShowStateKey; - extern const aura::WindowProperty<RootWindowController*>* const kRootWindowControllerKey; diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc index 65ed116..e4e6c84 100644 --- a/ash/wm/workspace/workspace_layout_manager.cc +++ b/ash/wm/workspace/workspace_layout_manager.cc @@ -126,8 +126,8 @@ void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child, if (visible && wm::IsWindowMinimized(child)) { // Attempting to show a minimized window. Unminimize it. child->SetProperty(aura::client::kShowStateKey, - child->GetProperty(internal::kRestoreShowStateKey)); - child->ClearProperty(internal::kRestoreShowStateKey); + child->GetProperty(aura::client::kRestoreShowStateKey)); + child->ClearProperty(aura::client::kRestoreShowStateKey); } workspace_manager()->OnWorkspaceChildWindowVisibilityChanged(workspace_, child); @@ -257,7 +257,7 @@ void WorkspaceLayoutManager::ShowStateChanged( if (wm::IsWindowMinimized(window)) { DCHECK(!cloned_layer); // Save the previous show state so that we can correctly restore it. - window->SetProperty(internal::kRestoreShowStateKey, last_show_state); + window->SetProperty(aura::client::kRestoreShowStateKey, last_show_state); views::corewm::SetWindowVisibilityAnimationType( window, WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE); workspace_manager()->OnWorkspaceWindowShowStateChanged( diff --git a/ash/wm/workspace/workspace_manager.cc b/ash/wm/workspace/workspace_manager.cc index 69413fe..b4d4226 100644 --- a/ash/wm/workspace/workspace_manager.cc +++ b/ash/wm/workspace/workspace_manager.cc @@ -160,7 +160,7 @@ bool WorkspaceManager::IsMaximizedState(ui::WindowShowState state) { // static bool WorkspaceManager::WillRestoreMaximized(Window* window) { return wm::IsWindowMinimized(window) && - IsMaximizedState(window->GetProperty(internal::kRestoreShowStateKey)); + IsMaximizedState(window->GetProperty(aura::client::kRestoreShowStateKey)); } WorkspaceWindowState WorkspaceManager::GetWindowState() const { diff --git a/chrome/browser/extensions/api/app_window/app_window_api.cc b/chrome/browser/extensions/api/app_window/app_window_api.cc index a421b95..2dccb33 100644 --- a/chrome/browser/extensions/api/app_window/app_window_api.cc +++ b/chrome/browser/extensions/api/app_window/app_window_api.cc @@ -22,6 +22,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/common/url_constants.h" #include "googleurl/src/gurl.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/rect.h" #if defined(USE_ASH) @@ -82,6 +83,20 @@ class DevToolsRestorer : public content::NotificationObserver { content::NotificationRegistrar registrar_; }; +void SetCreateResultFromShellWindow(ShellWindow* window, + base::DictionaryValue* result) { + result->SetBoolean("fullscreen", window->GetBaseWindow()->IsFullscreen()); + result->SetBoolean("minimized", window->GetBaseWindow()->IsMinimized()); + result->SetBoolean("maximized", window->GetBaseWindow()->IsMaximized()); + DictionaryValue* boundsValue = new DictionaryValue(); + gfx::Rect bounds = window->GetClientBounds(); + boundsValue->SetInteger("left", bounds.x()); + boundsValue->SetInteger("top", bounds.y()); + boundsValue->SetInteger("width", bounds.width()); + boundsValue->SetInteger("height", bounds.height()); + result->Set("bounds", boundsValue); +} + } // namespace void AppWindowCreateFunction::SendDelayedResponse() { @@ -140,6 +155,7 @@ bool AppWindowCreateFunction::RunImpl() { window->GetBaseWindow()->Show(); base::DictionaryValue* result = new base::DictionaryValue; result->Set("viewId", base::Value::CreateIntegerValue(view_id)); + SetCreateResultFromShellWindow(window, result); result->SetBoolean("existingWindow", true); result->SetBoolean("injectTitlebar", false); SetResult(result); @@ -230,13 +246,13 @@ bool AppWindowCreateFunction::RunImpl() { case extensions::api::app_window::STATE_NORMAL: break; case extensions::api::app_window::STATE_FULLSCREEN: - create_params.state = ShellWindow::CreateParams::STATE_FULLSCREEN; + create_params.state = ui::SHOW_STATE_FULLSCREEN; break; case extensions::api::app_window::STATE_MAXIMIZED: - create_params.state = ShellWindow::CreateParams::STATE_MAXIMIZED; + create_params.state = ui::SHOW_STATE_MAXIMIZED; break; case extensions::api::app_window::STATE_MINIMIZED: - create_params.state = ShellWindow::CreateParams::STATE_MINIMIZED; + create_params.state = ui::SHOW_STATE_MINIMIZED; break; } } else { @@ -266,7 +282,7 @@ bool AppWindowCreateFunction::RunImpl() { #endif if (force_maximize) - create_params.state = ShellWindow::CreateParams::STATE_MAXIMIZED; + create_params.state = ui::SHOW_STATE_MAXIMIZED; ShellWindow* shell_window = ShellWindow::Create(profile(), GetExtension(), url, create_params); @@ -285,13 +301,7 @@ bool AppWindowCreateFunction::RunImpl() { result->Set("injectTitlebar", base::Value::CreateBooleanValue(inject_html_titlebar)); result->Set("id", base::Value::CreateStringValue(shell_window->window_key())); - DictionaryValue* boundsValue = new DictionaryValue(); - gfx::Rect bounds = shell_window->GetClientBounds(); - boundsValue->SetInteger("left", bounds.x()); - boundsValue->SetInteger("top", bounds.y()); - boundsValue->SetInteger("width", bounds.width()); - boundsValue->SetInteger("height", bounds.height()); - result->Set("bounds", boundsValue); + SetCreateResultFromShellWindow(shell_window, result); SetResult(result); if (ShellWindowRegistry::Get(profile())->HadDevToolsAttached(created_view)) { diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc index 642f948..3e9551a 100644 --- a/chrome/browser/extensions/platform_app_browsertest.cc +++ b/chrome/browser/extensions/platform_app_browsertest.cc @@ -632,6 +632,18 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ASSERT_TRUE(RunPlatformAppTest("platform_apps/geometry")); } +// This appears to be unreliable on linux. +// TODO(stevenjb): Investigate and enable +#if defined(OS_LINUX) && !defined(USE_ASH) +#define MAYBE_ShellWindowRestoreState DISABLED_ShellWindowRestoreState +#else +#define MAYBE_ShellWindowRestoreState ShellWindowRestoreState +#endif +IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, + MAYBE_ShellWindowRestoreState) { + ASSERT_TRUE(RunPlatformAppTest("platform_apps/restore_state")); +} + namespace { class PlatformAppDevToolsBrowserTest : public PlatformAppBrowserTest { diff --git a/chrome/browser/extensions/shell_window_geometry_cache.cc b/chrome/browser/extensions/shell_window_geometry_cache.cc index f08f085..7d01f9c 100644 --- a/chrome/browser/extensions/shell_window_geometry_cache.cc +++ b/chrome/browser/extensions/shell_window_geometry_cache.cc @@ -40,18 +40,21 @@ ShellWindowGeometryCache::~ShellWindowGeometryCache() { void ShellWindowGeometryCache::SaveGeometry( const std::string& extension_id, const std::string& window_id, - const gfx::Rect& bounds) { + const gfx::Rect& bounds, + ui::WindowShowState window_state) { ExtensionData& extension_data = cache_[extension_id]; // If we don't have any unsynced changes and this is a duplicate of what's // already in the cache, just ignore it. if (extension_data[window_id].bounds == bounds && + extension_data[window_id].window_state == window_state && !ContainsKey(unsynced_extensions_, extension_id)) return; base::Time now = base::Time::Now(); extension_data[window_id].bounds = bounds; + extension_data[window_id].window_state = window_state; extension_data[window_id].last_change = now; if (extension_data.size() > kMaxCachedWindows) { @@ -99,6 +102,7 @@ void ShellWindowGeometryCache::SyncToStorage() { value->SetInteger("y", bounds.y()); value->SetInteger("w", bounds.width()); value->SetInteger("h", bounds.height()); + value->SetInteger("state", it->second.window_state); value->SetString( "ts", base::Int64ToString(it->second.last_change.ToInternalValue())); dict->SetWithoutPathExpansion(it->first, value); @@ -110,7 +114,8 @@ void ShellWindowGeometryCache::SyncToStorage() { bool ShellWindowGeometryCache::GetGeometry( const std::string& extension_id, const std::string& window_id, - gfx::Rect* bounds) const { + gfx::Rect* bounds, + ui::WindowShowState* window_state) const { std::map<std::string, ExtensionData>::const_iterator extension_data_it = cache_.find(extension_id); @@ -125,7 +130,10 @@ bool ShellWindowGeometryCache::GetGeometry( if (window_data == extension_data_it->second.end()) return false; - *bounds = window_data->second.bounds; + if (bounds) + *bounds = window_data->second.bounds; + if (window_state) + *window_state = window_data->second.window_state; return true; } @@ -171,8 +179,7 @@ void ShellWindowGeometryCache::OnExtensionLoaded( // overwrite that information since it is probably the result of an // application starting up very quickly. const std::string& window_id = it.key(); - ExtensionData::iterator cached_window = - extension_data.find(window_id); + ExtensionData::iterator cached_window = extension_data.find(window_id); if (cached_window == extension_data.end()) { const base::DictionaryValue* stored_window; if (it.value().GetAsDictionary(&stored_window)) { @@ -187,6 +194,10 @@ void ShellWindowGeometryCache::OnExtensionLoaded( window_data.bounds.set_width(i); if (stored_window->GetInteger("h", &i)) window_data.bounds.set_height(i); + if (stored_window->GetInteger("state", &i)) { + window_data.window_state = + static_cast<ui::WindowShowState>(i); + } std::string ts_as_string; if (stored_window->GetString("ts", &ts_as_string)) { int64 ts; diff --git a/chrome/browser/extensions/shell_window_geometry_cache.h b/chrome/browser/extensions/shell_window_geometry_cache.h index 744077c..5648b0d 100644 --- a/chrome/browser/extensions/shell_window_geometry_cache.h +++ b/chrome/browser/extensions/shell_window_geometry_cache.h @@ -16,6 +16,7 @@ #include "base/values.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/rect.h" class Profile; @@ -36,13 +37,19 @@ class ShellWindowGeometryCache virtual ~ShellWindowGeometryCache(); + // Save the geometry and state associated with |extension_id| and |window_id|. void SaveGeometry(const std::string& extension_id, const std::string& window_id, - const gfx::Rect& bounds); + const gfx::Rect& bounds, + ui::WindowShowState state); + // Get any saved geometry and state associated with |extension_id| and + // |window_id|. If saved data exists, sets |bounds| and |state| if not NULL + // and returns true. bool GetGeometry(const std::string& extension_id, const std::string& window_id, - gfx::Rect* bounds) const; + gfx::Rect* bounds, + ui::WindowShowState* state) const; // Maximum number of windows we'll cache the geometry for per app. static const size_t kMaxCachedWindows = 100; @@ -58,7 +65,9 @@ class ShellWindowGeometryCache private: // Data stored for each window. struct WindowData { + WindowData() : window_state(ui::SHOW_STATE_DEFAULT) {} gfx::Rect bounds; + ui::WindowShowState window_state; base::Time last_change; }; diff --git a/chrome/browser/extensions/shell_window_geometry_cache_unittest.cc b/chrome/browser/extensions/shell_window_geometry_cache_unittest.cc index e349da8..efab64f 100644 --- a/chrome/browser/extensions/shell_window_geometry_cache_unittest.cc +++ b/chrome/browser/extensions/shell_window_geometry_cache_unittest.cc @@ -36,9 +36,11 @@ class ShellWindowGeometryCacheTest : public testing::Test { cache_->SetSyncDelayForTests(0); } - void AddGeometryAndLoadExtension(const std::string& extension_id, - const std::string& window_id, - const gfx::Rect& bounds); + void AddGeometryAndLoadExtension( + const std::string& extension_id, + const std::string& window_id, + const gfx::Rect& bounds, + ui::WindowShowState state); // Spins the UI threads' message loops to make sure any task // posted to sync the geometry to the value store gets a chance to run. @@ -56,14 +58,17 @@ class ShellWindowGeometryCacheTest : public testing::Test { }; void ShellWindowGeometryCacheTest::AddGeometryAndLoadExtension( - const std::string& extension_id, const std::string& window_id, - const gfx::Rect& bounds) { + const std::string& extension_id, + const std::string& window_id, + const gfx::Rect& bounds, + ui::WindowShowState state) { scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); base::DictionaryValue* value = new base::DictionaryValue; value->SetInteger("x", bounds.x()); value->SetInteger("y", bounds.y()); value->SetInteger("w", bounds.width()); value->SetInteger("h", bounds.height()); + value->SetInteger("state", state); dict->SetWithoutPathExpansion(window_id, value); prefs_->prefs()->SetGeometryCache(extension_id, dict.Pass()); LoadExtension(extension_id); @@ -88,8 +93,7 @@ void ShellWindowGeometryCacheTest::UnloadExtension( // Test getting geometry from an empty store. TEST_F(ShellWindowGeometryCacheTest, GetGeometryEmptyStore) { const std::string extension_id = prefs_->AddExtensionAndReturnId("ext1"); - gfx::Rect bounds; - ASSERT_FALSE(cache_->GetGeometry(extension_id, kWindowId, &bounds)); + ASSERT_FALSE(cache_->GetGeometry(extension_id, kWindowId, NULL, NULL)); } // Test getting geometry for an unknown extension. @@ -97,32 +101,37 @@ TEST_F(ShellWindowGeometryCacheTest, GetGeometryUnkownExtension) { const std::string extension_id1 = prefs_->AddExtensionAndReturnId("ext1"); const std::string extension_id2 = prefs_->AddExtensionAndReturnId("ext2"); AddGeometryAndLoadExtension(extension_id1, kWindowId, - gfx::Rect(4, 5, 31, 43)); - gfx::Rect bounds; - ASSERT_FALSE(cache_->GetGeometry(extension_id2, kWindowId, &bounds)); + gfx::Rect(4, 5, 31, 43), + ui::SHOW_STATE_DEFAULT); + ASSERT_FALSE(cache_->GetGeometry(extension_id2, kWindowId, NULL, NULL)); } // Test getting geometry for an unknown window in a known extension. TEST_F(ShellWindowGeometryCacheTest, GetGeometryUnkownWindow) { const std::string extension_id = prefs_->AddExtensionAndReturnId("ext1"); AddGeometryAndLoadExtension(extension_id, kWindowId, - gfx::Rect(4, 5, 31, 43)); - gfx::Rect bounds; - ASSERT_FALSE(cache_->GetGeometry(extension_id, kWindowId2, &bounds)); + gfx::Rect(4, 5, 31, 43), + ui::SHOW_STATE_DEFAULT); + ASSERT_FALSE(cache_->GetGeometry(extension_id, kWindowId2, NULL, NULL)); } -// Test that loading geometry from the store works correctly. -TEST_F(ShellWindowGeometryCacheTest, GetGeometryFromStore) { +// Test that loading geometry and state from the store works correctly. +TEST_F(ShellWindowGeometryCacheTest, GetGeometryAndStateFromStore) { const std::string extension_id = prefs_->AddExtensionAndReturnId("ext1"); gfx::Rect bounds(4, 5, 31, 43); - AddGeometryAndLoadExtension(extension_id, kWindowId, bounds); - gfx::Rect newBounds; - ASSERT_TRUE(cache_->GetGeometry(extension_id, kWindowId, &newBounds)); - ASSERT_EQ(bounds, newBounds); + ui::WindowShowState state = ui::SHOW_STATE_NORMAL; + AddGeometryAndLoadExtension(extension_id, kWindowId, bounds, state); + gfx::Rect new_bounds; + ui::WindowShowState new_state = ui::SHOW_STATE_DEFAULT; + ASSERT_TRUE(cache_->GetGeometry( + extension_id, kWindowId, &new_bounds, &new_state)); + ASSERT_EQ(bounds, new_bounds); + ASSERT_EQ(state, new_state); } -// Test saving geometry to the cache and state store, and reading it back. -TEST_F(ShellWindowGeometryCacheTest, SaveGeometryToStore) { +// Test saving geometry and state to the cache and state store, and reading +// it back. +TEST_F(ShellWindowGeometryCacheTest, SaveGeometryAndStateToStore) { const std::string extension_id = prefs_->AddExtensionAndReturnId("ext1"); const std::string window_id(kWindowId); @@ -131,12 +140,16 @@ TEST_F(ShellWindowGeometryCacheTest, SaveGeometryToStore) { // update geometry stored in cache gfx::Rect bounds(4, 5, 31, 43); - gfx::Rect newBounds; - cache_->SaveGeometry(extension_id, window_id, bounds); + ui::WindowShowState state = ui::SHOW_STATE_NORMAL; + cache_->SaveGeometry(extension_id, window_id, bounds, state); // make sure that immediately reading back geometry works - ASSERT_TRUE(cache_->GetGeometry(extension_id, window_id, &newBounds)); - ASSERT_EQ(bounds, newBounds); + gfx::Rect new_bounds; + ui::WindowShowState new_state = ui::SHOW_STATE_DEFAULT; + ASSERT_TRUE(cache_->GetGeometry( + extension_id, window_id, &new_bounds, &new_state)); + ASSERT_EQ(bounds, new_bounds); + ASSERT_EQ(state, new_state); // unload extension to force cache to save data to the state store UnloadExtension(extension_id); @@ -156,15 +169,20 @@ TEST_F(ShellWindowGeometryCacheTest, SaveGeometryToStore) { ASSERT_EQ(bounds.width(), v); ASSERT_TRUE(dict->GetInteger(window_id + ".h", &v)); ASSERT_EQ(bounds.height(), v); + ASSERT_TRUE(dict->GetInteger(window_id + ".state", &v)); + ASSERT_EQ(state, v); // check to make sure cache indeed doesn't know about this extension anymore - ASSERT_FALSE(cache_->GetGeometry(extension_id, window_id, &newBounds)); + ASSERT_FALSE(cache_->GetGeometry( + extension_id, window_id, &new_bounds, &new_state)); // reload extension LoadExtension(extension_id); // and make sure the geometry got reloaded properly too - ASSERT_TRUE(cache_->GetGeometry(extension_id, window_id, &newBounds)); - ASSERT_EQ(bounds, newBounds); + ASSERT_TRUE(cache_->GetGeometry( + extension_id, window_id, &new_bounds, &new_state)); + ASSERT_EQ(bounds, new_bounds); + ASSERT_EQ(state, new_state); } // Tests that we won't do writes to the state store for SaveGeometry calls @@ -185,20 +203,30 @@ TEST_F(ShellWindowGeometryCacheTest, NoDuplicateWrites) { // Write the first bounds - it should do > 0 writes. EXPECT_CALL(observer, OnPreferenceChanged(_)); - cache_->SaveGeometry(extension_id, kWindowId, bounds1); + cache_->SaveGeometry(extension_id, kWindowId, bounds1, + ui::SHOW_STATE_DEFAULT); WaitForSync(); Mock::VerifyAndClearExpectations(&observer); // Write a different bounds - it should also do > 0 writes. EXPECT_CALL(observer, OnPreferenceChanged(_)); - cache_->SaveGeometry(extension_id, kWindowId, bounds2); + cache_->SaveGeometry(extension_id, kWindowId, bounds2, + ui::SHOW_STATE_DEFAULT); WaitForSync(); Mock::VerifyAndClearExpectations(&observer); - // Write a bounds that's a duplicate of what we already have. This should - // not do any writes. + // Write a different state - it should also do > 0 writes. + EXPECT_CALL(observer, OnPreferenceChanged(_)); + cache_->SaveGeometry(extension_id, kWindowId, bounds2, + ui::SHOW_STATE_NORMAL); + WaitForSync(); + Mock::VerifyAndClearExpectations(&observer); + + // Write a bounds and state that's a duplicate of what we already have. + // This should not do any writes. EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); - cache_->SaveGeometry(extension_id, kWindowId, bounds2_duplicate); + cache_->SaveGeometry(extension_id, kWindowId, bounds2_duplicate, + ui::SHOW_STATE_NORMAL); WaitForSync(); Mock::VerifyAndClearExpectations(&observer); } @@ -212,15 +240,16 @@ TEST_F(ShellWindowGeometryCacheTest, MaxWindows) { gfx::Rect bounds(4, 5, 31, 43); for (size_t i = 0; i < ShellWindowGeometryCache::kMaxCachedWindows + 1; ++i) { std::string window_id = "window_" + base::IntToString(i); - cache_->SaveGeometry(extension_id, window_id, bounds); + cache_->SaveGeometry(extension_id, window_id, bounds, + ui::SHOW_STATE_DEFAULT); } // The first added window should no longer have cached geometry. - EXPECT_FALSE(cache_->GetGeometry(extension_id, "window_0", &bounds)); + EXPECT_FALSE(cache_->GetGeometry(extension_id, "window_0", NULL, NULL)); // All other windows should still exist. for (size_t i = 1; i < ShellWindowGeometryCache::kMaxCachedWindows + 1; ++i) { std::string window_id = "window_" + base::IntToString(i); - EXPECT_TRUE(cache_->GetGeometry(extension_id, window_id, &bounds)); + EXPECT_TRUE(cache_->GetGeometry(extension_id, window_id, NULL, NULL)); } } diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 85af48e..0cace94 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc @@ -140,6 +140,7 @@ ui::WindowShowState AdjustShowState(ui::WindowShowState state) { case ui::SHOW_STATE_MINIMIZED: case ui::SHOW_STATE_MAXIMIZED: case ui::SHOW_STATE_FULLSCREEN: + case ui::SHOW_STATE_DETACHED: return state; case ui::SHOW_STATE_DEFAULT: @@ -1348,16 +1349,10 @@ void SessionService::BuildCommandsForBrowser( DCHECK(browser && commands); DCHECK(browser->session_id().id()); - ui::WindowShowState show_state = ui::SHOW_STATE_NORMAL; - if (browser->window()->IsMaximized()) - show_state = ui::SHOW_STATE_MAXIMIZED; - else if (browser->window()->IsMinimized()) - show_state = ui::SHOW_STATE_MINIMIZED; - commands->push_back( CreateSetWindowBoundsCommand(browser->session_id(), browser->window()->GetRestoredBounds(), - show_state)); + browser->window()->GetRestoredState())); commands->push_back(CreateSetWindowTypeCommand( browser->session_id(), WindowTypeForBrowserType(browser->type()))); diff --git a/chrome/browser/ui/base_window.h b/chrome/browser/ui/base_window.h index deaa700..823b7dc 100644 --- a/chrome/browser/ui/base_window.h +++ b/chrome/browser/ui/base_window.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_BASE_WINDOW_H_ #include "base/compiler_specific.h" +#include "ui/base/ui_base_types.h" // WindowShowState #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -38,6 +39,9 @@ class BaseWindow { // currently maximized or minimized) in terms of the screen coordinates. virtual gfx::Rect GetRestoredBounds() const = 0; + // Returns the restore state for the window (platform dependent). + virtual ui::WindowShowState GetRestoredState() const = 0; + // Retrieves the window's current bounds, including its window. // This will only differ from GetRestoredBounds() for maximized // and minimized windows. diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h index 71a3666..925f288 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.h +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h @@ -60,6 +60,7 @@ class BrowserWindowCocoa : virtual void SetStarredState(bool is_starred) OVERRIDE; virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual bool IsMaximized() const OVERRIDE; virtual bool IsMinimized() const OVERRIDE; diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm index 773dff8..65c506b 100644 --- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm @@ -316,6 +316,14 @@ gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const { return bounds; } +ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; + if (IsMinimized()) + return ui::SHOW_STATE_MINIMIZED; + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect BrowserWindowCocoa::GetBounds() const { return GetRestoredBounds(); } diff --git a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h index e9f12a0..d021e36 100644 --- a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h +++ b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.h @@ -53,6 +53,7 @@ class NativeAppWindowCocoa : public NativeAppWindow { virtual bool IsFullscreen() const OVERRIDE; virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual void Show() OVERRIDE; virtual void ShowInactive() OVERRIDE; @@ -104,6 +105,7 @@ class NativeAppWindowCocoa : public NativeAppWindow { // NativeAppWindow implementation. virtual void SetFullscreen(bool fullscreen) OVERRIDE; virtual bool IsFullscreenOrPending() const OVERRIDE; + virtual bool IsDetached() const OVERRIDE; virtual void UpdateWindowIcon() OVERRIDE; virtual void UpdateWindowTitle() OVERRIDE; virtual void UpdateDraggableRegions( diff --git a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm index 21dbb2d..34dbc59 100644 --- a/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm +++ b/chrome/browser/ui/cocoa/extensions/native_app_window_cocoa.mm @@ -394,6 +394,10 @@ bool NativeAppWindowCocoa::IsFullscreenOrPending() const { return is_fullscreen_; } +bool NativeAppWindowCocoa::IsDetached() const { + return false; +} + gfx::NativeWindow NativeAppWindowCocoa::GetNativeWindow() { return window(); } @@ -407,6 +411,12 @@ gfx::Rect NativeAppWindowCocoa::GetRestoredBounds() const { return bounds; } +ui::WindowShowState NativeAppWindowCocoa::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect NativeAppWindowCocoa::GetBounds() const { return GetRestoredBounds(); } diff --git a/chrome/browser/ui/extensions/native_app_window.h b/chrome/browser/ui/extensions/native_app_window.h index 811f4ed..447a9e0 100644 --- a/chrome/browser/ui/extensions/native_app_window.h +++ b/chrome/browser/ui/extensions/native_app_window.h @@ -26,6 +26,9 @@ class NativeAppWindow : public BaseWindow, public WebContentsModalDialogHost { virtual void SetFullscreen(bool fullscreen) = 0; virtual bool IsFullscreenOrPending() const = 0; + // Returns true if the window is a panel that has been detached. + virtual bool IsDetached() const = 0; + // Called when the icon of the window changes. virtual void UpdateWindowIcon() = 0; diff --git a/chrome/browser/ui/extensions/shell_window.cc b/chrome/browser/ui/extensions/shell_window.cc index e6c48ed..f167e74 100644 --- a/chrome/browser/ui/extensions/shell_window.cc +++ b/chrome/browser/ui/extensions/shell_window.cc @@ -72,7 +72,7 @@ ShellWindow::CreateParams::CreateParams() transparent_background(false), bounds(INT_MIN, INT_MIN, 0, 0), creator_process_id(0), - state(STATE_NORMAL), + state(ui::SHOW_STATE_DEFAULT), hidden(false), resizable(true), focused(true) { @@ -104,7 +104,7 @@ ShellWindow::ShellWindow(Profile* profile, void ShellWindow::Init(const GURL& url, ShellWindowContents* shell_window_contents, - const ShellWindow::CreateParams& params) { + const CreateParams& params) { // Initialize the render interface and web contents shell_window_contents_.reset(shell_window_contents); shell_window_contents_->Initialize(profile(), url); @@ -130,6 +130,7 @@ void ShellWindow::Init(const GURL& url, // If left and top are left undefined, the native shell window will center // the window on the main screen in a platform-defined manner. + ui::WindowShowState cached_state = ui::SHOW_STATE_DEFAULT; if (!params.window_key.empty()) { window_key_ = params.window_key; @@ -138,11 +139,12 @@ void ShellWindow::Init(const GURL& url, shell_window_geometry_cache(); gfx::Rect cached_bounds; if (cache->GetGeometry(extension()->id(), params.window_key, - &cached_bounds)) + &cached_bounds, &cached_state)) { bounds = cached_bounds; + } } - ShellWindow::CreateParams new_params = params; + CreateParams new_params = params; gfx::Size& minimum_size = new_params.minimum_size; gfx::Size& maximum_size = new_params.maximum_size; @@ -166,30 +168,27 @@ void ShellWindow::Init(const GURL& url, new_params.bounds = bounds; - native_app_window_.reset(NativeAppWindow::Create(this, new_params)); - OnNativeWindowChanged(); + if (cached_state != ui::SHOW_STATE_DEFAULT) + new_params.state = cached_state; - switch (params.state) { - case CreateParams::STATE_NORMAL: - break; - case CreateParams::STATE_FULLSCREEN: - Fullscreen(); - break; - case CreateParams::STATE_MAXIMIZED: - Maximize(); - break; - case CreateParams::STATE_MINIMIZED: - Minimize(); - break; - } + native_app_window_.reset(NativeAppWindow::Create(this, new_params)); - if (!params.hidden) { + if (!new_params.hidden) { if (window_type_is_panel()) GetBaseWindow()->ShowInactive(); // Panels are not activated by default. else GetBaseWindow()->Show(); } + if (new_params.state == ui::SHOW_STATE_FULLSCREEN) + Fullscreen(); + else if (new_params.state == ui::SHOW_STATE_MAXIMIZED) + Maximize(); + else if (new_params.state == ui::SHOW_STATE_MINIMIZED) + Minimize(); + + OnNativeWindowChanged(); + // When the render view host is changed, the native window needs to know // about it in case it has any setup to do to make the renderer appear // properly. In particular, on Windows, the view's clickthrough region needs @@ -576,7 +575,8 @@ void ShellWindow::SaveWindowPosition() { gfx::Rect bounds = native_app_window_->GetRestoredBounds(); bounds.Inset(native_app_window_->GetFrameInsets()); - cache->SaveGeometry(extension()->id(), window_key_, bounds); + ui::WindowShowState window_state = native_app_window_->GetRestoredState(); + cache->SaveGeometry(extension()->id(), window_key_, bounds, window_state); } // static diff --git a/chrome/browser/ui/extensions/shell_window.h b/chrome/browser/ui/extensions/shell_window.h index 7b28a5c..05b06ab 100644 --- a/chrome/browser/ui/extensions/shell_window.h +++ b/chrome/browser/ui/extensions/shell_window.h @@ -15,6 +15,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/common/console_message_level.h" +#include "ui/base/ui_base_types.h" // WindowShowState #include "ui/gfx/image/image.h" #include "ui/gfx/rect.h" @@ -102,15 +103,8 @@ class ShellWindow : public content::NotificationObserver, // The process ID of the process that requested the create. int32 creator_process_id; - enum State { - STATE_NORMAL, - STATE_FULLSCREEN, - STATE_MAXIMIZED, - STATE_MINIMIZED - }; - // Initial state of the window. - State state; + ui::WindowShowState state; // If true, don't show the window after creation. bool hidden; diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc index e594a6c..22ac92a 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.cc +++ b/chrome/browser/ui/gtk/browser_window_gtk.cc @@ -799,6 +799,14 @@ gfx::Rect BrowserWindowGtk::GetRestoredBounds() const { return restored_bounds_; } +ui::WindowShowState BrowserWindowGtk::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; + if (IsMinimized()) + return ui::SHOW_STATE_MINIMIZED; + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect BrowserWindowGtk::GetBounds() const { return bounds_; } diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h index 5ff445f..67dac6b 100644 --- a/chrome/browser/ui/gtk/browser_window_gtk.h +++ b/chrome/browser/ui/gtk/browser_window_gtk.h @@ -59,13 +59,13 @@ class PrefRegistrySyncable; // An implementation of BrowserWindow for GTK. Cross-platform code will interact // with this object when it needs to manipulate the window. -class BrowserWindowGtk : - public BrowserWindow, - public content::NotificationObserver, - public TabStripModelObserver, - public ui::ActiveWindowWatcherXObserver, - public InfoBarContainer::Delegate, - public extensions::ExtensionKeybindingRegistry::Delegate { +class BrowserWindowGtk + : public BrowserWindow, + public content::NotificationObserver, + public TabStripModelObserver, + public ui::ActiveWindowWatcherXObserver, + public InfoBarContainer::Delegate, + public extensions::ExtensionKeybindingRegistry::Delegate { public: explicit BrowserWindowGtk(Browser* browser); virtual ~BrowserWindowGtk(); @@ -95,6 +95,7 @@ class BrowserWindowGtk : virtual void SetStarredState(bool is_starred) OVERRIDE; virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual bool IsMaximized() const OVERRIDE; virtual bool IsMinimized() const OVERRIDE; diff --git a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc index b717e10..6e3a488 100644 --- a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc +++ b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.cc @@ -170,6 +170,12 @@ gfx::Rect NativeAppWindowGtk::GetRestoredBounds() const { return window_bounds; } +ui::WindowShowState NativeAppWindowGtk::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect NativeAppWindowGtk::GetBounds() const { gfx::Rect window_bounds = bounds_; window_bounds.Inset(-GetFrameInsets()); @@ -485,6 +491,10 @@ bool NativeAppWindowGtk::IsFullscreenOrPending() const { return content_thinks_its_fullscreen_; } +bool NativeAppWindowGtk::IsDetached() const { + return false; +} + void NativeAppWindowGtk::UpdateWindowIcon() { Profile* profile = shell_window_->profile(); gfx::Image app_icon = shell_window_->app_icon(); diff --git a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h index 7facadd..c75c46a 100644 --- a/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h +++ b/chrome/browser/ui/gtk/extensions/native_app_window_gtk.h @@ -36,8 +36,10 @@ class NativeAppWindowGtk : public NativeAppWindow, virtual bool IsMaximized() const OVERRIDE; virtual bool IsMinimized() const OVERRIDE; virtual bool IsFullscreen() const OVERRIDE; + virtual bool IsDetached() const OVERRIDE; virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual void Show() OVERRIDE; virtual void ShowInactive() OVERRIDE; diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc index 7fadec8..02af37e 100644 --- a/chrome/browser/ui/panels/panel.cc +++ b/chrome/browser/ui/panels/panel.cc @@ -253,6 +253,10 @@ gfx::Rect Panel::GetRestoredBounds() const { return bounds; } +ui::WindowShowState Panel::GetRestoredState() const { + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect Panel::GetBounds() const { return native_panel_->GetPanelBounds(); } diff --git a/chrome/browser/ui/panels/panel.h b/chrome/browser/ui/panels/panel.h index b2362a4..1542aa9 100644 --- a/chrome/browser/ui/panels/panel.h +++ b/chrome/browser/ui/panels/panel.h @@ -119,6 +119,7 @@ class Panel : public BaseWindow, virtual bool IsFullscreen() const OVERRIDE; virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual void Show() OVERRIDE; virtual void Hide() OVERRIDE; diff --git a/chrome/browser/ui/views/extensions/native_app_window_views.cc b/chrome/browser/ui/views/extensions/native_app_window_views.cc index e981a84..6781fcd 100644 --- a/chrome/browser/ui/views/extensions/native_app_window_views.cc +++ b/chrome/browser/ui/views/extensions/native_app_window_views.cc @@ -41,7 +41,9 @@ #include "ash/wm/panels/panel_frame_view.h" #include "ash/wm/window_properties.h" #include "chrome/browser/ui/ash/ash_util.h" +#include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" +#include "ui/aura/window.h" #endif namespace { @@ -261,15 +263,21 @@ void NativeAppWindowViews::InitializePanelWindow( window_->Init(params); window_->set_focus_on_creation(create_params.focused); -#if !defined(USE_ASH) - // TODO(oshima|stevenjb): Ideally, we should be able to just pre-determine - // the exact location and size, but this doesn't work well - // on non-ash environment where we don't have full control over - // window management. - gfx::Rect window_bounds = - window_->non_client_view()->GetWindowBoundsForClientBounds( - create_params.bounds); - window_->SetBounds(window_bounds); +#if defined(USE_ASH) + if (create_params.state == ui::SHOW_STATE_DETACHED) { + gfx::Rect window_bounds(create_params.bounds.x(), + create_params.bounds.y(), + preferred_size_.width(), + preferred_size_.height()); + aura::Window* native_window = GetNativeWindow(); + native_window->SetProperty(ash::internal::kPanelAttachedKey, false); + native_window->SetDefaultParentByRootWindow( + native_window->GetRootWindow(), native_window->GetBoundsInScreen()); + window_->SetBounds(window_bounds); + } +#else + // TODO(stevenjb): NativeAppWindow panels need to be implemented for other + // platforms. #endif } @@ -299,6 +307,23 @@ gfx::Rect NativeAppWindowViews::GetRestoredBounds() const { return window_->GetRestoredBounds(); } +ui::WindowShowState NativeAppWindowViews::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; +#if defined(USE_ASH) + // On Ash, restore fullscreen. + if (IsFullscreen()) + return ui::SHOW_STATE_FULLSCREEN; + // Use kRestoreShowStateKey in case a window is minimized/hidden. + ui::WindowShowState restore_state = + window_->GetNativeWindow()->GetProperty( + aura::client::kRestoreShowStateKey); + if (restore_state != ui::SHOW_STATE_MINIMIZED) + return restore_state; +#endif + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect NativeAppWindowViews::GetBounds() const { return window_->GetWindowBoundsInScreen(); } @@ -670,6 +695,17 @@ bool NativeAppWindowViews::IsFullscreenOrPending() const { return is_fullscreen_; } +bool NativeAppWindowViews::IsDetached() const { + if (!shell_window_->window_type_is_panel()) + return false; +#if defined(USE_ASH) + return !window_->GetNativeWindow()->GetProperty( + ash::internal::kPanelAttachedKey); +#else + return false; +#endif +} + views::View* NativeAppWindowViews::GetContentsView() { return this; } diff --git a/chrome/browser/ui/views/extensions/native_app_window_views.h b/chrome/browser/ui/views/extensions/native_app_window_views.h index 4a5cbac..90448d2 100644 --- a/chrome/browser/ui/views/extensions/native_app_window_views.h +++ b/chrome/browser/ui/views/extensions/native_app_window_views.h @@ -69,6 +69,7 @@ class NativeAppWindowViews : public NativeAppWindow, virtual bool IsFullscreen() const OVERRIDE; virtual gfx::NativeWindow GetNativeWindow() OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual void Show() OVERRIDE; virtual void ShowInactive() OVERRIDE; @@ -129,6 +130,7 @@ class NativeAppWindowViews : public NativeAppWindow, // NativeAppWindow implementation. virtual void SetFullscreen(bool fullscreen) OVERRIDE; virtual bool IsFullscreenOrPending() const OVERRIDE; + virtual bool IsDetached() const OVERRIDE; virtual void UpdateWindowIcon() OVERRIDE; virtual void UpdateWindowTitle() OVERRIDE; virtual void UpdateDraggableRegions( diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 0604615..ebe1f38 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -774,6 +774,14 @@ gfx::Rect BrowserView::GetRestoredBounds() const { return frame_->GetRestoredBounds(); } +ui::WindowShowState BrowserView::GetRestoredState() const { + if (IsMaximized()) + return ui::SHOW_STATE_MAXIMIZED; + if (IsMinimized()) + return ui::SHOW_STATE_MINIMIZED; + return ui::SHOW_STATE_NORMAL; +} + gfx::Rect BrowserView::GetBounds() const { return frame_->GetWindowBoundsInScreen(); } diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index d307e87..4744a17 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -276,6 +276,7 @@ class BrowserView : public BrowserWindow, virtual void SetStarredState(bool is_starred) OVERRIDE; virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE; virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual bool IsMaximized() const OVERRIDE; virtual bool IsMinimized() const OVERRIDE; diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js index 83322cf..a2a5af1 100644 --- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js @@ -122,9 +122,9 @@ appWindow.registerCustomHook(function(bindingsAPI) { id: params.id || '', bounds: { left: params.bounds.left, top: params.bounds.top, width: params.bounds.width, height: params.bounds.height }, - fullscreen: false, - minimized: false, - maximized: false + fullscreen: params.fullscreen, + minimized: params.minimized, + maximized: params.maximized }; chromeHidden.currentAppWindow = new AppWindow; }); diff --git a/chrome/test/base/test_browser_window.cc b/chrome/test/base/test_browser_window.cc index e454194..25102b2 100644 --- a/chrome/test/base/test_browser_window.cc +++ b/chrome/test/base/test_browser_window.cc @@ -38,6 +38,10 @@ gfx::Rect TestBrowserWindow::GetRestoredBounds() const { return gfx::Rect(); } +ui::WindowShowState TestBrowserWindow::GetRestoredState() const { + return ui::SHOW_STATE_DEFAULT; +} + gfx::Rect TestBrowserWindow::GetBounds() const { return gfx::Rect(); } diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index 2394601..1f84811 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h @@ -47,6 +47,7 @@ class TestBrowserWindow : public BrowserWindow { virtual void SetStarredState(bool is_starred) OVERRIDE {} virtual void ZoomChangedForActiveTab(bool can_show_bubble) OVERRIDE {} virtual gfx::Rect GetRestoredBounds() const OVERRIDE; + virtual ui::WindowShowState GetRestoredState() const OVERRIDE; virtual gfx::Rect GetBounds() const OVERRIDE; virtual bool IsMaximized() const OVERRIDE; virtual bool IsMinimized() const OVERRIDE; diff --git a/chrome/test/data/extensions/platform_apps/restore_state/empty.html b/chrome/test/data/extensions/platform_apps/restore_state/empty.html new file mode 100644 index 0000000..aabcd1b --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/restore_state/empty.html @@ -0,0 +1 @@ +<!-- This file intentionally left blank. --> diff --git a/chrome/test/data/extensions/platform_apps/restore_state/manifest.json b/chrome/test/data/extensions/platform_apps/restore_state/manifest.json new file mode 100644 index 0000000..1d8f040 --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/restore_state/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "Platform App Test: restore window state", + "version": "1", + "app": { + "background": { + "scripts": ["test.js"] + } + } +} diff --git a/chrome/test/data/extensions/platform_apps/restore_state/test.js b/chrome/test/data/extensions/platform_apps/restore_state/test.js new file mode 100644 index 0000000..d7497be --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/restore_state/test.js @@ -0,0 +1,46 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var assertState = function(win) { + if (win.id == 'normal') { + chrome.test.assertFalse(win.isMinimized()); + chrome.test.assertFalse(win.isMaximized()); + } + if (win.id == 'maximized') { + chrome.test.assertFalse(win.isMinimized()); + chrome.test.assertTrue(win.isMaximized()); + } +} + +var testRestoreState = function(state_type) { + chrome.app.window.create( + 'empty.html', + { id: state_type, state: state_type }, + chrome.test.callbackPass(windowCreated) + ); + function windowCreated(win) { + assertState(win); + win.onClosed.addListener(chrome.test.callbackPass(windowClosed)); + win.close(); + function windowClosed() { + chrome.app.window.create( + 'empty.html', + { id: state_type }, + function(win2) { assertState(win2); } + ); + } + }; +} + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.test.runTests([ + function testRestoreNormal() { + testRestoreState('normal'); + }, + function testRestoreMaximized() { + testRestoreState('maximized'); + }, + // Minimize and fullscreen behavior are platform dependent. + ]); +}); diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index 739f2e0..7ba9f87 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc @@ -28,6 +28,8 @@ DEFINE_WINDOW_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE); // gfx::Rect object for RestoreBoundsKey property is owned by the window // and will be freed automatically. DEFINE_OWNED_WINDOW_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, NULL); +DEFINE_WINDOW_PROPERTY_KEY( + ui::WindowShowState, kRestoreShowStateKey, ui::SHOW_STATE_DEFAULT); DEFINE_WINDOW_PROPERTY_KEY(ui::InputMethod*, kRootWindowInputMethodKey, NULL); DEFINE_WINDOW_PROPERTY_KEY( ui::WindowShowState, kShowStateKey, ui::SHOW_STATE_DEFAULT); diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index 6681eea..32c524f 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h @@ -44,6 +44,11 @@ AURA_EXPORT extern const WindowProperty<ui::ModalType>* const kModalKey; // A property key to store the restore bounds for a window. AURA_EXPORT extern const WindowProperty<gfx::Rect*>* const kRestoreBoundsKey; +// A property key to store ui::WindowShowState for restoring a window. +// Used in Ash to remember the show state before the window was minimized. +AURA_EXPORT extern const WindowProperty<ui::WindowShowState>* const + kRestoreShowStateKey; + // A property key to store an input method object that handles a key event. AURA_EXPORT extern const WindowProperty<ui::InputMethod*>* const kRootWindowInputMethodKey; diff --git a/ui/base/ui_base_types.h b/ui/base/ui_base_types.h index 3eb46ca..2f1bcec 100644 --- a/ui/base/ui_base_types.h +++ b/ui/base/ui_base_types.h @@ -17,7 +17,8 @@ enum WindowShowState { SHOW_STATE_MAXIMIZED = 3, SHOW_STATE_INACTIVE = 4, // Views only, not persisted. SHOW_STATE_FULLSCREEN = 5, - SHOW_STATE_END = 6 // The end of show state enum. + SHOW_STATE_DETACHED = 6, // Views only; detached panel. + SHOW_STATE_END = 7 // The end of show state enum. }; // Dialog button identifiers used to specify which buttons to show the user. |