1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#import <Cocoa/Cocoa.h> 6 7#import "chrome/browser/ui/cocoa/window_size_autosaver.h" 8 9#include "chrome/browser/prefs/pref_service.h" 10#include "chrome/browser/prefs/scoped_user_pref_update.h" 11 12// If the window width stored in the prefs is smaller than this, the size is 13// not restored but instead cleared from the profile -- to protect users from 14// accidentally making their windows very small and then not finding them again. 15const int kMinWindowWidth = 101; 16 17// Minimum restored window height, see |kMinWindowWidth|. 18const int kMinWindowHeight = 17; 19 20@interface WindowSizeAutosaver (Private) 21- (void)save:(NSNotification*)notification; 22- (void)restore; 23@end 24 25@implementation WindowSizeAutosaver 26 27- (id)initWithWindow:(NSWindow*)window 28 prefService:(PrefService*)prefs 29 path:(const char*)path { 30 if ((self = [super init])) { 31 window_ = window; 32 prefService_ = prefs; 33 path_ = path; 34 35 [self restore]; 36 [[NSNotificationCenter defaultCenter] 37 addObserver:self 38 selector:@selector(save:) 39 name:NSWindowDidMoveNotification 40 object:window_]; 41 [[NSNotificationCenter defaultCenter] 42 addObserver:self 43 selector:@selector(save:) 44 name:NSWindowDidResizeNotification 45 object:window_]; 46 } 47 return self; 48} 49 50- (void)dealloc { 51 [[NSNotificationCenter defaultCenter] removeObserver:self]; 52 [super dealloc]; 53} 54 55- (void)save:(NSNotification*)notification { 56 DictionaryPrefUpdate update(prefService_, path_); 57 DictionaryValue* windowPrefs = update.Get(); 58 NSRect frame = [window_ frame]; 59 if ([window_ styleMask] & NSResizableWindowMask) { 60 // Save the origin of the window. 61 windowPrefs->SetInteger("left", NSMinX(frame)); 62 windowPrefs->SetInteger("right", NSMaxX(frame)); 63 // windows's and linux's profiles have top < bottom due to having their 64 // screen origin in the upper left, while cocoa's is in the lower left. To 65 // keep the top < bottom invariant, store top in bottom and vice versa. 66 windowPrefs->SetInteger("top", NSMinY(frame)); 67 windowPrefs->SetInteger("bottom", NSMaxY(frame)); 68 } else { 69 // Save the origin of the window. 70 windowPrefs->SetInteger("x", frame.origin.x); 71 windowPrefs->SetInteger("y", frame.origin.y); 72 } 73} 74 75- (void)restore { 76 // Get the positioning information. 77 const DictionaryValue* windowPrefs = prefService_->GetDictionary(path_); 78 if ([window_ styleMask] & NSResizableWindowMask) { 79 int x1, x2, y1, y2; 80 if (!windowPrefs->GetInteger("left", &x1) || 81 !windowPrefs->GetInteger("right", &x2) || 82 !windowPrefs->GetInteger("top", &y1) || 83 !windowPrefs->GetInteger("bottom", &y2)) { 84 return; 85 } 86 if (x2 - x1 < kMinWindowWidth || y2 - y1 < kMinWindowHeight) { 87 // Windows should never be very small. 88 DictionaryPrefUpdate update(prefService_, path_); 89 DictionaryValue* mutableWindowPrefs = update.Get(); 90 mutableWindowPrefs->Remove("left", NULL); 91 mutableWindowPrefs->Remove("right", NULL); 92 mutableWindowPrefs->Remove("top", NULL); 93 mutableWindowPrefs->Remove("bottom", NULL); 94 } else { 95 [window_ setFrame:NSMakeRect(x1, y1, x2 - x1, y2 - y1) display:YES]; 96 97 // Make sure the window is on-screen. 98 [window_ cascadeTopLeftFromPoint:NSZeroPoint]; 99 } 100 } else { 101 int x, y; 102 if (!windowPrefs->GetInteger("x", &x) || 103 !windowPrefs->GetInteger("y", &y)) 104 return; // Nothing stored. 105 // Turn the origin (lower-left) into an upper-left window point. 106 NSPoint upperLeft = NSMakePoint(x, y + NSHeight([window_ frame])); 107 [window_ cascadeTopLeftFromPoint:upperLeft]; 108 } 109} 110 111@end 112 113