From fcdc18a51a39aa9f9a8961306eb583d17ee26289 Mon Sep 17 00:00:00 2001 From: "thakis@chromium.org" Date: Tue, 19 Jan 2010 22:10:53 +0000 Subject: Mac: Save/restore task manager window pos and size. Make window size remembering mechanism easier to use and more compatible with windows's chrome profiles. Nib changes: Unset "show at startup" so that the initial repositioning isn't visible. BUG=32147 TEST=Move & size taskman window, quit chrome, reopen chrome. Size & pos should've stayed. Same for keyword editor. Page info dialog should behave as it did before. Review URL: http://codereview.chromium.org/536086 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36557 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/app/nibs/KeywordEditor.xib | 612 ++------------------- chrome/app/nibs/PageInfo.xib | 19 +- chrome/app/nibs/TaskManager.xib | 4 +- chrome/browser/browser_prefs.cc | 11 +- .../cocoa/keyword_editor_cocoa_controller.h | 3 + .../cocoa/keyword_editor_cocoa_controller.mm | 27 +- chrome/browser/cocoa/nswindow_local_state.h | 21 - chrome/browser/cocoa/nswindow_local_state.mm | 37 -- .../browser/cocoa/nswindow_local_state_unittest.mm | 71 --- chrome/browser/cocoa/page_info_window_controller.h | 3 + .../browser/cocoa/page_info_window_controller.mm | 35 +- chrome/browser/cocoa/task_manager_mac.h | 3 + chrome/browser/cocoa/task_manager_mac.mm | 23 +- chrome/browser/cocoa/window_size_autosaver.h | 45 ++ chrome/browser/cocoa/window_size_autosaver.mm | 95 ++++ .../cocoa/window_size_autosaver_unittest.mm | 157 ++++++ chrome/chrome_browser.gypi | 4 +- chrome/chrome_tests.gypi | 2 +- 18 files changed, 397 insertions(+), 775 deletions(-) delete mode 100644 chrome/browser/cocoa/nswindow_local_state.h delete mode 100644 chrome/browser/cocoa/nswindow_local_state.mm delete mode 100644 chrome/browser/cocoa/nswindow_local_state_unittest.mm create mode 100644 chrome/browser/cocoa/window_size_autosaver.h create mode 100644 chrome/browser/cocoa/window_size_autosaver.mm create mode 100644 chrome/browser/cocoa/window_size_autosaver_unittest.mm diff --git a/chrome/app/nibs/KeywordEditor.xib b/chrome/app/nibs/KeywordEditor.xib index 7e28a4e..15c0f28 100644 --- a/chrome/app/nibs/KeywordEditor.xib +++ b/chrome/app/nibs/KeywordEditor.xib @@ -1,18 +1,14 @@ - + 1050 - 10B504 - 732 - 1038.2 - 437.00 - - com.apple.InterfaceBuilder.CocoaPlugin - 732 - + 9L31a + 677 + 949.54 + 353.00 YES - + YES @@ -20,7 +16,7 @@ YES - + YES @@ -46,7 +42,7 @@ ^IDS_SEARCH_ENGINES_EDITOR_WINDOW_TITLE NSWindow - {1.79769e+308, 1.79769e+308} + {3.40282e+38, 3.40282e+38} {400, 250} @@ -86,16 +82,16 @@ YES name - 286 - 40 - 1000 + 2.860000e+02 + 4.000000e+01 + 1.000000e+03 75628096 2048 ^IDS_SEARCH_ENGINES_EDITOR_DESCRIPTION_COLUMN LucidaGrande - 11 + 1.100000e+01 3100 @@ -118,7 +114,7 @@ Image and Text Cell LucidaGrande - 13 + 1.300000e+01 1044 @@ -142,9 +138,9 @@ keyword - 266 - 40 - 1000 + 2.660000e+02 + 4.000000e+01 + 1.000000e+03 75628096 2048 @@ -165,7 +161,7 @@ controlBackgroundColor 3 - MC42NjY2NjY2NjY3AA + MC42NjY2NjY2OQA @@ -180,8 +176,8 @@ - 3 - 2 + 3.000000e+00 + 2.000000e+00 6 @@ -192,15 +188,12 @@ MC41AA - 18 + 1.800000e+01 1379958784 - - 1 15 0 YES - 0 {{1, 17}, {558, 315}} @@ -217,7 +210,7 @@ _doScroller: - 0.99683549999999999 + 9.968355e-01 @@ -227,7 +220,7 @@ 1 _doScroller: - 0.93781512605042017 + 9.378151e-01 @@ -330,7 +323,7 @@ {{0, 0}, {1680, 1028}} {400, 272} - {1.79769e+308, 1.79769e+308} + {3.40282e+38, 3.40282e+38} ChromeUILocalizer @@ -441,26 +434,28 @@ YES 0 - + + YES + -2 - - File's Owner + + RmlsZSdzIE93bmVyA -1 - + First Responder -3 - + Application @@ -470,7 +465,7 @@ YES - + 2 @@ -589,7 +584,7 @@ 29 - + 41 @@ -600,7 +595,7 @@ YES - + YES -1.IBPluginDependency -2.IBPluginDependency @@ -636,10 +631,10 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{329, 482}, {558, 352}} + {{205, 482}, {558, 352}} com.apple.InterfaceBuilder.CocoaPlugin - {{329, 482}, {558, 352}} - + {{205, 482}, {558, 352}} + {196, 240} {{357, 418}, {480, 270}} @@ -665,7 +660,9 @@ YES - + + YES + YES @@ -673,7 +670,9 @@ YES - + + YES + YES @@ -697,7 +696,7 @@ NSObject YES - + YES otherObjectToLocalize_ owner_ @@ -720,7 +719,7 @@ NSWindowController YES - + YES addKeyword: deleteKeyword: @@ -735,7 +734,7 @@ YES - + YES addButton_ makeDefaultButton_ @@ -777,529 +776,8 @@ - - YES - - NSActionCell - NSCell - - IBFrameworkSource - AppKit.framework/Headers/NSActionCell.h - - - - NSApplication - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSApplication.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSApplicationScripting.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSColorPanel.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSHelpManager.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSPageLayout.h - - - - NSApplication - - IBFrameworkSource - AppKit.framework/Headers/NSUserInterfaceItemSearching.h - - - - NSButton - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSButton.h - - - - NSButtonCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSButtonCell.h - - - - NSCell - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSCell.h - - - - NSControl - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSControl.h - - - - NSFormatter - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFormatter.h - - - - NSMenu - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSMenu.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSAccessibility.h - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDictionaryController.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSDragging.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontManager.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSFontPanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSKeyValueBinding.h - - - - NSObject - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSNibLoading.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSOutlineView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSPasteboard.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSSavePanel.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableView.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSToolbarItem.h - - - - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSView.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSError.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSFileManager.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyValueObserving.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSKeyedArchiver.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObject.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSObjectScripting.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSPortCoder.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSRunLoop.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptClassDescription.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptKeyValueCoding.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptObjectSpecifiers.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSScriptWhoseTests.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSThread.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURL.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLConnection.h - - - - NSObject - - IBFrameworkSource - Foundation.framework/Headers/NSURLDownload.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CAAnimation.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CALayer.h - - - - NSObject - - IBFrameworkSource - QuartzCore.framework/Headers/CIImageProvider.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFAuthorizationView.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFCertificatePanel.h - - - - NSObject - - IBFrameworkSource - SecurityInterface.framework/Headers/SFChooseIdentityPanel.h - - - - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSInterfaceStyle.h - - - - NSResponder - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSResponder.h - - - - NSScrollView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSScrollView.h - - - - NSScroller - NSControl - - IBFrameworkSource - AppKit.framework/Headers/NSScroller.h - - - - NSTableColumn - NSObject - - IBFrameworkSource - AppKit.framework/Headers/NSTableColumn.h - - - - NSTableHeaderView - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSTableHeaderView.h - - - - NSTableView - NSControl - - - - NSTextFieldCell - NSActionCell - - IBFrameworkSource - AppKit.framework/Headers/NSTextFieldCell.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSClipView.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSMenuItem.h - - - - NSView - - IBFrameworkSource - AppKit.framework/Headers/NSRulerView.h - - - - NSView - NSResponder - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSDrawer.h - - - - NSWindow - NSResponder - - IBFrameworkSource - AppKit.framework/Headers/NSWindow.h - - - - NSWindow - - IBFrameworkSource - AppKit.framework/Headers/NSWindowScripting.h - - - - NSWindowController - NSResponder - - showWindow: - id - - - IBFrameworkSource - AppKit.framework/Headers/NSWindowController.h - - - 0 - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.macosx - - - - com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 - - - YES ../../chrome.xcodeproj 3 diff --git a/chrome/app/nibs/PageInfo.xib b/chrome/app/nibs/PageInfo.xib index a294a65..d043b27 100644 --- a/chrome/app/nibs/PageInfo.xib +++ b/chrome/app/nibs/PageInfo.xib @@ -2,13 +2,13 @@ 1050 - 9L30 + 9L31a 677 949.54 353.00 YES - + YES @@ -768,11 +768,11 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{549, 366}, {460, 290}} + {{303, 366}, {460, 290}} com.apple.InterfaceBuilder.CocoaPlugin - - {{549, 366}, {460, 290}} - + + {{303, 366}, {460, 290}} + {196, 240} {{357, 418}, {480, 270}} com.apple.InterfaceBuilder.CocoaPlugin @@ -911,13 +911,6 @@ - NSWindow - - IBProjectSource - browser/cocoa/nswindow_local_state.h - - - PageInfoWindowController NSWindowController diff --git a/chrome/app/nibs/TaskManager.xib b/chrome/app/nibs/TaskManager.xib index 2fe33d8..ceed983 100644 --- a/chrome/app/nibs/TaskManager.xib +++ b/chrome/app/nibs/TaskManager.xib @@ -8,7 +8,7 @@ 353.00 YES - + YES @@ -573,7 +573,7 @@ {{274, 515}, {480, 270}} com.apple.InterfaceBuilder.CocoaPlugin {{274, 515}, {480, 270}} - + {196, 240} {{357, 418}, {480, 270}} com.apple.InterfaceBuilder.CocoaPlugin diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index ced36f5..b9e7fa2 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -31,19 +31,12 @@ #include "chrome/browser/session_startup_pref.h" #include "chrome/browser/ssl/ssl_manager.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/task_manager.h" #if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port #include "chrome/browser/views/frame/browser_view.h" #endif -#if defined(OS_WIN) || defined(OS_LINUX) -#include "chrome/browser/task_manager.h" -#endif - -#if defined(OS_WIN) -#include "chrome/browser/views/keyword_editor_view.h" -#endif - #if defined(TOOLKIT_GTK) #include "chrome/browser/gtk/browser_window_gtk.h" #endif @@ -77,9 +70,7 @@ void RegisterLocalState(PrefService* local_state) { #if defined(TOOLKIT_VIEWS) // TODO(port): whittle this down as we port BrowserView::RegisterBrowserViewPrefs(local_state); #endif -#if defined(OS_WIN) || defined(OS_LINUX) TaskManager::RegisterPrefs(local_state); -#endif } void RegisterUserPrefs(PrefService* user_prefs) { diff --git a/chrome/browser/cocoa/keyword_editor_cocoa_controller.h b/chrome/browser/cocoa/keyword_editor_cocoa_controller.h index 9023a15..73aed70 100644 --- a/chrome/browser/cocoa/keyword_editor_cocoa_controller.h +++ b/chrome/browser/cocoa/keyword_editor_cocoa_controller.h @@ -15,6 +15,7 @@ class EditSearchEngineControllerDelegate; @class KeywordEditorCocoaController; class Profile; +@class WindowSizeAutosaver; // Very thin bridge that simply pushes notifications from C++ to ObjC. class KeywordEditorModelObserver : public TemplateURLModelObserver, @@ -77,6 +78,8 @@ class KeywordEditorModelObserver : public TemplateURLModelObserver, Profile* profile_; // weak scoped_ptr controller_; scoped_ptr observer_; + + scoped_nsobject sizeSaver_; } @property (readonly) KeywordEditorController* controller; diff --git a/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm b/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm index 7440a17..5495235 100644 --- a/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm +++ b/chrome/browser/cocoa/keyword_editor_cocoa_controller.mm @@ -9,8 +9,8 @@ #include "base/sys_string_conversions.h" #include "chrome/browser/browser_process.h" #import "chrome/browser/cocoa/edit_search_engine_cocoa_controller.h" -#import "chrome/browser/cocoa/nswindow_local_state.h" #import "chrome/browser/cocoa/keyword_editor_cocoa_controller.h" +#import "chrome/browser/cocoa/window_size_autosaver.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_table_model.h" #include "chrome/common/pref_names.h" @@ -144,6 +144,14 @@ typedef std::map ProfileControllerMap; controller_->table_model()->SetObserver(observer_.get()); controller_->url_model()->AddObserver(observer_.get()); groupCell_.reset([[NSTextFieldCell alloc] init]); + + if (g_browser_process && g_browser_process->local_state()) { + sizeSaver_.reset([[WindowSizeAutosaver alloc] + initWithWindow:[self window] + prefService:g_browser_process->local_state() + path:prefs::kKeywordEditorWindowPlacement + state:kSaveWindowRect]); + } } return self; } @@ -164,14 +172,6 @@ typedef std::map ProfileControllerMap; size.height = NSHeight([addButton_ frame]); [makeDefaultButton_ setFrameSize:size]; - // Restore the window position. - if (g_browser_process && g_browser_process->local_state()) { - PrefService* prefs = g_browser_process->local_state(); - NSWindow* window = [self window]; - [window restoreWindowPositionFromPrefs:prefs - withPath:prefs::kKeywordEditorWindowPlacement]; - } - [self adjustEditingButtons]; [tableView_ setDoubleAction:@selector(editKeyword:)]; [tableView_ setTarget:self]; @@ -192,15 +192,6 @@ typedef std::map ProfileControllerMap; } } -// Remeber the position of the keyword editor. -- (void)windowDidMove:(NSNotification*)notif { - if (g_browser_process && g_browser_process->local_state()) { - NSWindow* window = [self window]; - [window saveWindowPositionToPrefs:g_browser_process->local_state() - withPath:prefs::kKeywordEditorWindowPlacement]; - } -} - - (void)modelChanged { [tableView_ reloadData]; [self adjustEditingButtons]; diff --git a/chrome/browser/cocoa/nswindow_local_state.h b/chrome/browser/cocoa/nswindow_local_state.h deleted file mode 100644 index 93be19bc..0000000 --- a/chrome/browser/cocoa/nswindow_local_state.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2009 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. - -class PrefService; -@class NSWindow; - -// These additions to NSWindow assist in saving and restoring a window's -// position to Chromium's local state preferences. - -@interface NSWindow (LocalStateAdditions) - -// Saves the window's origin into the given PrefService. Caller is responsible -// for making sure |prefs| is not NULL. -- (void)saveWindowPositionToPrefs:(PrefService*)prefs - withPath:(const wchar_t*)path; - -- (void)restoreWindowPositionFromPrefs:(PrefService*)prefs - withPath:(const wchar_t*)path; - -@end diff --git a/chrome/browser/cocoa/nswindow_local_state.mm b/chrome/browser/cocoa/nswindow_local_state.mm deleted file mode 100644 index 42bc948..0000000 --- a/chrome/browser/cocoa/nswindow_local_state.mm +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2009 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. - -#import -#include "chrome/common/pref_service.h" - -@implementation NSWindow (LocalStateAdditions) - -- (void)saveWindowPositionToPrefs:(PrefService*)prefs - withPath:(const wchar_t*)path { - DCHECK(prefs); - // Save the origin of the window. - DictionaryValue* windowPrefs = prefs->GetMutableDictionary(path); - NSRect frame = [self frame]; - windowPrefs->SetInteger(L"x", frame.origin.x); - windowPrefs->SetInteger(L"y", frame.origin.y); -} - -- (void)restoreWindowPositionFromPrefs:(PrefService*)prefs - withPath:(const wchar_t*)path { - DCHECK(prefs); - // Get the positioning information. - DictionaryValue* windowPrefs = prefs->GetMutableDictionary(path); - int x = 0, y = 0; - windowPrefs->GetInteger(L"x", &x); - windowPrefs->GetInteger(L"y", &y); - // Turn the origin (lower-left) into an upper-left window point. - NSPoint upperLeft = NSMakePoint(x, y + [self frame].size.height); - NSPoint cascadePoint = [self cascadeTopLeftFromPoint:upperLeft]; - // Cascade again to get the offset when opening new windows. - [self cascadeTopLeftFromPoint:cascadePoint]; - // Force a save of the pref. - [self saveWindowPositionToPrefs:prefs withPath:path]; -} - -@end diff --git a/chrome/browser/cocoa/nswindow_local_state_unittest.mm b/chrome/browser/cocoa/nswindow_local_state_unittest.mm deleted file mode 100644 index ccd4628..0000000 --- a/chrome/browser/cocoa/nswindow_local_state_unittest.mm +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2009 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. - -#import - -#include "base/scoped_nsobject.h" -#include "chrome/browser/cocoa/browser_test_helper.h" -#import "chrome/browser/cocoa/cocoa_test_helper.h" -#import "chrome/browser/cocoa/nswindow_local_state.h" -#include "chrome/common/pref_service.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -class NSWindowLocalStateTest : public CocoaTest { - virtual void SetUp() { - CocoaTest::SetUp(); - path_ = L"NSWindowLocalStateTest"; - window_ = - [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 100, 20, 20) - styleMask:NSTitledWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - browser_helper_.profile()->GetPrefs()->RegisterDictionaryPref(path_); - } - - virtual void TearDown() { - [window_ close]; - CocoaTest::TearDown(); - } - - public: - BrowserTestHelper browser_helper_; - NSWindow* window_; - const wchar_t* path_; -}; - -TEST_F(NSWindowLocalStateTest, SaveWindowPlacement) { - PrefService* prefs = browser_helper_.profile()->GetPrefs(); - ASSERT_TRUE(prefs != NULL); - - // Check to make sure there is no existing pref for window placement. - ASSERT_TRUE(prefs->GetDictionary(path_) == NULL); - - // Ask the window to save its position, then check that a preference - // exists. We're technically passing in a pointer to the user prefs - // and not the local state prefs, but a PrefService* is a - // PrefService*, and this is a unittest. - [window_ saveWindowPositionToPrefs:prefs withPath:path_]; - EXPECT_TRUE(prefs->GetDictionary(path_) != NULL); - int x, y; - DictionaryValue* windowPrefs = prefs->GetMutableDictionary(path_); - windowPrefs->GetInteger(L"x", &x); - windowPrefs->GetInteger(L"y", &y); - EXPECT_EQ(x, [window_ frame].origin.x); - EXPECT_EQ(y, [window_ frame].origin.y); -} - -TEST_F(NSWindowLocalStateTest, RestoreWindowPlacement) { - PrefService* prefs = browser_helper_.profile()->GetPrefs(); - DictionaryValue* windowPrefs = prefs->GetMutableDictionary(path_); - - // Large enough so that the window is on screen without cascasding to a - // totally new location. - const int value = 420; - windowPrefs->SetInteger(L"x", value); - windowPrefs->SetInteger(L"y", value); - [window_ restoreWindowPositionFromPrefs:prefs withPath:path_]; - EXPECT_LT(value, [window_ frame].origin.x); - EXPECT_GT(value, [window_ frame].origin.y); -} diff --git a/chrome/browser/cocoa/page_info_window_controller.h b/chrome/browser/cocoa/page_info_window_controller.h index 5ad689b..c8e5564 100644 --- a/chrome/browser/cocoa/page_info_window_controller.h +++ b/chrome/browser/cocoa/page_info_window_controller.h @@ -9,6 +9,7 @@ class PageInfoWindowMac; class PrefService; +@class WindowSizeAutosaver; // This NSWindowController subclass implements the Cocoa window for // PageInfoWindow. This creates and owns the PageInfoWindowMac subclass. @@ -34,6 +35,8 @@ class PrefService; // Bridge to Chromium that we own. scoped_ptr pageInfo_; + + scoped_nsobject sizeSaver_; } @property(readwrite, retain) NSImage* identityImg; diff --git a/chrome/browser/cocoa/page_info_window_controller.mm b/chrome/browser/cocoa/page_info_window_controller.mm index 04c8049..144cfcb 100644 --- a/chrome/browser/cocoa/page_info_window_controller.mm +++ b/chrome/browser/cocoa/page_info_window_controller.mm @@ -8,17 +8,12 @@ #include "base/mac_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#import "chrome/browser/cocoa/nswindow_local_state.h" #include "chrome/browser/cocoa/page_info_window_mac.h" +#include "chrome/browser/cocoa/window_size_autosaver.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "grit/theme_resources.h" -@interface PageInfoWindowController (Private) -// Saves the window preference to the local state. -- (void)saveWindowPositionToLocalState; -@end - @implementation PageInfoWindowController @synthesize identityImg = identityImg_; @synthesize connectionImg = connectionImg_; @@ -36,18 +31,24 @@ ResourceBundle& rb = ResourceBundle::GetSharedInstance(); goodImg_.reset([rb.GetNSImageNamed(IDR_PAGEINFO_GOOD) retain]); badImg_.reset([rb.GetNSImageNamed(IDR_PAGEINFO_BAD) retain]); + + if (g_browser_process && g_browser_process->local_state()) { + sizeSaver_.reset([[WindowSizeAutosaver alloc] + initWithWindow:[self window] + prefService:g_browser_process->local_state() + path:prefs::kPageInfoWindowPlacement + state:kSaveWindowPos]); + // Cascade again to get the offset when opening new windows. + NSRect frame = [[self window] frame]; + NSPoint cascadePoint = [[self window] + cascadeTopLeftFromPoint:NSMakePoint(NSMinX(frame), NSMaxY(frame))]; + [[self window] cascadeTopLeftFromPoint:cascadePoint]; + } } return self; } - (void)awakeFromNib { - if (g_browser_process && g_browser_process->local_state()) { - // Get the positioning information. - PrefService* prefs = g_browser_process->local_state(); - [[self window] restoreWindowPositionFromPrefs:prefs - withPath:prefs::kPageInfoWindowPlacement]; - } - // By default, assume we have no history information. [self setShowHistoryBox:NO]; } @@ -103,12 +104,4 @@ [self autorelease]; } -// The last page info window that was moved will determine the location of the -// next new one. -- (void)windowDidMove:(NSNotification*)notif { - if (g_browser_process && g_browser_process->local_state()) - [[self window] saveWindowPositionToPrefs:g_browser_process->local_state() - withPath:prefs::kPageInfoWindowPlacement]; -} - @end diff --git a/chrome/browser/cocoa/task_manager_mac.h b/chrome/browser/cocoa/task_manager_mac.h index 5d78cff..b76f80a 100644 --- a/chrome/browser/cocoa/task_manager_mac.h +++ b/chrome/browser/cocoa/task_manager_mac.h @@ -10,6 +10,7 @@ #include "chrome/browser/cocoa/table_row_nsimage_cache.h" #include "chrome/browser/task_manager.h" +@class WindowSizeAutosaver; class TaskManagerMac; // This class is responsible for loading the task manager window and for @@ -21,6 +22,8 @@ class TaskManagerMac; TaskManagerMac* taskManagerObserver_; // weak TaskManager* taskManager_; // weak TaskManagerModel* model_; // weak + + scoped_nsobject size_saver_; } // Creates and shows the task manager's window. diff --git a/chrome/browser/cocoa/task_manager_mac.mm b/chrome/browser/cocoa/task_manager_mac.mm index 8ff5e87..593d9a1 100644 --- a/chrome/browser/cocoa/task_manager_mac.mm +++ b/chrome/browser/cocoa/task_manager_mac.mm @@ -10,9 +10,11 @@ #include "app/l10n_util_mac.h" #include "base/mac_util.h" #include "base/sys_string_conversions.h" +#include "chrome/browser/browser_process.h" +#import "chrome/browser/cocoa/window_size_autosaver.h" +#include "chrome/common/pref_names.h" #include "grit/generated_resources.h" -// TODO(thakis): Autoremember window size/pos (and selected columns?) // TODO(thakis): Better resizing behavior (and think about storing column sizes) // TODO(thakis): Column sort comparator // TODO(thakis): Clicking column header doesn't sort @@ -39,6 +41,14 @@ taskManagerObserver_ = taskManagerObserver; taskManager_ = taskManagerObserver_->task_manager(); model_ = taskManager_->model(); + + if (g_browser_process && g_browser_process->local_state()) { + size_saver_.reset([[WindowSizeAutosaver alloc] + initWithWindow:[self window] + prefService:g_browser_process->local_state() + path:prefs::kTaskManagerWindowPlacement + state:kSaveWindowRect]); + } [[self window] makeKeyAndOrderFront:self]; } return self; @@ -189,17 +199,6 @@ [self adjustEndProcessButton]; } -// Called when the window is being closed. Send out a notification that the user -// is done editing preferences. Make sure there are no pending field editors -// by clearing the first responder. -- (void)windowWillClose:(NSNotification*)notification { - if (taskManagerObserver_) { - taskManagerObserver_->WindowWasClosed(); - taskManagerObserver_ = nil; - } - [self autorelease]; -} - @end @implementation TaskManagerWindowController (NSTableDataSource) diff --git a/chrome/browser/cocoa/window_size_autosaver.h b/chrome/browser/cocoa/window_size_autosaver.h new file mode 100644 index 0000000..c8ace00 --- /dev/null +++ b/chrome/browser/cocoa/window_size_autosaver.h @@ -0,0 +1,45 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_WINDOW_SIZE_AUTOSAVER_H_ +#define CHROME_BROWSER_COCOA_WINDOW_SIZE_AUTOSAVER_H_ + +class PrefService; +@class NSWindow; + +enum WindowSizeAutosaverState { + + // Autosave only the window's bottom-right corner. + kSaveWindowPos, + + // Autosave the whole window rect, i.e. both position and size. + kSaveWindowRect, +}; + +// WindowSizeAutosaver is a helper class that makes it easy to let windows +// autoremember their position or position and size in a PrefService object. +// To use this, add a |scoped_nsobject| to your window +// controller and initialize it in the window controller's init method, passing +// a window and an autosave name. The autosaver will register for "window moved" +// and "window resized" notifications and write the current window state to the +// prefs service every time they fire. The window's size is automatically +// restored when the autosaver's |initWithWindow:...| method is called. +// +// Note: Your xib file should have "Visible at launch" UNCHECKED, so that the +// initial repositioning is not visible. +@interface WindowSizeAutosaver : NSObject { + NSWindow* window_; // weak + PrefService* prefService_; // weak + const wchar_t* path_; + WindowSizeAutosaverState state_; +} + +- (id)initWithWindow:(NSWindow*)window + prefService:(PrefService*)prefs + path:(const wchar_t*)path + state:(WindowSizeAutosaverState)state; +@end + +#endif // CHROME_BROWSER_COCOA_WINDOW_SIZE_AUTOSAVER_H_ + diff --git a/chrome/browser/cocoa/window_size_autosaver.mm b/chrome/browser/cocoa/window_size_autosaver.mm new file mode 100644 index 0000000..d8c0f77 --- /dev/null +++ b/chrome/browser/cocoa/window_size_autosaver.mm @@ -0,0 +1,95 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +#import "chrome/browser/cocoa/window_size_autosaver.h" + +#include "chrome/common/pref_service.h" + +@interface WindowSizeAutosaver (Private) +- (void)save:(NSNotification*)notification; +- (void)restore; +@end + +@implementation WindowSizeAutosaver + +- (id)initWithWindow:(NSWindow*)window + prefService:(PrefService*)prefs + path:(const wchar_t*)path + state:(WindowSizeAutosaverState)state { + if ((self = [super init])) { + window_ = window; + prefService_ = prefs; + path_ = path; + state_ = state; + + [self restore]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(save:) + name:NSWindowDidMoveNotification + object:window_]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(save:) + name:NSWindowDidResizeNotification + object:window_]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)save:(NSNotification*)notification { + DictionaryValue* windowPrefs = prefService_->GetMutableDictionary(path_); + NSRect frame = [window_ frame]; + if (state_ == kSaveWindowRect) { + // Save the origin of the window. + windowPrefs->SetInteger(L"left", NSMinX(frame)); + windowPrefs->SetInteger(L"right", NSMaxX(frame)); + // windows's and linux's profiles have top < bottom due to having their + // screen origin in the upper left, while cocoa's is in the lower left. To + // keep the top < bottom invariant, store top in bottom and vice versa. + windowPrefs->SetInteger(L"top", NSMinY(frame)); + windowPrefs->SetInteger(L"bottom", NSMaxY(frame)); + } else if (state_ == kSaveWindowPos) { + // Save the origin of the window. + windowPrefs->SetInteger(L"x", frame.origin.x); + windowPrefs->SetInteger(L"y", frame.origin.y); + } else { + NOTREACHED(); + } +} + +- (void)restore { + // Get the positioning information. + DictionaryValue* windowPrefs = prefService_->GetMutableDictionary(path_); + if (state_ == kSaveWindowRect) { + int x1, x2, y1, y2; + if (!windowPrefs->GetInteger(L"left", &x1) || + !windowPrefs->GetInteger(L"right", &x2) || + !windowPrefs->GetInteger(L"top", &y1) || + !windowPrefs->GetInteger(L"bottom", &y2)) { + return; + } + [window_ setFrame:NSMakeRect(x1, y1, x2 - x1, y2 - y1) display:YES]; + } else if (state_ == kSaveWindowPos) { + int x, y; + if (!windowPrefs->GetInteger(L"x", &x) || + !windowPrefs->GetInteger(L"y", &y)) + return; // Nothing stored. + // Turn the origin (lower-left) into an upper-left window point. + NSPoint upperLeft = NSMakePoint(x, y + NSHeight([window_ frame])); + [window_ cascadeTopLeftFromPoint:upperLeft]; + } else { + NOTREACHED(); + } +} + +@end + diff --git a/chrome/browser/cocoa/window_size_autosaver_unittest.mm b/chrome/browser/cocoa/window_size_autosaver_unittest.mm new file mode 100644 index 0000000..e5460d4 --- /dev/null +++ b/chrome/browser/cocoa/window_size_autosaver_unittest.mm @@ -0,0 +1,157 @@ +// Copyright (c) 2009 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. + +#import + +#import "chrome/browser/cocoa/window_size_autosaver.h" + +#include "base/scoped_nsobject.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/common/pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +class WindowSizeAutosaverTest : public CocoaTest { + virtual void SetUp() { + CocoaTest::SetUp(); + path_ = L"WindowSizeAutosaverTest"; + window_ = + [[NSWindow alloc] initWithContentRect:NSMakeRect(100, 101, 150, 151) + styleMask:NSTitledWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + browser_helper_.profile()->GetPrefs()->RegisterDictionaryPref(path_); + } + + virtual void TearDown() { + [window_ close]; + CocoaTest::TearDown(); + } + + public: + BrowserTestHelper browser_helper_; + NSWindow* window_; + const wchar_t* path_; +}; + +TEST_F(WindowSizeAutosaverTest, RestoresAndSavesPos) { + PrefService* pref = browser_helper_.profile()->GetPrefs(); + ASSERT_TRUE(pref != NULL); + + // Check to make sure there is no existing pref for window placement. + ASSERT_TRUE(pref->GetDictionary(path_) == NULL); + + // Ask the window to save its position, then check that a preference + // exists. We're technically passing in a pointer to the user prefs + // and not the local state prefs, but a PrefService* is a + // PrefService*, and this is a unittest. + + { + NSRect frame = [window_ frame]; + // Empty state, shouldn't restore: + scoped_nsobject sizeSaver([[WindowSizeAutosaver alloc] + initWithWindow:window_ + prefService:pref + path:path_ + state:kSaveWindowPos]); + EXPECT_EQ(NSMinX(frame), NSMinX([window_ frame])); + EXPECT_EQ(NSMinY(frame), NSMinY([window_ frame])); + EXPECT_EQ(NSWidth(frame), NSWidth([window_ frame])); + EXPECT_EQ(NSHeight(frame), NSHeight([window_ frame])); + + // Move and resize window, should store position but not size. + [window_ setFrame:NSMakeRect(300, 310, 50, 52) display:NO]; + } + + // Another window movement -- shouldn't be recorded. + [window_ setFrame:NSMakeRect(400, 420, 160, 162) display:NO]; + + { + // Should restore last stored position, but not size. + scoped_nsobject sizeSaver([[WindowSizeAutosaver alloc] + initWithWindow:window_ + prefService:pref + path:path_ + state:kSaveWindowPos]); + EXPECT_EQ(300, NSMinX([window_ frame])); + EXPECT_EQ(310, NSMinY([window_ frame])); + EXPECT_EQ(160, NSWidth([window_ frame])); + EXPECT_EQ(162, NSHeight([window_ frame])); + } + + // ...and it should be in the profile, too. + EXPECT_TRUE(pref->GetDictionary(path_) != NULL); + int x, y; + DictionaryValue* windowPref = pref->GetMutableDictionary(path_); + EXPECT_FALSE(windowPref->GetInteger(L"left", &x)); + EXPECT_FALSE(windowPref->GetInteger(L"right", &x)); + EXPECT_FALSE(windowPref->GetInteger(L"top", &x)); + EXPECT_FALSE(windowPref->GetInteger(L"bottom", &x)); + ASSERT_TRUE(windowPref->GetInteger(L"x", &x)); + ASSERT_TRUE(windowPref->GetInteger(L"y", &y)); + EXPECT_EQ(300, x); + EXPECT_EQ(310, y); +} + +TEST_F(WindowSizeAutosaverTest, RestoresAndSavesRect) { + PrefService* pref = browser_helper_.profile()->GetPrefs(); + ASSERT_TRUE(pref != NULL); + + // Check to make sure there is no existing pref for window placement. + ASSERT_TRUE(pref->GetDictionary(path_) == NULL); + + // Ask the window to save its position, then check that a preference + // exists. We're technically passing in a pointer to the user prefs + // and not the local state prefs, but a PrefService* is a + // PrefService*, and this is a unittest. + + { + NSRect frame = [window_ frame]; + // Empty state, shouldn't restore: + scoped_nsobject sizeSaver([[WindowSizeAutosaver alloc] + initWithWindow:window_ + prefService:pref + path:path_ + state:kSaveWindowRect]); + EXPECT_EQ(NSMinX(frame), NSMinX([window_ frame])); + EXPECT_EQ(NSMinY(frame), NSMinY([window_ frame])); + EXPECT_EQ(NSWidth(frame), NSWidth([window_ frame])); + EXPECT_EQ(NSHeight(frame), NSHeight([window_ frame])); + + // Move and resize window, should store + [window_ setFrame:NSMakeRect(300, 310, 50, 52) display:NO]; + } + + // Another window movement -- shouldn't be recorded. + [window_ setFrame:NSMakeRect(400, 420, 160, 162) display:NO]; + + { + // Should restore last stored size + scoped_nsobject sizeSaver([[WindowSizeAutosaver alloc] + initWithWindow:window_ + prefService:pref + path:path_ + state:kSaveWindowRect]); + EXPECT_EQ(300, NSMinX([window_ frame])); + EXPECT_EQ(310, NSMinY([window_ frame])); + EXPECT_EQ(50, NSWidth([window_ frame])); + EXPECT_EQ(52, NSHeight([window_ frame])); + } + + // ...and it should be in the profile, too. + EXPECT_TRUE(pref->GetDictionary(path_) != NULL); + int x1, y1, x2, y2; + DictionaryValue* windowPref = pref->GetMutableDictionary(path_); + EXPECT_FALSE(windowPref->GetInteger(L"x", &x1)); + EXPECT_FALSE(windowPref->GetInteger(L"y", &x1)); + ASSERT_TRUE(windowPref->GetInteger(L"left", &x1)); + ASSERT_TRUE(windowPref->GetInteger(L"right", &x2)); + ASSERT_TRUE(windowPref->GetInteger(L"top", &y1)); + ASSERT_TRUE(windowPref->GetInteger(L"bottom", &y2)); + EXPECT_EQ(300, x1); + EXPECT_EQ(310, y1); + EXPECT_EQ(300 + 50, x2); + EXPECT_EQ(310 + 52, y2); +} diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 666ecf8..69680d1 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -522,8 +522,6 @@ 'browser/cocoa/multi_key_equivalent_button.mm', 'browser/cocoa/nsmenuitem_additions.h', 'browser/cocoa/nsmenuitem_additions.mm', - 'browser/cocoa/nswindow_local_state.h', - 'browser/cocoa/nswindow_local_state.mm', 'browser/cocoa/objc_method_swizzle.h', 'browser/cocoa/objc_method_swizzle.mm', 'browser/cocoa/page_info_window_controller.h', @@ -589,6 +587,8 @@ 'browser/cocoa/web_drag_source.mm', 'browser/cocoa/web_drop_target.h', 'browser/cocoa/web_drop_target.mm', + 'browser/cocoa/window_size_autosaver.h', + 'browser/cocoa/window_size_autosaver.mm', 'browser/command_updater.cc', 'browser/command_updater.h', 'browser/cookies_tree_model.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 7ed6e6a..5b70806 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -634,7 +634,6 @@ 'browser/cocoa/menu_controller_unittest.mm', 'browser/cocoa/nsimage_cache_unittest.mm', 'browser/cocoa/nsmenuitem_additions_unittest.mm', - 'browser/cocoa/nswindow_local_state_unittest.mm', 'browser/cocoa/objc_method_swizzle_unittest.mm', 'browser/cocoa/page_info_window_controller_unittest.mm', 'browser/cocoa/preferences_window_controller_unittest.mm', @@ -662,6 +661,7 @@ 'browser/cocoa/view_resizer_pong.h', 'browser/cocoa/view_resizer_pong.mm', 'browser/cocoa/web_drop_target_unittest.mm', + 'browser/cocoa/window_size_autosaver_unittest.mm', 'browser/command_updater_unittest.cc', 'browser/cookies_tree_model_unittest.cc', 'browser/debugger/devtools_manager_unittest.cc', -- cgit v1.1