Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Side by Side Diff: chrome/browser/cocoa/tab_view.mm

Issue 159780: Add support for constrained windows on os x, based on Avi's GTMWindowSheetController. (Closed)
Patch Set: Merge with ToT Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/cocoa/nsimage_cache.h" 5 #include "chrome/browser/cocoa/nsimage_cache.h"
6 #include "chrome/browser/cocoa/tab_controller.h" 6 #include "chrome/browser/cocoa/tab_controller.h"
7 #include "chrome/browser/cocoa/tab_view.h" 7 #include "chrome/browser/cocoa/tab_view.h"
8 #include "chrome/browser/cocoa/tab_window_controller.h" 8 #include "chrome/browser/cocoa/tab_window_controller.h"
9 9
10 10
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 // corners of the tab inset by height*2/3, so we inset by half of 79 // corners of the tab inset by height*2/3, so we inset by half of
80 // that here. This doesn't completely eliminate the overlap, but it 80 // that here. This doesn't completely eliminate the overlap, but it
81 // works well enough. 81 // works well enough.
82 NSRect hitRect = NSInsetRect(frame, frame.size.height / 3.0f, 0); 82 NSRect hitRect = NSInsetRect(frame, frame.size.height / 3.0f, 0);
83 if (![closeButton_ isHidden]) 83 if (![closeButton_ isHidden])
84 if (NSPointInRect(viewPoint, [closeButton_ frame])) return closeButton_; 84 if (NSPointInRect(viewPoint, [closeButton_ frame])) return closeButton_;
85 if (NSPointInRect(aPoint, hitRect)) return self; 85 if (NSPointInRect(aPoint, hitRect)) return self;
86 return nil; 86 return nil;
87 } 87 }
88 88
89 // Returns |YES| if this tab can be torn away into a new window.
90 - (BOOL)canBeDragged {
91 NSWindowController *controller = [sourceWindow_ windowController];
92 if ([controller isKindOfClass:[TabWindowController class]]) {
93 TabWindowController* realController =
94 static_cast<TabWindowController*>(controller);
95 return [realController isTabDraggable:self];
96 }
97 return YES;
98 }
99
89 // Handle clicks and drags in this button. We get here because we have 100 // Handle clicks and drags in this button. We get here because we have
90 // overridden acceptsFirstMouse: and the click is within our bounds. 101 // overridden acceptsFirstMouse: and the click is within our bounds.
91 // TODO(pinkerton/alcor): This routine needs *a lot* of work to marry Cole's 102 // TODO(pinkerton/alcor): This routine needs *a lot* of work to marry Cole's
92 // ideas of dragging cocoa views between windows and how the Browser and 103 // ideas of dragging cocoa views between windows and how the Browser and
93 // TabStrip models want to manage tabs. 104 // TabStrip models want to manage tabs.
94 105
95 static const CGFloat kTearDistance = 36.0; 106 static const CGFloat kTearDistance = 36.0;
96 static const NSTimeInterval kTearDuration = 0.333; 107 static const NSTimeInterval kTearDuration = 0.333;
97 static const double kDragStartDistance = 3.0; 108 static const double kDragStartDistance = 3.0;
98 109
(...skipping 18 matching lines...) Expand all
117 targetController_ = nil; 128 targetController_ = nil;
118 tabWasDragged_ = NO; 129 tabWasDragged_ = NO;
119 tearTime_ = 0.0; 130 tearTime_ = 0.0;
120 draggingWithinTabStrip_ = YES; 131 draggingWithinTabStrip_ = YES;
121 132
122 // We don't want to "tear off" a tab if there's only one in the window. Treat 133 // We don't want to "tear off" a tab if there's only one in the window. Treat
123 // it like we're dragging around a tab we've already detached. Note that 134 // it like we're dragging around a tab we've already detached. Note that
124 // unit tests might have |-numberOfTabs| reporting zero since the model 135 // unit tests might have |-numberOfTabs| reporting zero since the model
125 // won't be fully hooked up. We need to be prepared for that and not send 136 // won't be fully hooked up. We need to be prepared for that and not send
126 // them into the "magnetic" codepath. 137 // them into the "magnetic" codepath.
127 isTheOnlyTab_ = [sourceController_ numberOfTabs] <= 1; 138 moveWindowOnDrag_ =
139 [sourceController_ numberOfTabs] <= 1 || ![self canBeDragged];
128 140
129 dragOrigin_ = [NSEvent mouseLocation]; 141 dragOrigin_ = [NSEvent mouseLocation];
130 142
131 // Because we move views between windows, we need to handle the event loop 143 // Because we move views between windows, we need to handle the event loop
132 // ourselves. Ideally we should use the standard event loop. 144 // ourselves. Ideally we should use the standard event loop.
133 while (1) { 145 while (1) {
134 theEvent = 146 theEvent =
135 [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask 147 [NSApp nextEventMatchingMask:NSLeftMouseUpMask | NSLeftMouseDraggedMask
136 untilDate:[NSDate distantFuture] 148 untilDate:[NSDate distantFuture]
137 inMode:NSDefaultRunLoopMode dequeue:YES]; 149 inMode:NSDefaultRunLoopMode dequeue:YES];
138 NSPoint thisPoint = [NSEvent mouseLocation]; 150 NSPoint thisPoint = [NSEvent mouseLocation];
139 151
140 NSEventType type = [theEvent type]; 152 NSEventType type = [theEvent type];
141 if (type == NSLeftMouseDragged) { 153 if (type == NSLeftMouseDragged) {
142 [self mouseDragged:theEvent]; 154 [self mouseDragged:theEvent];
143 } else { // Mouse Up 155 } else { // Mouse Up
144 [self mouseUp:theEvent]; 156 [self mouseUp:theEvent];
145 break; 157 break;
146 } 158 }
147 } 159 }
148 } 160 }
149 161
150 - (void)mouseDragged:(NSEvent *)theEvent { 162 - (void)mouseDragged:(NSEvent *)theEvent {
163 // Special-case this to keep the logic below simpler.
164 if (moveWindowOnDrag_) {
165 NSPoint thisPoint = [NSEvent mouseLocation];
166 NSPoint origin = sourceWindowFrame_.origin;
167 origin.x += (thisPoint.x - dragOrigin_.x);
168 origin.y += (thisPoint.y - dragOrigin_.y);
169 [sourceWindow_ setFrameOrigin:NSMakePoint(origin.x, origin.y)];
170 return;
171 }
172
151 // First, go through the magnetic drag cycle. We break out of this if 173 // First, go through the magnetic drag cycle. We break out of this if
152 // "stretchiness" ever exceeds the a set amount. 174 // "stretchiness" ever exceeds a set amount.
153 tabWasDragged_ = YES; 175 tabWasDragged_ = YES;
154 176
155 if (isTheOnlyTab_) draggingWithinTabStrip_ = NO;
156 if (draggingWithinTabStrip_) { 177 if (draggingWithinTabStrip_) {
157 NSRect frame = [self frame]; 178 NSRect frame = [self frame];
158 NSPoint thisPoint = [NSEvent mouseLocation]; 179 NSPoint thisPoint = [NSEvent mouseLocation];
159 CGFloat stretchiness = thisPoint.y - dragOrigin_.y; 180 CGFloat stretchiness = thisPoint.y - dragOrigin_.y;
160 stretchiness = copysign(sqrtf(fabs(stretchiness))/sqrtf(kTearDistance), 181 stretchiness = copysign(sqrtf(fabs(stretchiness))/sqrtf(kTearDistance),
161 stretchiness) / 2.0; 182 stretchiness) / 2.0;
162 CGFloat offset = thisPoint.x - dragOrigin_.x; 183 CGFloat offset = thisPoint.x - dragOrigin_.x;
163 if (fabsf(offset) > 100) stretchiness = 0; 184 if (fabsf(offset) > 100) stretchiness = 0;
164 [sourceController_ insertPlaceholderForTab:self 185 [sourceController_ insertPlaceholderForTab:self
165 frame:NSOffsetRect(sourceTabFrame_, 186 frame:NSOffsetRect(sourceTabFrame_,
(...skipping 17 matching lines...) Expand all
183 // moving more than 3 pixels. 204 // moving more than 3 pixels.
184 NSDate* targetDwellDate = nil; // The date this target was first chosen 205 NSDate* targetDwellDate = nil; // The date this target was first chosen
185 NSMutableArray* targets = [NSMutableArray array]; 206 NSMutableArray* targets = [NSMutableArray array];
186 207
187 NSPoint thisPoint = [NSEvent mouseLocation]; 208 NSPoint thisPoint = [NSEvent mouseLocation];
188 209
189 // Find all the windows that could be a target. It has to be of the 210 // Find all the windows that could be a target. It has to be of the
190 // appropriate class, and visible (obviously). 211 // appropriate class, and visible (obviously).
191 if (![targets count]) { 212 if (![targets count]) {
192 for (NSWindow* window in [NSApp windows]) { 213 for (NSWindow* window in [NSApp windows]) {
193 if (window == sourceWindow_ && isTheOnlyTab_) continue;
194 if (window == dragWindow_) continue; 214 if (window == dragWindow_) continue;
195 if (![window isVisible]) continue; 215 if (![window isVisible]) continue;
196 NSWindowController *controller = [window windowController]; 216 NSWindowController *controller = [window windowController];
197 if ([controller isKindOfClass:[TabWindowController class]]) { 217 if ([controller isKindOfClass:[TabWindowController class]]) {
198 TabWindowController* realController = 218 TabWindowController* realController =
199 static_cast<TabWindowController*>(controller); 219 static_cast<TabWindowController*>(controller);
200 if ([realController canReceiveFrom:sourceController_]) { 220 if ([realController canReceiveFrom:sourceController_]) {
201 [targets addObject:controller]; 221 [targets addObject:controller];
202 } 222 }
203 } 223 }
(...skipping 24 matching lines...) Expand all
228 [targetController_ removePlaceholder]; 248 [targetController_ removePlaceholder];
229 targetController_ = newTarget; 249 targetController_ = newTarget;
230 if (!newTarget) { 250 if (!newTarget) {
231 tearTime_ = [NSDate timeIntervalSinceReferenceDate]; 251 tearTime_ = [NSDate timeIntervalSinceReferenceDate];
232 tearOrigin_ = [dragWindow_ frame].origin; 252 tearOrigin_ = [dragWindow_ frame].origin;
233 } 253 }
234 } 254 }
235 255
236 // Create or identify the dragged controller. 256 // Create or identify the dragged controller.
237 if (!draggedController_) { 257 if (!draggedController_) {
238 if (isTheOnlyTab_) { 258 // Detach from the current window and put it in a new window.
239 draggedController_ = sourceController_; 259 draggedController_ = [sourceController_ detachTabToNewWindow:self];
240 dragWindow_ = [draggedController_ window]; 260 dragWindow_ = [draggedController_ window];
241 } else { 261 [dragWindow_ setAlphaValue:0.0];
242 // Detach from the current window and put it in a new window.
243 draggedController_ = [sourceController_ detachTabToNewWindow:self];
244 dragWindow_ = [draggedController_ window];
245 [dragWindow_ setAlphaValue:0.0];
246 }
247 262
263 // If dragging the tab only moves the current window, do not show overlay
264 // so that sheets stay on top of the window.
248 // Bring the target window to the front and make sure it has a border. 265 // Bring the target window to the front and make sure it has a border.
249 [dragWindow_ setLevel:NSFloatingWindowLevel]; 266 [dragWindow_ setLevel:NSFloatingWindowLevel];
250 [dragWindow_ orderFront:nil]; 267 [dragWindow_ orderFront:nil];
251 [dragWindow_ makeMainWindow]; 268 [dragWindow_ makeMainWindow];
252 [draggedController_ showOverlay]; 269 [draggedController_ showOverlay];
253 dragOverlay_ = [draggedController_ overlayWindow]; 270 dragOverlay_ = [draggedController_ overlayWindow];
254 // Force the new tab button to be hidden. We'll reset it on mouse up. 271 // Force the new tab button to be hidden. We'll reset it on mouse up.
255 [draggedController_ showNewTabButton:NO]; 272 [draggedController_ showNewTabButton:NO];
256 //if (![targets count]) 273 //if (![targets count])
257 // [dragOverlay_ setHasShadow:NO]; 274 // [dragOverlay_ setHasShadow:NO];
258 if (!isTheOnlyTab_) { 275 tearTime_ = [NSDate timeIntervalSinceReferenceDate];
259 tearTime_ = [NSDate timeIntervalSinceReferenceDate]; 276 tearOrigin_ = sourceWindowFrame_.origin;
260 tearOrigin_ = sourceWindowFrame_.origin;
261 }
262 } 277 }
263 278
264 float tearProgress = [NSDate timeIntervalSinceReferenceDate] - tearTime_; 279 float tearProgress = [NSDate timeIntervalSinceReferenceDate] - tearTime_;
265 tearProgress /= kTearDuration; 280 tearProgress /= kTearDuration;
266 tearProgress = sqrtf(MAX(MIN(tearProgress, 1.0), 0.0)); 281 tearProgress = sqrtf(MAX(MIN(tearProgress, 1.0), 0.0));
267 282
268 // Move the dragged window to the right place on the screen. 283 // Move the dragged window to the right place on the screen.
269 NSPoint origin = sourceWindowFrame_.origin; 284 NSPoint origin = sourceWindowFrame_.origin;
270 origin.x += (thisPoint.x - dragOrigin_.x); 285 origin.x += (thisPoint.x - dragOrigin_.x);
271 origin.y += (thisPoint.y - dragOrigin_.y); 286 origin.y += (thisPoint.y - dragOrigin_.y);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 [[dragWindow_ animator] setAlphaValue:0.5]; 356 [[dragWindow_ animator] setAlphaValue:0.5];
342 } 357 }
343 chromeIsVisible_ = chromeShouldBeVisible; 358 chromeIsVisible_ = chromeShouldBeVisible;
344 } 359 }
345 } 360 }
346 361
347 - (void)mouseUp:(NSEvent *)theEvent { 362 - (void)mouseUp:(NSEvent *)theEvent {
348 // The drag/click is done. If the user dragged the mouse, finalize the drag 363 // The drag/click is done. If the user dragged the mouse, finalize the drag
349 // and clean up. 364 // and clean up.
350 365
366 // Special-case this to keep the logic below simpler.
367 if (moveWindowOnDrag_)
368 return;
369
351 // We are now free to re-display the new tab button in the window we're 370 // We are now free to re-display the new tab button in the window we're
352 // dragging. It will show when the next call to -layoutTabs (which happens 371 // dragging. It will show when the next call to -layoutTabs (which happens
353 // indrectly by several of the calls below, such as removing the placeholder). 372 // indrectly by several of the calls below, such as removing the placeholder).
354 [draggedController_ showNewTabButton:YES]; 373 [draggedController_ showNewTabButton:YES];
355 374
356 if (draggingWithinTabStrip_) { 375 if (draggingWithinTabStrip_) {
357 if (tabWasDragged_) { 376 if (tabWasDragged_) {
358 // Move tab to new location. 377 // Move tab to new location.
359 TabWindowController* dropController = sourceController_; 378 TabWindowController* dropController = sourceController_;
360 [dropController moveTabView:[dropController selectedTabView] 379 [dropController moveTabView:[dropController selectedTabView]
361 fromController:nil]; 380 fromController:nil];
362 } 381 }
363 } else if (targetController_) { 382 } else if (targetController_) {
364 // Move between windows. If |targetController_| is nil, we're not dropping 383 // Move between windows. If |targetController_| is nil, we're not dropping
365 // into any existing window. 384 // into any existing window.
366 NSView* draggedTabView = [draggedController_ selectedTabView]; 385 NSView* draggedTabView = [draggedController_ selectedTabView];
367 [draggedController_ removeOverlay]; 386 [draggedController_ removeOverlay];
368 [targetController_ moveTabView:draggedTabView 387 [targetController_ moveTabView:draggedTabView
369 fromController:draggedController_]; 388 fromController:draggedController_];
370 [targetController_ showWindow:nil]; 389 [targetController_ showWindow:nil];
371 } else { 390 } else {
391 // Tab dragging did move window only.
372 [dragWindow_ setAlphaValue:1.0]; 392 [dragWindow_ setAlphaValue:1.0];
373 [dragOverlay_ setHasShadow:NO]; 393 [dragOverlay_ setHasShadow:NO];
374 [dragWindow_ setHasShadow:YES]; 394 [dragWindow_ setHasShadow:YES];
375 [draggedController_ removeOverlay]; 395 [draggedController_ removeOverlay];
376 [dragWindow_ makeKeyAndOrderFront:nil]; 396 [dragWindow_ makeKeyAndOrderFront:nil];
377 397
378 [[draggedController_ window] setLevel:NSNormalWindowLevel]; 398 [[draggedController_ window] setLevel:NSNormalWindowLevel];
379 [draggedController_ removePlaceholder]; 399 [draggedController_ removePlaceholder];
380 } 400 }
381 [sourceController_ removePlaceholder]; 401 [sourceController_ removePlaceholder];
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 [[NSGraphicsContext currentContext] restoreGraphicsState]; 524 [[NSGraphicsContext currentContext] restoreGraphicsState];
505 } 525 }
506 526
507 // Called when the user hits the right mouse button (or control-clicks) to 527 // Called when the user hits the right mouse button (or control-clicks) to
508 // show a context menu. 528 // show a context menu.
509 - (void)rightMouseDown:(NSEvent*)theEvent { 529 - (void)rightMouseDown:(NSEvent*)theEvent {
510 [NSMenu popUpContextMenu:[self menu] withEvent:theEvent forView:self]; 530 [NSMenu popUpContextMenu:[self menu] withEvent:theEvent forView:self];
511 } 531 }
512 532
513 @end 533 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698