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

Side by Side Diff: chrome/browser/ui/cocoa/browser_window_controller.mm

Issue 157403004: [mac] Implement dragging of multiple tabs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 10 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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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 #import "chrome/browser/ui/cocoa/browser_window_controller.h" 5 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <numeric> 8 #include <numeric>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 1269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 return YES; 1280 return YES;
1281 } 1281 }
1282 1282
1283 // Move a given tab view to the location of the current placeholder. If there is 1283 // Move a given tab view to the location of the current placeholder. If there is
1284 // no placeholder, it will go at the end. |controller| is the window controller 1284 // no placeholder, it will go at the end. |controller| is the window controller
1285 // of a tab being dropped from a different window. It will be nil if the drag is 1285 // of a tab being dropped from a different window. It will be nil if the drag is
1286 // within the window, otherwise the tab is removed from that window before being 1286 // within the window, otherwise the tab is removed from that window before being
1287 // placed into this one. The implementation will call |-removePlaceholder| since 1287 // placed into this one. The implementation will call |-removePlaceholder| since
1288 // the drag is now complete. This also calls |-layoutTabs| internally so 1288 // the drag is now complete. This also calls |-layoutTabs| internally so
1289 // clients do not need to call it again. 1289 // clients do not need to call it again.
1290 - (void)moveTabView:(NSView*)view 1290 - (void)moveTabViews:(NSArray*)views
1291 fromController:(TabWindowController*)dragController { 1291 fromController:(TabWindowController*)dragController {
1292 if (dragController) { 1292 if (dragController) {
1293 // Moving between windows. Figure out the WebContents to drop into our tab 1293 NSView* activeTabView = [dragController activeTabView];
Robert Sesek 2014/02/24 15:25:20 I'd maybe keep the comment about "Moving between w
Andre 2014/02/25 01:16:16 Done.
1294 // model from the source window's model.
1295 BrowserWindowController* dragBWC = 1294 BrowserWindowController* dragBWC =
1296 base::mac::ObjCCastStrict<BrowserWindowController>(dragController); 1295 base::mac::ObjCCastStrict<BrowserWindowController>(dragController);
1297 int index = [dragBWC->tabStripController_ modelIndexForTabView:view];
1298 WebContents* contents =
1299 dragBWC->browser_->tab_strip_model()->GetWebContentsAt(index);
1300 // The tab contents may have gone away if given a window.close() while it
1301 // is being dragged. If so, bail, we've got nothing to drop.
1302 if (!contents)
1303 return;
1304 1296
1305 // Convert |view|'s frame (which starts in the source tab strip's coordinate 1297 // We will drop the tabs starting at indexOfPlaceholder, and increment from
1306 // system) to the coordinate system of the destination tab strip. This needs 1298 // there. We remove the placehoder before dropping the tabs, so that the
1307 // to be done before being detached so the window transforms can be 1299 // new tab animation's destination frame is correct.
1308 // performed. 1300 int tabIndex = [tabStripController_ indexOfPlaceholder];
1309 NSRect destinationFrame = [view frame]; 1301 [self removePlaceholder];
1310 NSPoint tabOrigin = destinationFrame.origin;
1311 tabOrigin = [[dragController tabStripView] convertPoint:tabOrigin
1312 toView:nil];
1313 tabOrigin = [[view window] convertBaseToScreen:tabOrigin];
1314 tabOrigin = [[self window] convertScreenToBase:tabOrigin];
1315 tabOrigin = [[self tabStripView] convertPoint:tabOrigin fromView:nil];
1316 destinationFrame.origin = tabOrigin;
1317 1302
1318 // Before the tab is detached from its originating tab strip, store the 1303 for (NSView* view in views) {
1319 // pinned state so that it can be maintained between the windows. 1304 // Moving between windows. Figure out the WebContents to drop into our tab
1320 bool isPinned = dragBWC->browser_->tab_strip_model()->IsTabPinned(index); 1305 // model from the source window's model.
1306 int index = [dragBWC->tabStripController_ modelIndexForTabView:view];
1307 WebContents* contents =
1308 dragBWC->browser_->tab_strip_model()->GetWebContentsAt(index);
1309 // The tab contents may have gone away if given a window.close() while it
1310 // is being dragged. If so, bail, we've got nothing to drop.
1311 if (!contents)
1312 continue;
1321 1313
1322 // Now that we have enough information about the tab, we can remove it from 1314 // Convert |view|'s frame (which starts in the source tab strip's
1323 // the dragging window. We need to do this *before* we add it to the new 1315 // coordinate system) to the coordinate system of the destination tab
1324 // window as this will remove the WebContents' delegate. 1316 // strip. This needs to be done before being detached so the window
1325 [dragController detachTabView:view]; 1317 // transforms can be performed.
1318 NSRect destinationFrame = [view frame];
1319 NSPoint tabOrigin = destinationFrame.origin;
1320 tabOrigin = [[dragController tabStripView] convertPoint:tabOrigin
1321 toView:nil];
1322 tabOrigin = [[dragController window] convertBaseToScreen:tabOrigin];
Andre 2014/02/20 23:05:26 Changed from [view window] to [dragController wind
1323 tabOrigin = [[self window] convertScreenToBase:tabOrigin];
1324 tabOrigin = [[self tabStripView] convertPoint:tabOrigin fromView:nil];
1325 destinationFrame.origin = tabOrigin;
1326 1326
1327 // Deposit it into our model at the appropriate location (it already knows 1327 // Before the tab is detached from its originating tab strip, store the
1328 // where it should go from tracking the drag). Doing this sets the tab's 1328 // pinned state so that it can be maintained between the windows.
1329 // delegate to be the Browser. 1329 bool isPinned = dragBWC->browser_->tab_strip_model()->IsTabPinned(index);
1330 [tabStripController_ dropWebContents:contents 1330
1331 withFrame:destinationFrame 1331 // Now that we have enough information about the tab, we can remove it
1332 asPinnedTab:isPinned]; 1332 // from the dragging window. We need to do this *before* we add it to the
1333 // new window as this will remove the WebContents' delegate.
1334 [dragController detachTabView:view];
1335
1336 // Deposit it into our model at the appropriate location (it already knows
1337 // where it should go from tracking the drag). Doing this sets the tab's
1338 // delegate to be the Browser.
1339 [tabStripController_ dropWebContents:contents
1340 atIndex:tabIndex++
1341 withFrame:destinationFrame
1342 asPinnedTab:isPinned
1343 activate:view == activeTabView];
1344 }
1333 } else { 1345 } else {
1334 // Moving within a window. 1346 // Moving within a window.
1335 int index = [tabStripController_ modelIndexForTabView:view]; 1347 for (NSView* view in views) {
1336 [tabStripController_ moveTabFromIndex:index]; 1348 int index = [tabStripController_ modelIndexForTabView:view];
1349 [tabStripController_ moveTabFromIndex:index];
1350 }
1351 [self removePlaceholder];
1337 } 1352 }
1338
1339 // Remove the placeholder since the drag is now complete.
1340 [self removePlaceholder];
1341 } 1353 }
1342 1354
1343 // Tells the tab strip to forget about this tab in preparation for it being 1355 // Tells the tab strip to forget about this tab in preparation for it being
1344 // put into a different tab strip, such as during a drop on another window. 1356 // put into a different tab strip, such as during a drop on another window.
1345 - (void)detachTabView:(NSView*)view { 1357 - (void)detachTabView:(NSView*)view {
1346 int index = [tabStripController_ modelIndexForTabView:view]; 1358 int index = [tabStripController_ modelIndexForTabView:view];
1347 browser_->tab_strip_model()->DetachWebContentsAt(index); 1359 browser_->tab_strip_model()->DetachWebContentsAt(index);
1348 } 1360 }
1349 1361
1362 - (NSArray*)tabViews {
1363 return [tabStripController_ tabViews];
1364 }
1365
1350 - (NSView*)activeTabView { 1366 - (NSView*)activeTabView {
1351 return [tabStripController_ activeTabView]; 1367 return [tabStripController_ activeTabView];
1352 } 1368 }
1353 1369
1354 - (void)setIsLoading:(BOOL)isLoading force:(BOOL)force { 1370 - (void)setIsLoading:(BOOL)isLoading force:(BOOL)force {
1355 [toolbarController_ setIsLoading:isLoading force:force]; 1371 [toolbarController_ setIsLoading:isLoading force:force];
1356 } 1372 }
1357 1373
1358 // Make the location bar the first responder, if possible. 1374 // Make the location bar the first responder, if possible.
1359 - (void)focusLocationBar:(BOOL)selectAll { 1375 - (void)focusLocationBar:(BOOL)selectAll {
1360 [toolbarController_ focusLocationBar:selectAll]; 1376 [toolbarController_ focusLocationBar:selectAll];
1361 } 1377 }
1362 1378
1363 - (void)focusTabContents { 1379 - (void)focusTabContents {
1364 [[self window] makeFirstResponder:[tabStripController_ activeTabView]]; 1380 [[self window] makeFirstResponder:[tabStripController_ activeTabView]];
1365 } 1381 }
1366 1382
1367 - (void)layoutTabs { 1383 - (void)layoutTabs {
1368 [tabStripController_ layoutTabs]; 1384 [tabStripController_ layoutTabs];
1369 } 1385 }
1370 1386
1371 - (TabWindowController*)detachTabToNewWindow:(TabView*)tabView { 1387 - (TabWindowController*)detachTabsToNewWindow:(NSArray*)tabViews
1388 draggedTab:(NSView*)draggedTab {
1389 DCHECK([tabViews count] > 0);
Robert Sesek 2014/02/24 15:25:20 DCHECK_GT
Andre 2014/02/25 01:16:16 Done.
1390
1372 // Disable screen updates so that this appears as a single visual change. 1391 // Disable screen updates so that this appears as a single visual change.
1373 gfx::ScopedNSDisableScreenUpdates disabler; 1392 gfx::ScopedNSDisableScreenUpdates disabler;
1374 1393
1375 // Fetch the tab contents for the tab being dragged.
1376 int index = [tabStripController_ modelIndexForTabView:tabView];
1377 WebContents* contents = browser_->tab_strip_model()->GetWebContentsAt(index);
1378
1379 // Set the window size. Need to do this before we detach the tab so it's 1394 // Set the window size. Need to do this before we detach the tab so it's
1380 // still in the window. We have to flip the coordinates as that's what 1395 // still in the window. We have to flip the coordinates as that's what
1381 // is expected by the Browser code. 1396 // is expected by the Browser code.
1382 NSWindow* sourceWindow = [tabView window]; 1397 NSWindow* sourceWindow = [draggedTab window];
1383 NSRect windowRect = [sourceWindow frame]; 1398 NSRect windowRect = [sourceWindow frame];
1384 NSScreen* screen = [sourceWindow screen]; 1399 NSScreen* screen = [sourceWindow screen];
1385 windowRect.origin.y = NSHeight([screen frame]) - NSMaxY(windowRect); 1400 windowRect.origin.y = NSHeight([screen frame]) - NSMaxY(windowRect);
1386 gfx::Rect browserRect(windowRect.origin.x, windowRect.origin.y, 1401 gfx::Rect browserRect(windowRect.origin.x, windowRect.origin.y,
1387 NSWidth(windowRect), NSHeight(windowRect)); 1402 NSWidth(windowRect), NSHeight(windowRect));
1388 1403
1389 NSRect sourceTabRect = [tabView frame]; 1404 std::vector<TabStripModelDelegate::NewStripContents> contentses;
1390 NSView* tabStrip = [self tabStripView]; 1405 TabStripModel* model = browser_->tab_strip_model();
1391 1406
1392 // Pushes tabView's frame back inside the tabstrip. 1407 for (TabView* tabView in tabViews) {
1393 NSSize tabOverflow = 1408 // Fetch the tab contents for the tab being dragged.
1394 [self overflowFrom:[tabStrip convertRect:sourceTabRect toView:nil] 1409 int index = [tabStripController_ modelIndexForTabView:tabView];
1395 to:[tabStrip frame]]; 1410 bool isPinned = model->IsTabPinned(index);
1396 NSRect tabRect = NSOffsetRect(sourceTabRect, 1411 bool isActive = (index == model->active_index());
1397 -tabOverflow.width, -tabOverflow.height);
1398 1412
1399 // Before detaching the tab, store the pinned state. 1413 TabStripModelDelegate::NewStripContents item;
1400 bool isPinned = browser_->tab_strip_model()->IsTabPinned(index); 1414 item.web_contents = model->GetWebContentsAt(index);
1415 item.add_types =
1416 (isActive ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE) |
1417 (isPinned ? TabStripModel::ADD_PINNED : TabStripModel::ADD_NONE);
1418 contentses.push_back(item);
1419 }
1401 1420
1402 // Detach it from the source window, which just updates the model without 1421 for (TabView* tabView in tabViews) {
1403 // deleting the tab contents. This needs to come before creating the new 1422 int index = [tabStripController_ modelIndexForTabView:tabView];
1404 // Browser because it clears the WebContents' delegate, which gets hooked 1423 // Detach it from the source window, which just updates the model without
1405 // up during creation of the new window. 1424 // deleting the tab contents. This needs to come before creating the new
1406 browser_->tab_strip_model()->DetachWebContentsAt(index); 1425 // Browser because it clears the WebContents' delegate, which gets hooked
1426 // up during creation of the new window.
1427 model->DetachWebContentsAt(index);
1428 }
1407 1429
1408 // Create the new window with a single tab in its model, the one being 1430 // Create the new window with a single tab in its model, the one being
Robert Sesek 2014/02/24 15:25:20 No longer just a "single tab" :)
Andre 2014/02/25 01:16:16 Done.
1409 // dragged. 1431 // dragged.
1410 DockInfo dockInfo; 1432 DockInfo dockInfo;
1411 TabStripModelDelegate::NewStripContents item; 1433 Browser* newBrowser = model->delegate()->CreateNewStripWithContents(
1412 item.web_contents = contents; 1434 contentses, browserRect, dockInfo, false);
1413 item.add_types = TabStripModel::ADD_ACTIVE |
1414 (isPinned ? TabStripModel::ADD_PINNED
1415 : TabStripModel::ADD_NONE);
1416 std::vector<TabStripModelDelegate::NewStripContents> contentses;
1417 contentses.push_back(item);
1418 Browser* newBrowser = browser_->tab_strip_model()->delegate()->
1419 CreateNewStripWithContents(contentses, browserRect, dockInfo, false);
1420 1435
1421 // Get the new controller by asking the new window for its delegate. 1436 // Get the new controller by asking the new window for its delegate.
1422 BrowserWindowController* controller = 1437 BrowserWindowController* controller =
1423 reinterpret_cast<BrowserWindowController*>( 1438 reinterpret_cast<BrowserWindowController*>(
1424 [newBrowser->window()->GetNativeWindow() delegate]); 1439 [newBrowser->window()->GetNativeWindow() delegate]);
1425 DCHECK(controller && [controller isKindOfClass:[TabWindowController class]]); 1440 DCHECK(controller && [controller isKindOfClass:[TabWindowController class]]);
1426 1441
1427 // Force the added tab to the right size (remove stretching.) 1442 // And make sure we use the correct frame in the new view.
1428 tabRect.size.height = [TabStripController defaultTabHeight]; 1443 TabStripController* tabStripController = [controller tabStripController];
1444 NSView* tabStrip = [self tabStripView];
1445 NSEnumerator* tabEnumerator = [tabViews objectEnumerator];
1446 for (NSView* newView in [tabStripController tabViews]) {
1447 NSView* oldView = [tabEnumerator nextObject];
1448 if (oldView) {
1449 // Pushes tabView's frame back inside the tabstrip.
1450 NSRect sourceTabRect = [oldView frame];
1451 NSSize tabOverflow =
1452 [self overflowFrom:[tabStrip convertRect:sourceTabRect toView:nil]
1453 to:[tabStrip frame]];
1454 NSRect tabRect =
1455 NSOffsetRect(sourceTabRect, -tabOverflow.width, -tabOverflow.height);
1456 // Force the added tab to the right size (remove stretching.)
1457 tabRect.size.height = [TabStripController defaultTabHeight];
1429 1458
1430 // And make sure we use the correct frame in the new view. 1459 [tabStripController setFrame:tabRect ofTabView:newView];
1431 [[controller tabStripController] setFrameOfActiveTab:tabRect]; 1460 }
1461 }
1462
1432 return controller; 1463 return controller;
1433 } 1464 }
1434 1465
1435 - (void)insertPlaceholderForTab:(TabView*)tab 1466 - (void)insertPlaceholderForTab:(TabView*)tab
1436 frame:(NSRect)frame { 1467 frame:(NSRect)frame {
1437 [super insertPlaceholderForTab:tab frame:frame]; 1468 [super insertPlaceholderForTab:tab frame:frame];
1438 [tabStripController_ insertPlaceholderForTab:tab frame:frame]; 1469 [tabStripController_ insertPlaceholderForTab:tab frame:frame];
1439 } 1470 }
1440 1471
1441 - (void)removePlaceholder { 1472 - (void)removePlaceholder {
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 2220
2190 - (BOOL)supportsBookmarkBar { 2221 - (BOOL)supportsBookmarkBar {
2191 return [self supportsWindowFeature:Browser::FEATURE_BOOKMARKBAR]; 2222 return [self supportsWindowFeature:Browser::FEATURE_BOOKMARKBAR];
2192 } 2223 }
2193 2224
2194 - (BOOL)isTabbedWindow { 2225 - (BOOL)isTabbedWindow {
2195 return browser_->is_type_tabbed(); 2226 return browser_->is_type_tabbed();
2196 } 2227 }
2197 2228
2198 @end // @implementation BrowserWindowController(WindowType) 2229 @end // @implementation BrowserWindowController(WindowType)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698