| // Copyright (c) 2011 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 <Cocoa/Cocoa.h> |
| |
| #import "chrome/browser/ui/cocoa/window_size_autosaver.h" |
| |
| #include "base/prefs/pref_service.h" |
| #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| |
| // If the window width stored in the prefs is smaller than this, the size is |
| // not restored but instead cleared from the profile -- to protect users from |
| // accidentally making their windows very small and then not finding them again. |
| const int kMinWindowWidth = 101; |
| |
| // Minimum restored window height, see |kMinWindowWidth|. |
| const int kMinWindowHeight = 17; |
| |
| @interface WindowSizeAutosaver (Private) |
| - (void)save:(NSNotification*)notification; |
| - (void)restore; |
| @end |
| |
| @implementation WindowSizeAutosaver |
| |
| - (id)initWithWindow:(NSWindow*)window |
| prefService:(PrefService*)prefs |
| path:(const char*)path { |
| if ((self = [super init])) { |
| window_ = window; |
| prefService_ = prefs; |
| path_ = path; |
| |
| [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 { |
| DictionaryPrefUpdate update(prefService_, path_); |
| DictionaryValue* windowPrefs = update.Get(); |
| NSRect frame = [window_ frame]; |
| if ([window_ styleMask] & NSResizableWindowMask) { |
| // Save the origin of the window. |
| windowPrefs->SetInteger("left", NSMinX(frame)); |
| windowPrefs->SetInteger("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("top", NSMinY(frame)); |
| windowPrefs->SetInteger("bottom", NSMaxY(frame)); |
| } else { |
| // Save the origin of the window. |
| windowPrefs->SetInteger("x", frame.origin.x); |
| windowPrefs->SetInteger("y", frame.origin.y); |
| } |
| } |
| |
| - (void)restore { |
| // Get the positioning information. |
| const DictionaryValue* windowPrefs = prefService_->GetDictionary(path_); |
| if ([window_ styleMask] & NSResizableWindowMask) { |
| int x1, x2, y1, y2; |
| if (!windowPrefs->GetInteger("left", &x1) || |
| !windowPrefs->GetInteger("right", &x2) || |
| !windowPrefs->GetInteger("top", &y1) || |
| !windowPrefs->GetInteger("bottom", &y2)) { |
| return; |
| } |
| if (x2 - x1 < kMinWindowWidth || y2 - y1 < kMinWindowHeight) { |
| // Windows should never be very small. |
| DictionaryPrefUpdate update(prefService_, path_); |
| DictionaryValue* mutableWindowPrefs = update.Get(); |
| mutableWindowPrefs->Remove("left", NULL); |
| mutableWindowPrefs->Remove("right", NULL); |
| mutableWindowPrefs->Remove("top", NULL); |
| mutableWindowPrefs->Remove("bottom", NULL); |
| } else { |
| [window_ setFrame:NSMakeRect(x1, y1, x2 - x1, y2 - y1) display:YES]; |
| |
| // Make sure the window is on-screen. |
| [window_ cascadeTopLeftFromPoint:NSZeroPoint]; |
| } |
| } else { |
| int x, y; |
| if (!windowPrefs->GetInteger("x", &x) || |
| !windowPrefs->GetInteger("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]; |
| } |
| } |
| |
| @end |
| |