BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / tabs / tab_window_controller.mm
blobe84f098b9b75da5fafae3eaff825763ba52c67b2
1 // Copyright (c) 2012 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.
5 #import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
7 #include "base/logging.h"
8 #import "chrome/browser/ui/cocoa/browser_window_layout.h"
9 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
10 #import "chrome/browser/ui/cocoa/framed_browser_window.h"
11 #import "chrome/browser/ui/cocoa/tabs/tab_strip_background_view.h"
12 #import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
13 #import "chrome/browser/ui/cocoa/themed_window.h"
14 #import "ui/base/cocoa/focus_tracker.h"
15 #include "ui/base/theme_provider.h"
17 @interface TabWindowController ()
18 - (void)setUseOverlay:(BOOL)useOverlay;
20 // The tab strip background view should always be inserted as the back-most
21 // subview of the root view. It cannot be a subview of the contentView, as that
22 // would cause it to become layer backed, which would cause it to draw on top
23 // of non-layer backed content like the window controls.
24 - (void)insertTabStripBackgroundViewIntoWindow:(NSWindow*)window;
25 @end
27 @interface TabWindowOverlayWindow : NSWindow
28 @end
30 @implementation TabWindowOverlayWindow
32 - (ui::ThemeProvider*)themeProvider {
33   if ([self parentWindow])
34     return [[[self parentWindow] windowController] themeProvider];
35   return NULL;
38 - (ThemedWindowStyle)themedWindowStyle {
39   if ([self parentWindow])
40     return [[[self parentWindow] windowController] themedWindowStyle];
41   return NO;
44 - (NSPoint)themeImagePositionForAlignment:(ThemeImageAlignment)alignment {
45   if ([self parentWindow]) {
46     return [[[self parentWindow] windowController]
47         themeImagePositionForAlignment:alignment];
48   }
49   return NSZeroPoint;
52 @end
54 @implementation TabWindowController
56 - (id)initTabWindowControllerWithTabStrip:(BOOL)hasTabStrip {
57   const CGFloat kDefaultWidth = 750;
58   const CGFloat kDefaultHeight = 600;
60   NSRect contentRect = NSMakeRect(60, 229, kDefaultWidth, kDefaultHeight);
61   base::scoped_nsobject<FramedBrowserWindow> window(
62       [[FramedBrowserWindow alloc] initWithContentRect:contentRect
63                                            hasTabStrip:hasTabStrip]);
64   [window setReleasedWhenClosed:YES];
65   [window setAutorecalculatesKeyViewLoop:YES];
67   if ((self = [super initWithWindow:window])) {
68     [[self window] setDelegate:self];
70     chromeContentView_.reset([[NSView alloc]
71         initWithFrame:NSMakeRect(0, 0, kDefaultWidth, kDefaultHeight)]);
72     [chromeContentView_
73         setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
74     [chromeContentView_ setWantsLayer:YES];
75     [[[self window] contentView] addSubview:chromeContentView_];
77     tabContentArea_.reset(
78         [[FastResizeView alloc] initWithFrame:[chromeContentView_ bounds]]);
79     [tabContentArea_ setAutoresizingMask:NSViewWidthSizable |
80                                          NSViewHeightSizable];
81     [chromeContentView_ addSubview:tabContentArea_];
83     // tabStripBackgroundView_ draws the theme image behind the tab strip area.
84     // When making a tab dragging window (setUseOverlay:), this view stays in
85     // the parent window so that it can be translucent, while the tab strip view
86     // moves to the child window and stays opaque.
87     NSView* windowView = [window contentView];
88     tabStripBackgroundView_.reset([[TabStripBackgroundView alloc]
89         initWithFrame:NSMakeRect(0,
90                                  NSMaxY([windowView bounds]) -
91                                      kBrowserFrameViewPaintHeight,
92                                  NSWidth([windowView bounds]),
93                                  kBrowserFrameViewPaintHeight)]);
94     [tabStripBackgroundView_
95         setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin];
96     [self insertTabStripBackgroundViewIntoWindow:window];
98     tabStripView_.reset([[TabStripView alloc]
99         initWithFrame:NSMakeRect(
100                           0, 0, kDefaultWidth, chrome::kTabStripHeight)]);
101     [tabStripView_ setAutoresizingMask:NSViewWidthSizable |
102                                        NSViewMinYMargin];
103     if (hasTabStrip)
104       [windowView addSubview:tabStripView_];
105   }
106   return self;
109 - (NSView*)tabStripBackgroundView {
110   return tabStripBackgroundView_;
113 - (TabStripView*)tabStripView {
114   return tabStripView_;
117 - (FastResizeView*)tabContentArea {
118   return tabContentArea_;
121 - (NSView*)chromeContentView {
122   return chromeContentView_;
125 - (void)removeOverlay {
126   [self setUseOverlay:NO];
127   if (closeDeferred_) {
128     // See comment in BrowserWindowCocoa::Close() about orderOut:.
129     [[self window] orderOut:self];
130     [[self window] performClose:self];  // Autoreleases the controller.
131   }
134 - (void)showOverlay {
135   [self setUseOverlay:YES];
138 // If |useOverlay| is YES, creates a new overlay window and puts the tab strip
139 // and the content area inside of it. This allows it to have a different opacity
140 // from the title bar. If NO, returns everything to the previous state and
141 // destroys the overlay window until it's needed again. The tab strip and window
142 // contents are returned to the original window.
143 - (void)setUseOverlay:(BOOL)useOverlay {
144   [NSObject cancelPreviousPerformRequestsWithTarget:self
145                                            selector:@selector(removeOverlay)
146                                              object:nil];
147   NSWindow* window = [self window];
148   if (useOverlay && !overlayWindow_) {
149     DCHECK(!originalContentView_);
151     overlayWindow_ = [[TabWindowOverlayWindow alloc]
152                          initWithContentRect:[window frame]
153                                    styleMask:NSBorderlessWindowMask
154                                      backing:NSBackingStoreBuffered
155                                        defer:NO];
156     [overlayWindow_ setTitle:@"overlay"];
157     [overlayWindow_ setBackgroundColor:[NSColor clearColor]];
158     [overlayWindow_ setOpaque:NO];
159     [overlayWindow_ setDelegate:self];
160     [[overlayWindow_ contentView] setWantsLayer:YES];
162     originalContentView_ = self.chromeContentView;
163     [window addChildWindow:overlayWindow_ ordered:NSWindowAbove];
165     // Explicitly set the responder to be nil here (for restoring later).
166     // If the first responder were to be left non-nil here then
167     // [RenderWidgethostViewCocoa resignFirstResponder] would be called,
168     // followed by RenderWidgetHost::Blur(), which would result in an unexpected
169     // loss of focus.
170     focusBeforeOverlay_.reset([[FocusTracker alloc] initWithWindow:window]);
171     [window makeFirstResponder:nil];
173     // Move the original window's tab strip view and content view to the overlay
174     // window. The content view is added as a subview of the overlay window's
175     // content view (rather than using setContentView:) because the overlay
176     // window has a different content size (due to it being borderless).
177     [[overlayWindow_ contentView] addSubview:[self tabStripView]];
178     [[overlayWindow_ contentView] addSubview:originalContentView_];
180     [overlayWindow_ orderFront:nil];
181   } else if (!useOverlay && overlayWindow_) {
182     DCHECK(originalContentView_);
184     // Return the original window's tab strip view and content view to their
185     // places. The TabStripView always needs to be in front of the window's
186     // content view and therefore it should always be added after the content
187     // view is set.
188     [[window contentView] addSubview:originalContentView_
189                           positioned:NSWindowBelow
190                           relativeTo:nil];
191     originalContentView_.frame = [[window contentView] bounds];
192     [[window contentView] addSubview:[self tabStripView]];
193     [[window contentView] updateTrackingAreas];
195     [focusBeforeOverlay_ restoreFocusInWindow:window];
196     focusBeforeOverlay_.reset();
198     [window display];
199     [window removeChildWindow:overlayWindow_];
201     [overlayWindow_ orderOut:nil];
202     [overlayWindow_ release];
203     overlayWindow_ = nil;
204     originalContentView_ = nil;
205   } else {
206     NOTREACHED();
207   }
210 - (NSWindow*)overlayWindow {
211   return overlayWindow_;
214 - (BOOL)shouldConstrainFrameRect {
215   // If we currently have an overlay window, do not attempt to change the
216   // window's size, as our overlay window doesn't know how to resize properly.
217   return overlayWindow_ == nil;
220 - (BOOL)canReceiveFrom:(TabWindowController*)source {
221   // subclass must implement
222   NOTIMPLEMENTED();
223   return NO;
226 - (void)moveTabViews:(NSArray*)views
227       fromController:(TabWindowController*)dragController {
228   NOTIMPLEMENTED();
231 - (NSArray*)tabViews {
232   NOTIMPLEMENTED();
233   return nil;
236 - (NSView*)activeTabView {
237   NOTIMPLEMENTED();
238   return nil;
241 - (void)layoutTabs {
242   // subclass must implement
243   NOTIMPLEMENTED();
246 - (TabWindowController*)detachTabsToNewWindow:(NSArray*)tabViews
247                                    draggedTab:(NSView*)draggedTab {
248   // subclass must implement
249   NOTIMPLEMENTED();
250   return NULL;
253 - (void)insertPlaceholderForTab:(TabView*)tab frame:(NSRect)frame {
254   [self showNewTabButton:NO];
257 - (void)removePlaceholder {
258   [self showNewTabButton:YES];
261 - (BOOL)isDragSessionActive {
262   NOTIMPLEMENTED();
263   return NO;
266 - (BOOL)tabDraggingAllowed {
267   return YES;
270 - (BOOL)tabTearingAllowed {
271   return YES;
274 - (BOOL)windowMovementAllowed {
275   return YES;
278 - (BOOL)isTabFullyVisible:(TabView*)tab {
279   // Subclasses should implement this, but it's not necessary.
280   return YES;
283 - (void)showNewTabButton:(BOOL)show {
284   // subclass must implement
285   NOTIMPLEMENTED();
288 - (void)detachTabView:(NSView*)view {
289   // subclass must implement
290   NOTIMPLEMENTED();
293 - (NSInteger)numberOfTabs {
294   // subclass must implement
295   NOTIMPLEMENTED();
296   return 0;
299 - (BOOL)hasLiveTabs {
300   // subclass must implement
301   NOTIMPLEMENTED();
302   return NO;
305 - (NSString*)activeTabTitle {
306   // subclass must implement
307   NOTIMPLEMENTED();
308   return @"";
311 - (BOOL)hasTabStrip {
312   // Subclasses should implement this.
313   NOTIMPLEMENTED();
314   return YES;
317 - (BOOL)isTabDraggable:(NSView*)tabView {
318   // Subclasses should implement this.
319   NOTIMPLEMENTED();
320   return YES;
323 // Tell the window that it needs to call performClose: as soon as the current
324 // drag is complete. This prevents a window (and its overlay) from going away
325 // during a drag.
326 - (void)deferPerformClose {
327   closeDeferred_ = YES;
330 - (void)insertTabStripBackgroundViewIntoWindow:(NSWindow*)window {
331   DCHECK(tabStripBackgroundView_);
332   NSView* rootView = [[window contentView] superview];
333   [rootView addSubview:tabStripBackgroundView_
334             positioned:NSWindowBelow
335             relativeTo:nil];
338 // Called when the size of the window content area has changed. Override to
339 // position specific views. Base class implementation does nothing.
340 - (void)layoutSubviews {
341   NOTIMPLEMENTED();
344 @end