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