Home | History | Annotate | Download | only in cocoa
      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.
     15 const int kMinWindowWidth = 101;
     16 
     17 // Minimum restored window height, see |kMinWindowWidth|.
     18 const 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