123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500 |
- #import "CTBrowser.h"
- #import "CTBrowserWindow.h"
- #import "CTBrowserWindowController.h"
- #import "CTPresentationModeController.h"
- #import "CTFloatingBarBackingView.h"
- #import "CTTabContents.h"
- #import "CTTabStripController.h"
- #import "CTTabStripModel.h"
- #import "CTTabView.h"
- #import "CTTabStripView.h"
- #import "CTToolbarController.h"
- #import "CTUtil.h"
- #import "FastResizeView.h"
- #import "CTTabController.h"
- #if VERSION_DMG
- #import <PDF_Master-Swift.h>
- #else
- #import <PDF_Master-Swift.h>
- #endif
- #import "common.h"
- //#import "scoped_nsdisable_screen_updates.h"
- @interface NSWindow (ThingsThatMightBeImplemented)
- - (void)setShouldHideTitle:(BOOL)y;
- - (void)setBottomCornerRounded:(BOOL)y;
- @end
- @interface CTBrowserWindowController (Private)
- - (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY
- width:(CGFloat)width
- fullscreen:(BOOL)fullscreen;
- - (CGFloat)layoutToolbarAtMinX:(CGFloat)minX
- maxY:(CGFloat)maxY
- width:(CGFloat)width;
- @end
- @interface CTBrowserWindowController (FullScreen)
- - (void)registerForContentViewResizeNotifications;
- - (void)deregisterForContentViewResizeNotifications;
- // Creates the button used to toggle presentation mode. Must only be called on
- // Lion or later. Does nothing if the button already exists.
- - (void)createAndInstallPresentationModeToggleButton;
- // Toggles presentation mode without exiting fullscreen mode. Should only be
- // called by the presentation mode toggle button.
- - (void)togglePresentationModeForLionOrLater:(id)sender;
- // Sets presentation mode, creating the PresentationModeController if needed and
- // forcing a relayout. If |forceDropdown| is YES, this method will always
- // initially show the floating bar when entering presentation mode, even if the
- // floating bar does not have focus. This method is safe to call on all OS
- // versions.
- - (void)setPresentationModeInternal:(BOOL)presentationMode
- forceDropdown:(BOOL)forceDropdown;
- // Allows/prevents bar visibility locks and releases from updating the visual
- // state. Enabling makes changes instantaneously; disabling cancels any
- // timers/animation.
- - (void)enableBarVisibilityUpdates;
- - (void)disableBarVisibilityUpdates;
- @end
- @implementation NSDocumentController (CTBrowserWindowControllerAdditions)
- - (id)openUntitledDocumentWithWindowController:(NSWindowController*)windowController
- display:(BOOL)display
- error:(NSError **)outError {
- // default implementation
- return [self openUntitledDocumentAndDisplay:display error:outError];
- }
- @end
- static CTBrowserWindowController* _currentMain = nil; // weak
- @implementation CTBrowserWindowController
- @synthesize tabStripController = tabStripController_;
- @synthesize toolbarController = toolbarController_;
- @synthesize browser = browser_;
- @synthesize shouldUsePresentationModeWhenEnteringFullscreen = shouldUsePresentationModeWhenEnteringFullscreen_;
- + (CTBrowserWindowController*)browserWindowController {
- return [[self alloc] init];
- }
- + (CTBrowserWindowController*)mainBrowserWindowController {
- return _currentMain;
- }
- + (CTBrowserWindowController*)browserWindowControllerForWindow:(NSWindow*)window {
- while (window) {
- id controller = [window windowController];
- if ([controller isKindOfClass:[CTBrowserWindowController class]])
- return (CTBrowserWindowController*)controller;
- window = [window parentWindow];
- }
- return nil;
- }
- + (CTBrowserWindowController*)browserWindowControllerForView:(NSView*)view {
- NSWindow* window = [view window];
- return [CTBrowserWindowController browserWindowControllerForWindow:window];
- }
- // Load the browser window nib and do initialization. Note that the nib also
- // sets this controller up as the window's delegate.
- - (id)initWithWindowNibPath:(NSString *)windowNibPath
- browser:(CTBrowser*)browser {
- if (!(self = [super initWithWindowNibPath:windowNibPath owner:self]))
- return nil;
-
- // Set initialization boolean state so subroutines can act accordingly
- initializing_ = YES;
-
- // Our browser
- browser_ = browser;
- NSWindow* window = [self window];
-
- // Lion will attempt to automagically save and restore the UI. This
- // functionality appears to be leaky (or at least interacts badly with our
- // architecture) and thus BrowserWindowController never gets released. This
- // prevents the browser from being able to quit <http://crbug.com/79113>.
- //
- // As of 2013/05/03, with ARC and the latest retain cycle fixups, I don't
- // see restorable windows causing any more trouble, so I'm re-enabling this
- // functionality.
- // if ([window respondsToSelector:@selector(setRestorable:)])
- // [window setRestorable:NO];
- // Create the bar visibility lock set; 10 is arbitrary, but should hopefully
- // be big enough to hold all locks that'll ever be needed.
- barVisibilityLocks_ = [NSMutableSet setWithCapacity:10];
-
- // Note: the below statement including [self window] implicitly loads the
- // window and thus initializes IBOutlets, needed later. If [self window] is
- // not called (i.e. code removed), substitute the loading with a call to
- // [self loadWindow]
-
- // Set the window to not have rounded corners, which prevents the resize
- // control from being inset slightly and looking ugly. Only bother to do
- // this on Snow Leopard and earlier; on Lion and later all windows have
- // rounded bottom corners, and this won't work anyway.
- if ([window respondsToSelector:@selector(setBottomCornerRounded:)])
- [window setBottomCornerRounded:NO];
- [[window contentView] setAutoresizesSubviews:YES];
-
- // Lion will attempt to automagically save and restore the UI. This
- // functionality appears to be leaky (or at least interacts badly with our
- // architecture) and thus BrowserWindowController never gets released. This
- // prevents the browser from being able to quit <http://crbug.com/79113>.
- //
- // As of 2013/05/03, with ARC and the latest retain cycle fixups, I don't
- // see restorable windows causing any more trouble, so I'm re-enabling this
- // functionality.
- // if ([window respondsToSelector:@selector(setRestorable:)])
- // [window setRestorable:NO];
- // Note: when using the default BrowserWindow.xib, window bounds are saved and
- // restored by Cocoa using NSUserDefaults key "browserWindow".
-
- // Get the windows to swish in on Lion.
- if ([window respondsToSelector:@selector(setAnimationBehavior:)])
- [window setAnimationBehavior:NSWindowAnimationBehaviorDocumentWindow];
-
- // Set the window to participate in Lion Fullscreen mode. Setting this flag
- // has no effect on Snow Leopard or earlier. Panels can share a fullscreen
- // space with a tabbed window, but they can not be primary fullscreen
- // windows.
- NSUInteger collectionBehavior = [window collectionBehavior];
- collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
- [window setCollectionBehavior:collectionBehavior];
-
- // Create a tab strip controller
- tabStripController_ =
- [[CTTabStripController alloc] initWithView:self.tabStripView
- switchView:self.tabContentArea
- browser:browser_];
- tabStripController_.isHomeFixWidth = YES;
-
- // Create a toolbar controller. The browser object might return nil, in which
- // means we do not have a toolbar.
- toolbarController_ = [browser_ createToolbarController];
- if (toolbarController_ && self.hasToolbar) {
- [[[self window] contentView] addSubview:[toolbarController_ view]];
- }
- self.rightStripView.wantsLayer = YES;
- self.homeRightStripView.wantsLayer = YES;
- // When using NSDocuments
- [self setShouldCloseDocument:YES];
-
- // Allow bar visibility to be changed.
- [self enableBarVisibilityUpdates];
-
- // Observe tabs
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabDidSelect:)
- name:CTTabSelectedNotification
- object:browser_.tabStripModel];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabDidInsert:)
- name:CTTabInsertedNotification
- object:browser_.tabStripModel];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabDidReplace:)
- name:CTTabReplacedNotification
- object:browser_.tabStripModel];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabDidDetach:)
- name:CTTabDetachedNotification
- object:browser_.tabStripModel];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabWillClose:)
- name:CTTabClosingNotification
- object:browser_.tabStripModel];
-
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tabStripDidBecomeEmpty)
- name:CTTabStripEmptyNotification
- object:browser_.tabStripModel];
-
- // Register for application hide/unhide notifications.
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(applicationDidHide:)
- name:NSApplicationDidHideNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(applicationDidUnhide:)
- name:NSApplicationDidUnhideNotification
- object:nil];
-
- // Force a relayout of all the various bars.
- [self layoutSubviews];
-
- initializing_ = NO;
- if (!_currentMain) {
- // ct_casid(&_currentMain, self);
- _currentMain = self;
- }
- return self;
- }
- - (id)initWithBrowser:(CTBrowser *)browser {
- // subclasses could override this to provie a custom nib
- NSString *windowNibPath = [CTUtil pathForResource:@"KMBrowserWindowController"
- ofType:@"nib"];
- return [self initWithWindowNibPath:windowNibPath browser:browser];
- }
- - (id)init {
- // subclasses could override this to provide a custom |CTBrowser|
- return [self initWithBrowser:[CTBrowser browser]];
- }
- -(void)finalize {
- if (_currentMain == self) {
- // ct_casid(&_currentMain, nil);
- _currentMain = nil;
- }
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super finalize];
- }
- - (BOOL)hasToolbar {
- return !!toolbarController_;
- }
- - (void)setDisableNewTabButton:(BOOL)disable {
- tabStripController_.disableNewTabButton = disable;
- }
- - (BOOL)disableNewTabButton {
- return tabStripController_.disableNewTabButton;
- }
- // Updates the toolbar with the states of the specified |contents|.
- // If |shouldRestore| is YES, we're switching (back?) to this tab and should
- // restore any previous state (such as user editing a text field) as well.
- - (void)updateToolbarWithContents:(CTTabContents*)contents
- shouldRestoreState:(BOOL)shouldRestore {
- // safe even if toolbarController_ is nil
- [toolbarController_ updateToolbarWithContents:contents
- shouldRestoreState:shouldRestore];
- }
- - (void)synchronizeWindowTitleWithDocumentName {
- // overriding this to not do anything have the effect of not adding a title to
- // our window (the title is in the tab, remember?)
- }
- #pragma mark -
- #pragma mark NSWindow (CTThemed)
- - (NSPoint)themePatternPhase {
- // Our patterns want to be drawn from the upper left hand corner of the view.
- // Cocoa wants to do it from the lower left of the window.
- //
- // Rephase our pattern to fit this view. Some other views (Tabs, Toolbar etc.)
- // will phase their patterns relative to this so all the views look right.
- //
- // To line up the background pattern with the pattern in the browser window
- // the background pattern for the tabs needs to be moved left by 5 pixels.
- const CGFloat kPatternHorizontalOffset = -5;
- NSView* tabStripView = [self tabStripView];
- NSRect tabStripViewWindowBounds = [tabStripView bounds];
- NSView* windowChromeView = [[[self window] contentView] superview];
- tabStripViewWindowBounds =
- [tabStripView convertRect:tabStripViewWindowBounds
- toView:windowChromeView];
- NSPoint phase = NSMakePoint(NSMinX(tabStripViewWindowBounds)
- + kPatternHorizontalOffset,
- NSMinY(tabStripViewWindowBounds)
- + [CTTabStripController defaultTabHeight]);
- CTTabContents* document = [self.browser activeTabContents];
- NSView * rightView = nil;
- if (document.isHome) {
- rightView = self.homeRightStripView;
- self.rightStripView.hidden = YES;
- self.homeRightStripView.hidden = NO;
- } else {
- rightView = self.rightStripView;
- self.rightStripView.hidden = NO;
- self.homeRightStripView.hidden = YES;
- }
- CGFloat rightOffst = NSWidth(rightView.frame);
- NSRect contentFrame = [windowChromeView frame];
- NSRect rightFrame =
- NSMakeRect(NSWidth(contentFrame) - rightOffst, rightView.frame.origin.y,
- rightOffst,
- NSHeight([tabStripView frame]));
- [rightView setFrame:rightFrame];
- NSView* contentParent = [[[self window] contentView] superview];
- [contentParent addSubview:[self tabStripView] positioned:NSWindowAbove relativeTo:nil];
- [contentParent addSubview:rightView positioned:NSWindowAbove relativeTo:nil];
- return phase;
- }
- #pragma mark -
- #pragma mark Actions
- - (IBAction)saveAllDocuments:(id)sender {
- [[NSDocumentController sharedDocumentController] saveAllDocuments:sender];
- }
- - (IBAction)openDocument:(id)sender {
- [[NSDocumentController sharedDocumentController] openDocument:sender];
- }
- - (IBAction)newDocument:(id)sender {
- NSDocumentController* docController =
- [NSDocumentController sharedDocumentController];
- NSError *error = nil;
- DCHECK(browser_);
- CTTabContents *baseTabContents = browser_.activeTabContents;
- CTTabContents *tabContents =
- [docController openUntitledDocumentWithWindowController:self
- display:YES
- error:&error];
- if (!tabContents) {
- [NSApp presentError:error];
- } else if (baseTabContents) {
- tabContents.parentOpener = baseTabContents;
- }
- }
- - (IBAction)newWindow:(id)sender {
- [browser_ newWindow];
- }
- - (IBAction)closeTab:(id)sender {
- [browser_ closeTab];
- }
- // Called when the user picks a menu or toolbar item when this window is key.
- // Calls through to the browser object to execute the command. This assumes that
- // the command is supported and doesn't check, otherwise it would have been
- // disabled in the UI in validateUserInterfaceItem:.
- - (void)commandDispatch:(id)sender {
- assert(sender);
- // Identify the actual BWC to which the command should be dispatched. It might
- // belong to a background window, yet this controller gets it because it is
- // the foreground window's controller and thus in the responder chain. Some
- // senders don't have this problem (for example, menus only operate on the
- // foreground window), so this is only an issue for senders that are part of
- // windows.
- CTBrowserWindowController* targetController = self;
- if ([sender respondsToSelector:@selector(window)])
- targetController = [[sender window] windowController];
- assert([targetController isKindOfClass:[CTBrowserWindowController class]]);
- [targetController.browser executeCommand:[(NSView *)sender tag]];
- }
- #pragma mark -
- #pragma mark CTTabWindowController implementation
- // Accept tabs from a CTBrowserWindowController with the same Profile.
- - (BOOL)canReceiveFrom:(CTTabWindowController*)source {
- if (![source isKindOfClass:[CTTabWindowController class]]) {
- return NO;
- }
-
- // here we could for instance check (and deny) dragging a tab from a normal
- // window into a special window (e.g. pop-up or similar)
-
- return YES;
- }
- #pragma mark -
- #pragma mark Tab Management
- // Move a given tab view to the location of the current placeholder. If there is
- // no placeholder, it will go at the end. |controller| is the window controller
- // of a tab being dropped from a different window. It will be nil if the drag is
- // within the window, otherwise the tab is removed from that window before being
- // placed into this one.
- //
- // The implementation will call |-removePlaceholder| since the drag is now
- // complete. This also calls |-layoutTabs| internally so clients do not need to
- // call it again.
- - (void)moveTabView:(NSView*)view
- fromController:(CTTabWindowController*)dragController {
- if (dragController) {
- // Moving between windows. Figure out the CTTabContents to drop into our tab
- // model from the source window's model.
- BOOL isBrowser =
- [dragController isKindOfClass:[CTBrowserWindowController class]];
- assert(isBrowser);
- if (!isBrowser) return;
- CTBrowserWindowController* dragBWC = (CTBrowserWindowController*)dragController;
- int index = [dragBWC->tabStripController_ modelIndexForTabView:view];
- CTTabContents* contents =
- [[dragBWC->browser_ tabStripModel] tabContentsAtIndex:index];
- // The tab contents may have gone away if given a window.close() while it
- // is being dragged. If so, bail, we've got nothing to drop.
- if (!contents)
- return;
-
- // Convert |view|'s frame (which starts in the source tab strip's coordinate
- // system) to the coordinate system of the destination tab strip. This needs
- // to be done before being detached so the window transforms can be
- // performed.
- NSRect destinationFrame = [view frame];
- NSPoint tabOrigin = destinationFrame.origin;
- tabOrigin = [[dragController tabStripView] convertPoint:tabOrigin
- toView:nil];
- tabOrigin = [[view window] convertBaseToScreen:tabOrigin];
- tabOrigin = [[self window] convertScreenToBase:tabOrigin];
- tabOrigin = [[self tabStripView] convertPoint:tabOrigin fromView:nil];
- if (tabOrigin.x <= [CTTabController homeTabWidth] + [CTTabStripController defaultIndentForControls]){
- tabOrigin.x = [CTTabController homeTabWidth] + [CTTabStripController defaultIndentForControls];
- }
- destinationFrame.origin = tabOrigin;
- // Before the tab is detached from its originating tab strip, store the
- // pinned state so that it can be maintained between the windows.
- BOOL isPinned = [[dragBWC->browser_ tabStripModel] isTabPinnedAtIndex:index];
-
- // Now that we have enough information about the tab, we can remove it from
- // the dragging window. We need to do this *before* we add it to the new
- // window as this will remove the CTTabContents' delegate.
- [dragController detachTabView:view];
-
- // Deposit it into our model at the appropriate location (it already knows
- // where it should go from tracking the drag). Doing this sets the tab's
- // delegate to be the CTBrowser.
- [tabStripController_ dropTabContents:contents
- withFrame:destinationFrame
- asPinnedTab:isPinned];
- } else {
- // Moving within a window.
- int index = [tabStripController_ modelIndexForTabView:view];
- [tabStripController_ moveTabFromIndex:index];
- }
-
- // Remove the placeholder since the drag is now complete.
- [self removePlaceholder];
- }
- - (NSView*)activeTabView {
- return [tabStripController_ activeTabView];
- }
- // Creates a new window by pulling the given tab out and placing it in
- // the new window. Returns the controller for the new window. The size of the
- // new window will be the same size as this window.
- - (CTTabWindowController*)detachTabToNewWindow:(CTTabView*)tabView {
- // Disable screen updates so that this appears as a single visual change.
- NSDisableScreenUpdates();
- @try {
- // Keep a local ref to the tab strip model object
- CTTabStripModel *tabStripModel = [browser_ tabStripModel];
-
- // Fetch the tab contents for the tab being dragged.
- int index = [tabStripController_ modelIndexForTabView:tabView];
- CTTabContents* contents = [tabStripModel tabContentsAtIndex:index];
-
- // Set the window size. Need to do this before we detach the tab so it's
- // still in the window. We have to flip the coordinates as that's what
- // is expected by the CTBrowser code.
- NSWindow* sourceWindow = [tabView window];
- NSRect windowRect = [sourceWindow frame];
- NSScreen* screen = [sourceWindow screen];
- windowRect.origin.y =
- [screen frame].size.height - windowRect.size.height - windowRect.origin.y;
-
- //gfx::Rect browserRect(windowRect.origin.x, windowRect.origin.y,
- // windowRect.size.width, windowRect.size.height);
-
- NSRect tabRect = [tabView frame];
-
- // Before detaching the tab, store the pinned state.
- BOOL isPinned = [tabStripModel isTabPinnedAtIndex:index];
-
- // Detach it from the source window, which just updates the model without
- // deleting the tab contents. This needs to come before creating the new
- // CTBrowser because it clears the CTTabContents' delegate, which gets hooked
- // up during creation of the new window.
- [tabStripModel detachTabContentsAtIndex:index];
-
- // Create the new browser with a single tab in its model, the one being
- // dragged.
- CTBrowser* newBrowser = [browser_ createNewStripWithContents:contents];
- CTBrowserWindowController* controller = [newBrowser windowController];
-
- // Set window frame
- [controller.window setFrame:windowRect display:NO];
-
- // Propagate the tab pinned state of the new tab (which is the only tab in
- // this new window).
- [[newBrowser tabStripModel] setTabAtIndex:0
- pinned:isPinned];
-
- // Force the added tab to the right size (remove stretching.)
- tabRect.size.height = [CTTabStripController defaultTabHeight];
-
- // And make sure we use the correct frame in the new view.
- [[controller tabStripController] setFrameOfActiveTab:tabRect];
- return controller;
- }
- @finally {
- NSEnableScreenUpdates();
- }
- }
- - (void)insertPlaceholderForTab:(CTTabView*)tab
- frame:(NSRect)frame {
- [super insertPlaceholderForTab:tab frame:frame];
- [tabStripController_ insertPlaceholderForTab:tab
- frame:frame];
- }
- - (void)removePlaceholder {
- [super removePlaceholder];
- [tabStripController_ insertPlaceholderForTab:nil
- frame:NSZeroRect];
- }
- - (BOOL)tabDraggingAllowed {
- return [tabStripController_ tabDraggingAllowed];
- }
- // Default implementation of the below are both YES. Until we have fullscreen
- // support these will always be YES.
- - (BOOL)tabTearingAllowed {
- return ![self isFullscreen];
- }
- - (BOOL)windowMovementAllowed {
- return ![self isFullscreen];
- }
- - (BOOL)isTabFullyVisible:(CTTabView*)tab {
- return [tabStripController_ isTabFullyVisible:tab];
- }
- // impl. CTTabWindowController requirements
- - (void)setShowsNewTabButton:(BOOL)show {
- tabStripController_.showsNewTabButton = show;
- }
- - (BOOL)showsNewTabButton {
- return tabStripController_.showsNewTabButton;
- }
- // Tells the tab strip to forget about this tab in preparation for it being
- // put into a different tab strip, such as during a drop on another window.
- - (void)detachTabView:(NSView*)view {
- int index = [tabStripController_ modelIndexForTabView:view];
- [[browser_ tabStripModel] detachTabContentsAtIndex:index];
- }
- - (NSInteger)numberOfTabs {
- // count includes pinned tabs.
- return [[browser_ tabStripModel] count];
- }
- - (BOOL)hasLiveTabs {
- return [self numberOfTabs] > 0;
- }
- - (int)activeTabIndex {
- return [browser_ tabStripModel].activeIndex;
- }
- - (CTTabContents*)activeTabContents {
- return [[browser_ tabStripModel] activeTabContents];
- }
- - (NSString*)activeTabTitle {
- CTTabContents* contents = [self activeTabContents];
- return contents ? contents.title : nil;
- }
- - (BOOL)hasTabStrip {
- return YES;
- }
- -(void)willStartTearingTab {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isTeared = YES;
- }
- }
- -(void)willEndTearingTab {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isTeared = NO;
- }
- }
- -(void)didEndTearingTab {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- [contents tabDidResignTeared];
- }
- }
- - (void)focusTabContents {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- [[self window] makeFirstResponder:contents.view];
- }
- }
- #pragma mark -
- #pragma mark Layout
- // Find the total height of the floating bar (in presentation mode). Safe to
- // call even when not in presentation mode.
- - (CGFloat)floatingBarHeight {
- if (![self inPresentationMode])
- return 0;
-
- CGFloat totalHeight = [presentationModeController_ floatingBarVerticalOffset];
-
- if ([self hasTabStrip])
- totalHeight += NSHeight([[self tabStripView] frame]);
-
- if ([self hasToolbar]) {
- totalHeight += NSHeight([[toolbarController_ view] frame]);
- }
-
- return totalHeight;
- }
- // Lay out the view which draws the background for the floating bar when in
- // presentation mode, with the given frame and presentation-mode-status. Should
- // be called even when not in presentation mode to hide the backing view.
- - (void)layoutFloatingBarBackingView:(NSRect)frame
- presentationMode:(BOOL)presentationMode {
- // Only display when in presentation mode.
- if (presentationMode) {
- // For certain window types such as app windows (e.g., the dev tools
- // window), there's no actual overlay. (Displaying one would result in an
- // overly sliding in only under the menu, which gives an ugly effect.)
- if (floatingBarBackingView_) {
- // BOOL aboveBookmarkBar = [self placeBookmarkBarBelowInfoBar];
- //
- // // Insert it into the view hierarchy if necessary.
- if (![floatingBarBackingView_ superview]) {
- NSView* contentView = [[self window] contentView];
- // z-order gets messed up unless we explicitly remove the floatingbar
- // view and re-add it.
- [floatingBarBackingView_ removeFromSuperview];
- [contentView addSubview:floatingBarBackingView_
- positioned:NSWindowBelow
- relativeTo:[toolbarController_ view]];
- // floatingBarAboveBookmarkBar_ = aboveBookmarkBar;
- }
-
- // Set its frame.
- [floatingBarBackingView_ setFrame:frame];
- }
-
- // But we want the logic to work as usual (for show/hide/etc. purposes).
- [presentationModeController_ overlayFrameChanged:frame];
- } else {
- // Okay to call even if |floatingBarBackingView_| is nil.
- if ([floatingBarBackingView_ superview])
- [floatingBarBackingView_ removeFromSuperview];
- }
- }
- - (void)layoutTabContentArea:(NSRect)newFrame {
- NSView* tabContentView = self.tabContentArea;
- NSRect tabContentFrame = tabContentView.frame;
- BOOL contentShifted =
- NSMaxY(tabContentFrame) != NSMaxY(newFrame) ||
- NSMinX(tabContentFrame) != NSMinX(newFrame);
- tabContentFrame = newFrame;
- [tabContentView setFrame:tabContentFrame];
- // If the relayout shifts the content area up or down, let the renderer know.
- if (contentShifted) {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- [contents viewFrameDidChange:newFrame];
- }
- }
- }
- // Called when the size of the window content area has changed.
- // Position specific views.
- - (void)layoutSubviews {
- // With the exception of the top tab strip, the subviews which we lay out are
- // subviews of the content view, so we mainly work in the content view's
- // coordinate system. Note, however, that the content view's coordinate system
- // and the window's base coordinate system should coincide.
- NSWindow* window = [self window];
- NSView* contentView = [window contentView];
- if (!contentView) {
- return;
- }
- NSRect contentBounds = [contentView bounds];
- CGFloat minX = NSMinX(contentBounds);
- CGFloat minY = NSMinY(contentBounds);
- CGFloat width = NSWidth(contentBounds);
-
- // Suppress title drawing (the title is in the tab, baby)
- if ([window respondsToSelector:@selector(setShouldHideTitle:)])
- [window setShouldHideTitle:YES];
-
- BOOL inPresentationMode = [self inPresentationMode];
- CGFloat floatingBarHeight = [self floatingBarHeight];
- // In presentation mode, |yOffset| accounts for the sliding position of the
- // floating bar and the extra offset needed to dodge the menu bar.
- CGFloat yOffset = inPresentationMode ?
- (floor((1 - floatingBarShownFraction_) * floatingBarHeight) -
- [presentationModeController_ floatingBarVerticalOffset]) : 0;
- CGFloat maxY = NSMaxY(contentBounds) + yOffset;
-
- CGFloat overlayMaxY = NSMaxY([window frame]) + floor((1 - floatingBarShownFraction_) * floatingBarHeight);
- [self layoutPresentationModeToggleAtOverlayMaxX:NSMaxX([window frame])
- overlayMaxY:overlayMaxY];
-
- if ([self hasTabStrip]) {
- // If we need to lay out the top tab strip, replace |maxY| and |startMaxY|
- // with higher values, and then lay out the tab strip.
- NSRect windowFrame = [contentView convertRect:[window frame] fromView:nil];
- maxY = NSHeight(windowFrame) + yOffset;
- maxY = [self layoutTabStripAtMaxY:maxY
- width:width
- fullscreen:[self isFullscreen]];
- }
-
- // Sanity-check |maxY|.
- DCHECK_GE(maxY, minY);
- DCHECK_LE(maxY, NSMaxY(contentBounds) + yOffset);
-
- // Place the toolbar at the top of the reserved area.
- if ([self hasToolbar]){
- NSView* toolbarView = [toolbarController_ view];
- if (!toolbarView.hidden) {
- maxY = [self layoutToolbarAtMinX:minX maxY:maxY width:width];
- }
- }
-
- // The floating bar backing view doesn't actually add any height.
- NSRect floatingBarBackingRect = NSMakeRect(minX, maxY, width, floatingBarHeight);
- [self layoutFloatingBarBackingView:floatingBarBackingRect
- presentationMode:inPresentationMode];
-
- // If in presentation mode, reset |maxY| to top of screen, so that the
- // floating bar slides over the things which appear to be in the content area.
- if (inPresentationMode)
- maxY = NSMaxY(contentBounds);
-
- // Finally, the content area takes up all of the remaining space.
- NSRect contentAreaRect = NSMakeRect(minX, minY, width, maxY - minY);
- [self layoutTabContentArea:contentAreaRect];
-
- // Place the status bubble at the bottom of the content area.
- //verticalOffsetForStatusBubble_ = minY;
-
- // Normally, we don't need to tell the toolbar whether or not to show the
- // divider, but things break down during animation.
- if (toolbarController_) {
- [toolbarController_ setDividerOpacity:0.4];
- }
- // TODO: check this
- // [toolbarController_
- // setDividerOpacity:[bookmarkBarController_ toolbarDividerOpacity]];
- }
- - (CGFloat)layoutToolbarAtMinX:(CGFloat)minX
- maxY:(CGFloat)maxY
- width:(CGFloat)width {
- assert([self hasToolbar]);
- NSView* toolbarView = [toolbarController_ view];
- NSRect toolbarFrame = [toolbarView frame];
- assert(![toolbarView isHidden]);
- toolbarFrame.origin.x = minX;
- toolbarFrame.origin.y = maxY - NSHeight(toolbarFrame);
- toolbarFrame.size.width = width;
- maxY -= NSHeight(toolbarFrame);
- [toolbarView setFrame:toolbarFrame];
- return maxY;
- }
- - (void)layoutTabs {
- [tabStripController_ layoutTabs];
- }
- - (void)layoutPresentationModeToggleAtOverlayMaxX:(CGFloat)maxX
- overlayMaxY:(CGFloat)maxY {
- // Lay out the presentation mode toggle button at the very top of the
- // tab strip.
- if ([self shouldShowPresentationModeToggle]) {
- [self createAndInstallPresentationModeToggleButton];
-
- NSPoint origin =
- NSMakePoint(maxX - NSWidth([presentationModeToggleButton_ frame]),
- maxY - NSHeight([presentationModeToggleButton_ frame]));
- [presentationModeToggleButton_ setFrameOrigin:origin];
- } else {
- [presentationModeToggleButton_ removeFromSuperview];
- presentationModeToggleButton_ = nil;
- }
- }
- - (CGFloat)layoutTabStripAtMaxY:(CGFloat)maxY
- width:(CGFloat)width
- fullscreen:(BOOL)fullscreen {
-
- if (![self hasTabStrip])
- return maxY;
- NSView* tabStripView = [self tabStripView];
-
- CTTabContents* document = [self.browser activeTabContents];
- KMToolbarRightView *rightStripView = nil;
- if (document.isHome) {
- rightStripView = self.homeRightStripView;
- } else {
- rightStripView = self.rightStripView;
- }
- CGFloat rightWidth = NSWidth([rightStripView frame]);
- if ([[KMLightMemberManager manager] canShowAdvancedView] && ![[KMLightMemberManager manager] isLogin]) {
- // rightWidth = NSWidth([rightStripView frame]);
- rightWidth = 56.0 + rightStripView.fetchAdvancedViewSize.width;
- // rightWidth += rightStripView.fetchAdvancedViewSize.width;
- } else {
- rightWidth = 56.0;
- }
- CGFloat tabStripHeight = NSHeight([tabStripView frame]);
- CGFloat tabStripWidth = width - rightWidth;
- maxY -= tabStripHeight;
- if (fullscreen) {
- [tabStripView setFrame:NSMakeRect(0, maxY, tabStripWidth, tabStripHeight)];
- } else {
- CGFloat offset = [[tabStripController_ class] defaultIndentForControls];
- tabStripWidth -= offset;
- [tabStripView setFrame:NSMakeRect(offset, maxY, tabStripWidth, tabStripHeight)];
- }
-
- [tabStripController_ setIndentForControls:0];
- // [rightStripView setFrame:NSMakeRect(NSMaxX(tabStripView.frame), maxY, rightWidth, tabStripHeight)];
- self.homeRightStripView.frame = NSMakeRect(NSMaxX(tabStripView.frame), maxY, rightWidth, tabStripHeight);
- self.rightStripView.frame = NSMakeRect(NSMaxX(tabStripView.frame), maxY, rightWidth, tabStripHeight);
- [(KMToolbarRightView *)self.rightStripView updateView];
- [(KMToolbarRightView *)self.homeRightStripView updateView];
- // Set indentation.
- [tabStripController_ layoutTabsWithoutAnimation];
-
- return maxY;
- }
- #pragma mark -
- #pragma mark NSWindowController impl
- - (BOOL)windowShouldClose:(id)sender {
- // Disable updates while closing all tabs to avoid flickering.
- NSDisableScreenUpdates();
- @try {
- // NOTE: when using the default BrowserWindow.xib, window bounds are saved and
- // restored by Cocoa using NSUserDefaults key "browserWindow".
-
- // NOTE: orderOut: ends up activating another window, so if we save window
- // bounds in a custom manner we have to do it here, before we call
- // orderOut:
-
- if ([browser_.tabStripModel count] > 0) {
- // Tab strip isn't empty. Hide the frame (so it appears to have closed
- // immediately) and close all the tabs, allowing them to shut down. When the
- // tab strip is empty we'll be called back again.
- [[self window] orderOut:self];
- [browser_ windowDidBeginToClose];
- if (_currentMain == self) {
- // ct_casid(&_currentMain, nil);
- _currentMain = nil;
- }
- return NO;
- }
-
- // the tab strip is empty, it's ok to close the window
- return YES;
- }
- @finally {
- NSEnableScreenUpdates();
- }
- }
- - (void)windowWillClose:(NSNotification *)notification {
- // [self autorelease];
- }
- // Called right after our window became the main window.
- - (void)windowDidBecomeMain:(NSNotification*)notification {
- // NOTE: if you use custom window bounds saving/restoring, you should probably
- // save the window bounds here.
- _currentMain = self;
-
- // TODO(dmaclach): Instead of redrawing the whole window, views that care
- // about the active window state should be registering for notifications.
- [[self window] setViewsNeedDisplay:YES];
-
- // TODO(viettrungluu): For some reason, the above doesn't suffice.
- if ([self isFullscreen])
- [floatingBarBackingView_ setNeedsDisplay:YES]; // Okay even if nil.
- }
- - (void)windowDidResignMain:(NSNotification*)notification {
- if (_currentMain == self) {
- _currentMain = nil;
- }
-
- // TODO(dmaclach): Instead of redrawing the whole window, views that care
- // about the active window state should be registering for notifications.
- [[self window] setViewsNeedDisplay:YES];
-
- // TODO(viettrungluu): For some reason, the above doesn't suffice.
- if ([self isFullscreen])
- [floatingBarBackingView_ setNeedsDisplay:YES]; // Okay even if nil.
- }
- // Called when we are activated (when we gain focus).
- - (void)windowDidBecomeKey:(NSNotification*)notification {
- if (![[self window] isMiniaturized]) {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isVisible = YES;
- }
- }
- }
- // Called when we are deactivated (when we lose focus).
- - (void)windowDidResignKey:(NSNotification*)notification {
- // If our app is still active and we're still the key window, ignore this
- // message, since it just means that a menu extra (on the "system status bar")
- // was activated; we'll get another |-windowDidResignKey| if we ever really
- // lose key window status.
- if ([NSApp isActive] && ([NSApp keyWindow] == [self window]))
- return;
- }
- // Called when we have been minimized.
- - (void)windowDidMiniaturize:(NSNotification *)notification {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isVisible = NO;
- }
- }
- // Called when we have been unminimized.
- - (void)windowDidDeminiaturize:(NSNotification *)notification {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isVisible = YES;
- }
- }
- // Called when the application has been hidden.
- - (void)applicationDidHide:(NSNotification *)notification {
- // Let the active tab know (unless we are minimized, in which case nothing
- // has really changed).
- if (![[self window] isMiniaturized]) {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isVisible = NO;
- }
- }
- }
- // Called when the application has been unhidden.
- - (void)applicationDidUnhide:(NSNotification *)notification {
- // Let the active tab know
- // (unless we are minimized, in which case nothing has really changed).
- if (![[self window] isMiniaturized]) {
- CTTabContents* contents = [browser_ activeTabContents];
- if (contents) {
- contents.isVisible = YES;
- }
- }
- }
- #pragma mark -
- #pragma mark Etc (need sorting out)
- - (void)activate {
- [[self window] makeKeyAndOrderFront:self];
- }
- #pragma mark -
- #pragma mark CTTabStripModel Observer
- // Note: the following are called by the CTTabStripModel and thus indicate
- // the model's state rather than the UI state. This means that when for instance
- // tabSelectedWithContents:... is called, the view is not yet on screen, so
- // doing things like restoring focus is not possible.
- // Note: this is called _before_ the view is on screen
- - (void)tabDidSelect:(NSNotification *)notification {
- NSDictionary *userInfo = notification.userInfo;
- CTTabContents *newContents = [userInfo valueForKey:CTTabNewContentsUserInfoKey];
- CTTabContents *oldContents = [userInfo valueForKey:CTTabContentsUserInfoKey];
- assert(newContents != oldContents);
- [self updateToolbarWithContents:newContents
- shouldRestoreState:!!oldContents];
- }
- - (void)tabWillClose:(NSNotification *)notification {
- NSDictionary *userInfo = notification.userInfo;
- CTTabContents *contents = [userInfo valueForKey:CTTabContentsUserInfoKey];
- NSInteger index = [[userInfo valueForKey:CTTabIndexUserInfoKey] intValue];
- [contents tabWillCloseInBrowser:browser_ atIndex:index];
- if (contents.isActive)
- [self updateToolbarWithContents:nil shouldRestoreState:NO];
- }
- - (void)tabDidInsert:(NSNotification *)notification {
- NSDictionary *userInfo = notification.userInfo;
- CTTabContents *contents = [userInfo valueForKey:CTTabContentsUserInfoKey];
- NSInteger index = [[userInfo valueForKey:CTTabIndexUserInfoKey] intValue];
- BOOL isInForeground = [[userInfo valueForKey:CTTabOptionsUserInfoKey] boolValue];
- [contents tabDidInsertIntoBrowser:browser_
- atIndex:index
- inForeground:isInForeground];
- }
- - (void)tabDidReplace:(NSNotification *)notification {
- NSDictionary *userInfo = notification.userInfo;
- CTTabContents *newContents = [userInfo valueForKey:CTTabNewContentsUserInfoKey];
- CTTabContents *oldContents = [userInfo valueForKey:CTTabContentsUserInfoKey];
- NSInteger index = [[userInfo valueForKey:CTTabIndexUserInfoKey] intValue];
- [newContents tabReplaced:oldContents inBrowser:browser_ atIndex:index];
- if ([self activeTabIndex] == index) {
- [self updateToolbarWithContents:newContents
- shouldRestoreState:!!oldContents];
- }
- }
- - (void)tabDidDetach:(NSNotification *)notification {
- NSDictionary *userInfo = notification.userInfo;
- CTTabContents *contents = [userInfo valueForKey:CTTabContentsUserInfoKey];
- NSInteger index = [[userInfo valueForKey:CTTabIndexUserInfoKey] intValue];
- [contents tabDidDetachFromBrowser:browser_ atIndex:index];
- if (contents.isActive)
- [self updateToolbarWithContents:nil shouldRestoreState:NO];
- }
- - (void)tabStripDidBecomeEmpty {
- [self close];
- }
- -(void)updateViewColor
- {
- self.rightStripView.layer.backgroundColor = [KMTabAppearance tabsViewBackgroundColor].CGColor;
- self.homeRightStripView.layer.backgroundColor = [KMTabAppearance tabsViewBackgroundColor].CGColor;
- self.window.backgroundColor = [KMTabAppearance tabsViewBackgroundColor];
- }
- @end
- #pragma mark -
- @implementation CTBrowserWindowController (FullScreen)
- #pragma mark Full Screen Mode
- - (void)contentViewDidResize:(NSNotification*)notification {
- [self layoutSubviews];
- }
- // Register or deregister for content view resize notifications. These
- // notifications are used while transitioning to fullscreen mode in Lion or
- // later. This method is safe to call on all OS versions.
- - (void)registerForContentViewResizeNotifications {
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(contentViewDidResize:)
- name:NSViewFrameDidChangeNotification
- object:[[self window] contentView]];
- }
- - (void)deregisterForContentViewResizeNotifications {
- [[NSNotificationCenter defaultCenter] removeObserver:self
- name:NSViewFrameDidChangeNotification
- object:[[self window] contentView]];
- }
- // On Lion, this method is called by either the Lion fullscreen button or the
- // "Enter Full Screen" menu item. On Snow Leopard, this function is never
- // called by the UI directly, but it provides the implementation for
- // |-setPresentationMode:|.
- - (void)setFullscreen:(BOOL)fullscreen {
- if (fullscreen == [self isFullscreen])
- return;
-
- enteredPresentationModeFromFullscreen_ = YES;
- [self.window toggleFullScreen:nil];
- }
- - (BOOL)isFullscreen {
- return ([[self window] styleMask] & NSFullScreenWindowMask) || enteringFullscreen_;
- }
- - (void)windowWillEnterFullScreen:(NSNotification*)notification {
- [self registerForContentViewResizeNotifications];
-
- // NSWindow* window = [self window];
- // savedRegularWindowFrame_ = [window frame];
- BOOL mode = [self shouldUsePresentationModeWhenEnteringFullscreen];
- // mode = mode || browser_->IsFullscreenForTabOrPending();
- enteringFullscreen_ = YES;
- [self setPresentationModeInternal:mode forceDropdown:NO];
- }
- - (void)windowDidEnterFullScreen:(NSNotification*)notification {
- [self deregisterForContentViewResizeNotifications];
- enteringFullscreen_ = NO;
- }
- - (void)windowWillExitFullScreen:(NSNotification*)notification {
- [self registerForContentViewResizeNotifications];
- [self setPresentationModeInternal:NO forceDropdown:NO];
- }
- - (void)windowDidExitFullScreen:(NSNotification*)notification {
- [self deregisterForContentViewResizeNotifications];
- }
- - (void)windowDidFailToEnterFullScreen:(NSWindow*)window {
- [self deregisterForContentViewResizeNotifications];
- enteringFullscreen_ = NO;
- [self setPresentationModeInternal:NO forceDropdown:NO];
-
- // Force a relayout to try and get the window back into a reasonable state.
- [self layoutSubviews];
- }
- - (void)windowDidFailToExitFullScreen:(NSWindow*)window {
- [self deregisterForContentViewResizeNotifications];
-
- // Force a relayout to try and get the window back into a reasonable state.
- [self layoutSubviews];
- }
- #pragma mark -
- #pragma mark Presentation Mode
- - (BOOL)shouldShowPresentationModeToggle {
- return [self isFullscreen];
- }
- - (void)createAndInstallPresentationModeToggleButton {
- if (presentationModeToggleButton_)
- return;
-
- // TODO(rohitrao): Make this button prettier.
- presentationModeToggleButton_ = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 25, 25)];
- [presentationModeToggleButton_ setButtonType:NSMomentaryLightButton];
- [presentationModeToggleButton_ setBezelStyle:NSRegularSquareBezelStyle];
- [presentationModeToggleButton_ setBordered:NO];
- [[presentationModeToggleButton_ cell] setHighlightsBy:NSContentsCellMask];
- [[presentationModeToggleButton_ cell] setShowsStateBy:NSContentsCellMask];
- [presentationModeToggleButton_ setImage:[NSImage imageNamed:NSImageNameIChatTheaterTemplate]];
- [presentationModeToggleButton_ setTarget:self];
- [presentationModeToggleButton_ setAction:@selector(togglePresentationModeForLionOrLater:)];
- [[[[self window] contentView] superview] addSubview:presentationModeToggleButton_];
- }
- - (void)togglePresentationModeForLionOrLater:(id)sender {
- // Called only by the presentation mode toggle button.
- enteredPresentationModeFromFullscreen_ = YES;
- // browser_->ExecuteCommand(IDC_PRESENTATION_MODE);
- if ([self inPresentationMode])
- [self exitPresentationMode];
- else
- [self enterPresentationMode];
- // TODO: Post notification on WindowFullscreenStateChanged
- }
- // Adjust the UI when entering or leaving presentation mode. This method is
- // safe to call on all OS versions.
- - (void)adjustUIForPresentationMode:(BOOL)fullscreen {
- // Create the floating bar backing view if necessary.
- if (fullscreen && !floatingBarBackingView_ &&
- ([self hasTabStrip] || [self hasToolbar])) {
- floatingBarBackingView_ = [[CTFloatingBarBackingView alloc] initWithFrame:NSZeroRect];
- [floatingBarBackingView_ setAutoresizingMask:(NSViewWidthSizable |
- NSViewMinYMargin)];
- }
- }
- - (BOOL)isBarVisibilityLockedForOwner:(id)owner {
- DCHECK(owner);
- DCHECK(barVisibilityLocks_);
- return [barVisibilityLocks_ containsObject:owner];
- }
- - (void)enableBarVisibilityUpdates {
- // Early escape if there's nothing to do.
- if (barVisibilityUpdatesEnabled_)
- return;
-
- barVisibilityUpdatesEnabled_ = YES;
-
- if ([barVisibilityLocks_ count])
- [presentationModeController_ ensureOverlayShownWithAnimation:NO delay:NO];
- else
- [presentationModeController_ ensureOverlayHiddenWithAnimation:NO delay:NO];
- }
- - (void)disableBarVisibilityUpdates {
- // Early escape if there's nothing to do.
- if (!barVisibilityUpdatesEnabled_)
- return;
-
- barVisibilityUpdatesEnabled_ = NO;
- [presentationModeController_ cancelAnimationAndTimers];
- }
- - (void)lockBarVisibilityForOwner:(id)owner
- withAnimation:(BOOL)animate
- delay:(BOOL)delay {
- if (![self isBarVisibilityLockedForOwner:owner]) {
- [barVisibilityLocks_ addObject:owner];
-
- // If enabled, show the overlay if necessary (and if in presentation mode).
- if (barVisibilityUpdatesEnabled_) {
- [presentationModeController_ ensureOverlayShownWithAnimation:animate
- delay:delay];
- }
- }
- }
- - (void)releaseBarVisibilityForOwner:(id)owner
- withAnimation:(BOOL)animate
- delay:(BOOL)delay {
- if ([self isBarVisibilityLockedForOwner:owner]) {
- [barVisibilityLocks_ removeObject:owner];
-
- // If enabled, hide the overlay if necessary (and if in presentation mode).
- if (barVisibilityUpdatesEnabled_ &&
- ![barVisibilityLocks_ count]) {
- [presentationModeController_ ensureOverlayHiddenWithAnimation:animate
- delay:delay];
- }
- }
- }
- // On Lion, this function is called by either the presentation mode toggle
- // button or the "Enter Presentation Mode" menu item. In the latter case, this
- // function also triggers the Lion machinery to enter fullscreen mode as well as
- // set presentation mode. On Snow Leopard, this function is called by the
- // "Enter Presentation Mode" menu item, and triggering presentation mode always
- // moves the user into fullscreen mode.
- - (void)setPresentationMode:(BOOL)presentationMode {
- if (presentationMode) {
- BOOL fullscreen = [self isFullscreen];
-
- [self setShouldUsePresentationModeWhenEnteringFullscreen:YES];
- enteredPresentationModeFromFullscreen_ = fullscreen;
-
- if (fullscreen) {
- // If already in fullscreen mode, just toggle the presentation mode
- // setting. Go through an elaborate dance to force the overlay to show,
- // then animate out once the mouse moves away. This helps draw attention
- // to the fact that the UI is in an overlay. Focus the tab contents
- // because the omnibox is the most likely source of bar visibility locks,
- // and taking focus away from the omnibox releases its lock.
- [self lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
- [self focusTabContents];
- [self setPresentationModeInternal:YES forceDropdown:YES];
- [self releaseBarVisibilityForOwner:self withAnimation:YES delay:YES];
- } else {
- // If not in fullscreen mode, trigger the Lion fullscreen mode machinery.
- // Presentation mode will automatically be enabled in
- // |-windowWillEnterFullScreen:|.
- // NSWindow* window = [self window];
- // if ([window isKindOfClass:[CTBrowser class]])
- // [static_cast<FramedBrowserWindow*>(window) toggleSystemFullScreen];
- [[self window] toggleFullScreen:nil];
- }
- } else {
- if (enteredPresentationModeFromFullscreen_) {
- // The window is currently in fullscreen mode, but the user is choosing to
- // turn presentation mode off (choosing to always show the UI). Set the
- // preference to ensure that presentation mode will stay off for the next
- // window that goes fullscreen.
- [self setShouldUsePresentationModeWhenEnteringFullscreen:NO];
- [self setPresentationModeInternal:NO forceDropdown:NO];
- } else {
- // The user entered presentation mode directly from non-fullscreen mode
- // using the "Enter Presentation Mode" menu item and is using that same
- // menu item to exit presentation mode. In this case, exit fullscreen
- // mode as well (using the Lion machinery).
- // NSWindow* window = [self window];
- // if ([window isKindOfClass:[FramedBrowserWindow class]])
- // [static_cast<FramedBrowserWindow*>(window) toggleSystemFullScreen];
- [[self window] toggleFullScreen:nil];
- }
- }
- }
- - (void)setPresentationModeInternal:(BOOL)presentationMode
- forceDropdown:(BOOL)forceDropdown {
- if (presentationMode == [self inPresentationMode])
- return;
-
- if (presentationMode) {
- // BOOL showDropdown = forceDropdown || [self floatingBarHasFocus];
- BOOL showDropdown = forceDropdown;
- NSView* contentView = [[self window] contentView];
- presentationModeController_ = [[CTPresentationModeController alloc]
- initWithBrowserController:self];
- [presentationModeController_ enterPresentationModeForContentView:contentView
- showDropdown:showDropdown];
- } else {
- [presentationModeController_ exitPresentationMode];
- presentationModeController_ = nil;
- }
-
- [self adjustUIForPresentationMode:presentationMode];
- [self layoutSubviews];
- }
- - (void)enterPresentationMode {
- [self setPresentationMode:YES];
- }
- - (void)exitPresentationMode {
- [self setPresentationMode:NO];
- }
- - (BOOL)inPresentationMode {
- return presentationModeController_ && [presentationModeController_ inPresentationMode];
- }
- - (CGFloat)floatingBarShownFraction {
- return floatingBarShownFraction_;
- }
- - (void)setFloatingBarShownFraction:(CGFloat)fraction {
- floatingBarShownFraction_ = fraction;
- [self layoutSubviews];
- }
- @end
- @implementation CTBrowserWindowController (KMExtensions)
- - (void)appendBrowserWindowController:(__kindof CTBrowserWindowController *)browserWindowC toTabView:(NSView *)toTabView {
- if (!browserWindowC || [self isEqual:browserWindowC]) {
- return;
- }
-
- CTTabStripController *myTabStripC = self.tabStripController;
- CTTabView *targetTabView = (CTTabView *)toTabView;
- NSInteger toIndex = 0;
- if (!toTabView || ![toTabView isKindOfClass:[CTTabView class]]) {
- targetTabView = (CTTabView *)[myTabStripC activeTabView];
- }
- toIndex = [myTabStripC modelIndexForTabView:targetTabView] + 1;
- toIndex = MAX(toIndex, 0);
-
- CTTabStripController *tabStripC = browserWindowC.tabStripController;
- NSInteger tabViewCount = [tabStripC viewsCount];
- for (int i = 0; i < tabViewCount; i++) {
- CTTabView *tabView = (CTTabView *)[tabStripC viewAtIndex:tabViewCount-i-1];
- CTTabController *tabController = [tabView controller];
- if (tabController.isHome && !tabController.isNewTab) {
- continue;
- }
-
- [self km_moveTabView:tabView fromController:browserWindowC toIndex:toIndex];
- }
- }
- - (void)km_moveTabView:(NSView*)view fromController:(CTTabWindowController*)dragController toIndex:(NSInteger)toIndex {
- if (dragController) {
- // Moving between windows. Figure out the CTTabContents to drop into our tab
- // model from the source window's model.
- BOOL isBrowser =
- [dragController isKindOfClass:[CTBrowserWindowController class]];
- assert(isBrowser);
- if (!isBrowser) return;
- CTBrowserWindowController* dragBWC = (CTBrowserWindowController*)dragController;
- int index = [dragBWC->tabStripController_ modelIndexForTabView:view];
- CTTabContents* contents =
- [[dragBWC->browser_ tabStripModel] tabContentsAtIndex:index];
- // The tab contents may have gone away if given a window.close() while it
- // is being dragged. If so, bail, we've got nothing to drop.
- if (!contents)
- return;
-
- // Convert |view|'s frame (which starts in the source tab strip's coordinate
- // system) to the coordinate system of the destination tab strip. This needs
- // to be done before being detached so the window transforms can be
- // performed.
- NSRect destinationFrame = [view frame];
- NSPoint tabOrigin = destinationFrame.origin;
- tabOrigin = [[dragController tabStripView] convertPoint:tabOrigin
- toView:nil];
- tabOrigin = [[view window] convertBaseToScreen:tabOrigin];
- tabOrigin = [[self window] convertScreenToBase:tabOrigin];
- tabOrigin = [[self tabStripView] convertPoint:tabOrigin fromView:nil];
- if (tabOrigin.x <= [CTTabController homeTabWidth] + [CTTabStripController defaultIndentForControls]){
- tabOrigin.x = [CTTabController homeTabWidth] + [CTTabStripController defaultIndentForControls];
- }
- destinationFrame.origin = tabOrigin;
- // Before the tab is detached from its originating tab strip, store the
- // pinned state so that it can be maintained between the windows.
- BOOL isPinned = [[dragBWC->browser_ tabStripModel] isTabPinnedAtIndex:index];
-
- // Now that we have enough information about the tab, we can remove it from
- // the dragging window. We need to do this *before* we add it to the new
- // window as this will remove the CTTabContents' delegate.
- [dragController detachTabView:view];
-
- // Deposit it into our model at the appropriate location (it already knows
- // where it should go from tracking the drag). Doing this sets the tab's
- // delegate to be the CTBrowser.
- // [tabStripController_ dropTabContents:contents
- // withFrame:destinationFrame
- // asPinnedTab:isPinned];
- [tabStripController_ km_dropTabContents:contents withFrame:destinationFrame asPinnedTab:isPinned toIndex:toIndex];
- } else {
- // Moving within a window.
- int index = [tabStripController_ modelIndexForTabView:view];
- [tabStripController_ moveTabFromIndex:index];
- }
-
- // Remove the placeholder since the drag is now complete.
- [self removePlaceholder];
- }
- @end
|