| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/bookmarks/bookmark_bar_folder_controller.h" | 5 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_folder_controller.h" |
| 6 | 6 |
| 7 #include "base/mac/bundle_locations.h" | 7 #include "base/mac/bundle_locations.h" |
| 8 #include "base/strings/sys_string_conversions.h" | 8 #include "base/strings/sys_string_conversions.h" |
| 9 #import "chrome/browser/bookmarks/bookmark_model_factory.h" | 9 #import "chrome/browser/bookmarks/bookmark_model_factory.h" |
| 10 #import "chrome/browser/bookmarks/chrome_bookmark_client.h" | 10 #import "chrome/browser/bookmarks/chrome_bookmark_client.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 } | 122 } |
| 123 | 123 |
| 124 } // namespace | 124 } // namespace |
| 125 | 125 |
| 126 | 126 |
| 127 // Required to set the right tracking bounds for our fake menus. | 127 // Required to set the right tracking bounds for our fake menus. |
| 128 @interface NSView(Private) | 128 @interface NSView(Private) |
| 129 - (void)_updateTrackingAreas; | 129 - (void)_updateTrackingAreas; |
| 130 @end | 130 @end |
| 131 | 131 |
| 132 @interface BookmarkBarFolderController(Private) | 132 @interface BookmarkBarFolderController () |
| 133 - (void)configureWindow; | 133 - (void)configureWindow; |
| 134 - (void)addOrUpdateScrollTracking; | 134 - (void)addOrUpdateScrollTracking; |
| 135 - (void)removeScrollTracking; | 135 - (void)removeScrollTracking; |
| 136 - (void)endScroll; | 136 - (void)endScroll; |
| 137 - (void)addScrollTimerWithDelta:(CGFloat)delta; | 137 - (void)addScrollTimerWithDelta:(CGFloat)delta; |
| 138 | 138 |
| 139 // Return the screen to which the menu should be restricted. The screen list is |
| 140 // very volatile and can change with very short notice so it isn't worth |
| 141 // caching. http://crbug.com/463458 |
| 142 - (NSScreen*)menuScreen; |
| 143 |
| 139 // Helper function to configureWindow which performs a basic layout of | 144 // Helper function to configureWindow which performs a basic layout of |
| 140 // the window subviews, in particular the menu buttons and the window width. | 145 // the window subviews, in particular the menu buttons and the window width. |
| 141 - (void)layOutWindowWithHeight:(CGFloat)height; | 146 - (void)layOutWindowWithHeight:(CGFloat)height; |
| 142 | 147 |
| 143 // Determine the best button width (which will be the widest button or the | 148 // Determine the best button width (which will be the widest button or the |
| 144 // maximum allowable button width, whichever is less) and resize all buttons. | 149 // maximum allowable button width, whichever is less) and resize all buttons. |
| 145 // Return the new width so that the window can be adjusted. | 150 // Return the new width so that the window can be adjusted. |
| 146 - (CGFloat)adjustButtonWidths; | 151 - (CGFloat)adjustButtonWidths; |
| 147 | 152 |
| 148 // Returns the total menu height needed to display |buttonCount| buttons. | 153 // Returns the total menu height needed to display |buttonCount| buttons. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 ofType:@"nib"]; | 259 ofType:@"nib"]; |
| 255 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { | 260 if ((self = [super initWithWindowNibPath:nibPath owner:self])) { |
| 256 parentButton_.reset([button retain]); | 261 parentButton_.reset([button retain]); |
| 257 selectedIndex_ = -1; | 262 selectedIndex_ = -1; |
| 258 | 263 |
| 259 profile_ = profile; | 264 profile_ = profile; |
| 260 | 265 |
| 261 // We want the button to remain bordered as part of the menu path. | 266 // We want the button to remain bordered as part of the menu path. |
| 262 [button forceButtonBorderToStayOnAlways:YES]; | 267 [button forceButtonBorderToStayOnAlways:YES]; |
| 263 | 268 |
| 264 // Pick the parent button's screen to be the screen upon which all display | |
| 265 // happens. This loop over all screens is not equivalent to | |
| 266 // |[[button window] screen]|. BookmarkButtons are commonly positioned near | |
| 267 // the edge of their windows (both in the bookmark bar and in other bookmark | |
| 268 // menus), and |[[button window] screen]| would return the screen that the | |
| 269 // majority of their window was on even if the parent button were clearly | |
| 270 // contained within a different screen. | |
| 271 NSRect parentButtonGlobalFrame = | |
| 272 [button convertRect:[button bounds] toView:nil]; | |
| 273 parentButtonGlobalFrame.origin = | |
| 274 [[button window] convertBaseToScreen:parentButtonGlobalFrame.origin]; | |
| 275 for (NSScreen* screen in [NSScreen screens]) { | |
| 276 if (NSIntersectsRect([screen frame], parentButtonGlobalFrame)) { | |
| 277 screen_ = screen; | |
| 278 break; | |
| 279 } | |
| 280 } | |
| 281 if (!screen_) { | |
| 282 // The parent button is offscreen. The ideal thing to do would be to | |
| 283 // calculate the "closest" screen, the screen which has an edge parallel | |
| 284 // to, and the least distance from, one of the edges of the button. | |
| 285 // However, popping a subfolder from an offscreen button is an unrealistic | |
| 286 // edge case and so this ideal remains unrealized. Cheat instead; this | |
| 287 // code is wrong but a lot simpler. | |
| 288 screen_ = [[button window] screen]; | |
| 289 } | |
| 290 | |
| 291 parentController_.reset([parentController retain]); | 269 parentController_.reset([parentController retain]); |
| 292 if (!parentController_) | 270 if (!parentController_) |
| 293 [self setSubFolderGrowthToRight:YES]; | 271 [self setSubFolderGrowthToRight:YES]; |
| 294 else | 272 else |
| 295 [self setSubFolderGrowthToRight:[parentController | 273 [self setSubFolderGrowthToRight:[parentController |
| 296 subFolderGrowthToRight]]; | 274 subFolderGrowthToRight]]; |
| 297 barController_ = barController; // WEAK | 275 barController_ = barController; // WEAK |
| 298 buttons_.reset([[NSMutableArray alloc] init]); | 276 buttons_.reset([[NSMutableArray alloc] init]); |
| 299 folderTarget_.reset( | 277 folderTarget_.reset( |
| 300 [[BookmarkFolderTarget alloc] initWithController:self profile:profile]); | 278 [[BookmarkFolderTarget alloc] initWithController:self profile:profile]); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 // since it looks much more menu-like than with none. If we would | 439 // since it looks much more menu-like than with none. If we would |
| 462 // grow off the screen, switch growth to the other direction. Growth | 440 // grow off the screen, switch growth to the other direction. Growth |
| 463 // direction sticks for folder windows which are descendents of us. | 441 // direction sticks for folder windows which are descendents of us. |
| 464 // If we have tried both directions and neither fits, degrade to a | 442 // If we have tried both directions and neither fits, degrade to a |
| 465 // default. | 443 // default. |
| 466 - (CGFloat)childFolderWindowLeftForWidth:(int)windowWidth { | 444 - (CGFloat)childFolderWindowLeftForWidth:(int)windowWidth { |
| 467 // We may legitimately need to try two times (growth to right and | 445 // We may legitimately need to try two times (growth to right and |
| 468 // left but not in that order). Limit us to three tries in case | 446 // left but not in that order). Limit us to three tries in case |
| 469 // the folder window can't fit on either side of the screen; we | 447 // the folder window can't fit on either side of the screen; we |
| 470 // don't want to loop forever. | 448 // don't want to loop forever. |
| 449 NSRect screenVisibleFrame = [[self menuScreen] visibleFrame]; |
| 471 CGFloat x; | 450 CGFloat x; |
| 472 int tries = 0; | 451 int tries = 0; |
| 473 while (tries < 2) { | 452 while (tries < 2) { |
| 474 // Try to grow right. | 453 // Try to grow right. |
| 475 if ([self subFolderGrowthToRight]) { | 454 if ([self subFolderGrowthToRight]) { |
| 476 tries++; | 455 tries++; |
| 477 x = NSMaxX([[parentButton_ window] frame]) - | 456 x = NSMaxX([[parentButton_ window] frame]) - |
| 478 bookmarks::kBookmarkMenuOverlap; | 457 bookmarks::kBookmarkMenuOverlap; |
| 479 // If off the screen, switch direction. | 458 // If off the screen, switch direction. |
| 480 if ((x + windowWidth + | 459 if ((x + windowWidth + bookmarks::kBookmarkHorizontalScreenPadding) > |
| 481 bookmarks::kBookmarkHorizontalScreenPadding) > | 460 NSMaxX(screenVisibleFrame)) { |
| 482 NSMaxX([screen_ visibleFrame])) { | |
| 483 [self setSubFolderGrowthToRight:NO]; | 461 [self setSubFolderGrowthToRight:NO]; |
| 484 } else { | 462 } else { |
| 485 return x; | 463 return x; |
| 486 } | 464 } |
| 487 } | 465 } |
| 488 // Try to grow left. | 466 // Try to grow left. |
| 489 if (![self subFolderGrowthToRight]) { | 467 if (![self subFolderGrowthToRight]) { |
| 490 tries++; | 468 tries++; |
| 491 x = NSMinX([[parentButton_ window] frame]) + | 469 x = NSMinX([[parentButton_ window] frame]) + |
| 492 bookmarks::kBookmarkMenuOverlap - | 470 bookmarks::kBookmarkMenuOverlap - |
| 493 windowWidth; | 471 windowWidth; |
| 494 // If off the screen, switch direction. | 472 // If off the screen, switch direction. |
| 495 if (x < NSMinX([screen_ visibleFrame])) { | 473 if (x < NSMinX(screenVisibleFrame)) { |
| 496 [self setSubFolderGrowthToRight:YES]; | 474 [self setSubFolderGrowthToRight:YES]; |
| 497 } else { | 475 } else { |
| 498 return x; | 476 return x; |
| 499 } | 477 } |
| 500 } | 478 } |
| 501 } | 479 } |
| 502 // Unhappy; do the best we can. | 480 // Unhappy; do the best we can. |
| 503 return NSMaxX([screen_ visibleFrame]) - windowWidth; | 481 return NSMaxX(screenVisibleFrame) - windowWidth; |
| 504 } | 482 } |
| 505 | 483 |
| 506 | 484 |
| 507 // Compute and return the top left point of our window (screen | 485 // Compute and return the top left point of our window (screen |
| 508 // coordinates). The top left is positioned in a manner similar to | 486 // coordinates). The top left is positioned in a manner similar to |
| 509 // cascading menus. Windows may grow to either the right or left of | 487 // cascading menus. Windows may grow to either the right or left of |
| 510 // their parent (if a sub-folder) so we need to know |windowWidth|. | 488 // their parent (if a sub-folder) so we need to know |windowWidth|. |
| 511 - (NSPoint)windowTopLeftForWidth:(int)windowWidth height:(int)windowHeight { | 489 - (NSPoint)windowTopLeftForWidth:(int)windowWidth height:(int)windowHeight { |
| 512 CGFloat kMinSqueezedMenuHeight = bookmarks::kBookmarkFolderButtonHeight * 2.0; | 490 CGFloat kMinSqueezedMenuHeight = bookmarks::kBookmarkFolderButtonHeight * 2.0; |
| 513 NSPoint newWindowTopLeft; | 491 NSPoint newWindowTopLeft; |
| 514 if (![parentController_ isKindOfClass:[self class]]) { | 492 if (![parentController_ isKindOfClass:[self class]]) { |
| 515 // If we're not popping up from one of ourselves, we must be | 493 // If we're not popping up from one of ourselves, we must be |
| 516 // popping up from the bookmark bar itself. In this case, start | 494 // popping up from the bookmark bar itself. In this case, start |
| 517 // BELOW the parent button. Our left is the button left; our top | 495 // BELOW the parent button. Our left is the button left; our top |
| 518 // is bottom of button's parent view. | 496 // is bottom of button's parent view. |
| 519 NSPoint buttonBottomLeftInScreen = | 497 NSPoint buttonBottomLeftInScreen = |
| 520 [[parentButton_ window] | 498 [[parentButton_ window] |
| 521 convertBaseToScreen:[parentButton_ | 499 convertBaseToScreen:[parentButton_ |
| 522 convertPoint:NSZeroPoint toView:nil]]; | 500 convertPoint:NSZeroPoint toView:nil]]; |
| 523 NSPoint bookmarkBarBottomLeftInScreen = | 501 NSPoint bookmarkBarBottomLeftInScreen = |
| 524 [[parentButton_ window] | 502 [[parentButton_ window] |
| 525 convertBaseToScreen:[[parentButton_ superview] | 503 convertBaseToScreen:[[parentButton_ superview] |
| 526 convertPoint:NSZeroPoint toView:nil]]; | 504 convertPoint:NSZeroPoint toView:nil]]; |
| 527 newWindowTopLeft = NSMakePoint( | 505 newWindowTopLeft = NSMakePoint( |
| 528 buttonBottomLeftInScreen.x + bookmarks::kBookmarkBarButtonOffset, | 506 buttonBottomLeftInScreen.x + bookmarks::kBookmarkBarButtonOffset, |
| 529 bookmarkBarBottomLeftInScreen.y + bookmarks::kBookmarkBarMenuOffset); | 507 bookmarkBarBottomLeftInScreen.y + bookmarks::kBookmarkBarMenuOffset); |
| 530 // Make sure the window is on-screen; if not, push left or right. It is | 508 // Make sure the window is on-screen; if not, push left or right. It is |
| 531 // intentional that top level folders "push left" or "push right" slightly | 509 // intentional that top level folders "push left" or "push right" slightly |
| 532 // different than subfolders. | 510 // different than subfolders. |
| 533 NSRect screenFrame = [screen_ visibleFrame]; | 511 NSRect screenVisibleFrame = [[self menuScreen] visibleFrame]; |
| 534 // Test if window goes off-screen on the right side. | 512 // Test if window goes off-screen on the right side. |
| 535 CGFloat spillOff = (newWindowTopLeft.x + windowWidth) - NSMaxX(screenFrame); | 513 CGFloat spillOff = |
| 514 newWindowTopLeft.x + windowWidth - NSMaxX(screenVisibleFrame); |
| 536 if (spillOff > 0.0) { | 515 if (spillOff > 0.0) { |
| 537 newWindowTopLeft.x = std::max(newWindowTopLeft.x - spillOff, | 516 newWindowTopLeft.x = std::max(newWindowTopLeft.x - spillOff, |
| 538 NSMinX(screenFrame)); | 517 NSMinX(screenVisibleFrame)); |
| 539 } else if (newWindowTopLeft.x < NSMinX(screenFrame)) { | 518 } else if (newWindowTopLeft.x < NSMinX(screenVisibleFrame)) { |
| 540 // For left side. | 519 // For left side. |
| 541 newWindowTopLeft.x = NSMinX(screenFrame); | 520 newWindowTopLeft.x = NSMinX(screenVisibleFrame); |
| 542 } | 521 } |
| 543 // The menu looks bad when it is squeezed up against the bottom of the | 522 // The menu looks bad when it is squeezed up against the bottom of the |
| 544 // screen and ends up being only a few pixels tall. If it meets the | 523 // screen and ends up being only a few pixels tall. If it meets the |
| 545 // threshold for this case, instead show the menu above the button. | 524 // threshold for this case, instead show the menu above the button. |
| 546 CGFloat availableVerticalSpace = newWindowTopLeft.y - | 525 CGFloat availableVerticalSpace = newWindowTopLeft.y - |
| 547 (NSMinY(screenFrame) + bookmarks::kScrollWindowVerticalMargin); | 526 (NSMinY(screenVisibleFrame) + bookmarks::kScrollWindowVerticalMargin); |
| 548 if ((availableVerticalSpace < kMinSqueezedMenuHeight) && | 527 if ((availableVerticalSpace < kMinSqueezedMenuHeight) && |
| 549 (windowHeight > availableVerticalSpace)) { | 528 (windowHeight > availableVerticalSpace)) { |
| 550 newWindowTopLeft.y = std::min( | 529 newWindowTopLeft.y = std::min( |
| 551 newWindowTopLeft.y + windowHeight + NSHeight([parentButton_ frame]), | 530 newWindowTopLeft.y + windowHeight + NSHeight([parentButton_ frame]), |
| 552 NSMaxY(screenFrame)); | 531 NSMaxY(screenVisibleFrame)); |
| 553 } | 532 } |
| 554 } else { | 533 } else { |
| 555 // Parent is a folder: expose as much as we can vertically; grow right/left. | 534 // Parent is a folder: expose as much as we can vertically; grow right/left. |
| 556 newWindowTopLeft.x = [self childFolderWindowLeftForWidth:windowWidth]; | 535 newWindowTopLeft.x = [self childFolderWindowLeftForWidth:windowWidth]; |
| 557 NSPoint topOfWindow = NSMakePoint(0, | 536 NSPoint topOfWindow = NSMakePoint(0, |
| 558 NSMaxY([parentButton_ frame]) - | 537 NSMaxY([parentButton_ frame]) - |
| 559 bookmarks::kBookmarkVerticalPadding); | 538 bookmarks::kBookmarkVerticalPadding); |
| 560 topOfWindow = [[parentButton_ window] | 539 topOfWindow = [[parentButton_ window] |
| 561 convertBaseToScreen:[[parentButton_ superview] | 540 convertBaseToScreen:[[parentButton_ superview] |
| 562 convertPoint:topOfWindow toView:nil]]; | 541 convertPoint:topOfWindow toView:nil]]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 metrics.couldScrollUp = ![scrollUpArrowView_ isHidden]; | 587 metrics.couldScrollUp = ![scrollUpArrowView_ isHidden]; |
| 609 metrics.couldScrollDown = ![scrollDownArrowView_ isHidden]; | 588 metrics.couldScrollDown = ![scrollDownArrowView_ isHidden]; |
| 610 | 589 |
| 611 metrics.deltaWindowHeight = 0.0; | 590 metrics.deltaWindowHeight = 0.0; |
| 612 metrics.deltaWindowY = 0.0; | 591 metrics.deltaWindowY = 0.0; |
| 613 metrics.deltaVisibleHeight = 0.0; | 592 metrics.deltaVisibleHeight = 0.0; |
| 614 metrics.deltaVisibleY = 0.0; | 593 metrics.deltaVisibleY = 0.0; |
| 615 metrics.deltaScrollerHeight = 0.0; | 594 metrics.deltaScrollerHeight = 0.0; |
| 616 metrics.deltaScrollerY = 0.0; | 595 metrics.deltaScrollerY = 0.0; |
| 617 | 596 |
| 618 metrics.minimumY = NSMinY([screen_ visibleFrame]) + | 597 metrics.minimumY = NSMinY([[self menuScreen] visibleFrame]) + |
| 619 bookmarks::kScrollWindowVerticalMargin; | 598 bookmarks::kScrollWindowVerticalMargin; |
| 620 metrics.screenBottomY = NSMinY([screen_ frame]); | 599 metrics.screenBottomY = NSMinY([[self menuScreen] frame]); |
| 621 metrics.oldWindowY = NSMinY(metrics.windowFrame); | 600 metrics.oldWindowY = NSMinY(metrics.windowFrame); |
| 622 metrics.folderY = | 601 metrics.folderY = |
| 623 metrics.scrollerFrame.origin.y + metrics.visibleFrame.origin.y + | 602 metrics.scrollerFrame.origin.y + metrics.visibleFrame.origin.y + |
| 624 metrics.oldWindowY - metrics.scrollPoint.y; | 603 metrics.oldWindowY - metrics.scrollPoint.y; |
| 625 metrics.folderTop = metrics.folderY + NSHeight([folderView_ frame]); | 604 metrics.folderTop = metrics.folderY + NSHeight([folderView_ frame]); |
| 626 } | 605 } |
| 627 | 606 |
| 628 - (void)adjustMetrics:(LayoutMetrics*)layoutMetrics { | 607 - (void)adjustMetrics:(LayoutMetrics*)layoutMetrics { |
| 629 LayoutMetrics& metrics(*layoutMetrics); | 608 LayoutMetrics& metrics(*layoutMetrics); |
| 630 CGFloat effectiveFolderY = metrics.folderY; | 609 CGFloat effectiveFolderY = metrics.folderY; |
| 631 if (!metrics.couldScrollUp && !metrics.couldScrollDown) | 610 if (!metrics.couldScrollUp && !metrics.couldScrollDown) |
| 632 effectiveFolderY -= metrics.windowSize.height; | 611 effectiveFolderY -= metrics.windowSize.height; |
| 633 metrics.canScrollUp = effectiveFolderY < metrics.minimumY; | 612 metrics.canScrollUp = effectiveFolderY < metrics.minimumY; |
| 634 CGFloat maximumY = | 613 CGFloat maximumY = |
| 635 NSMaxY([screen_ visibleFrame]) - bookmarks::kScrollWindowVerticalMargin; | 614 NSMaxY([[self menuScreen] visibleFrame]) - |
| 615 bookmarks::kScrollWindowVerticalMargin; |
| 636 metrics.canScrollDown = metrics.folderTop > maximumY; | 616 metrics.canScrollDown = metrics.folderTop > maximumY; |
| 637 | 617 |
| 638 // Accommodate changes in the bottom of the menu. | 618 // Accommodate changes in the bottom of the menu. |
| 639 [self adjustMetricsForMenuBottomChanges:layoutMetrics]; | 619 [self adjustMetricsForMenuBottomChanges:layoutMetrics]; |
| 640 | 620 |
| 641 // Accommodate changes in the top of the menu. | 621 // Accommodate changes in the top of the menu. |
| 642 [self adjustMetricsForMenuTopChanges:layoutMetrics]; | 622 [self adjustMetricsForMenuTopChanges:layoutMetrics]; |
| 643 | 623 |
| 644 metrics.scrollerFrame.origin.y += metrics.deltaScrollerY; | 624 metrics.scrollerFrame.origin.y += metrics.deltaScrollerY; |
| 645 metrics.scrollerFrame.size.height += metrics.deltaScrollerHeight; | 625 metrics.scrollerFrame.size.height += metrics.deltaScrollerHeight; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 - (void)adjustMetricsForMenuTopChanges:(LayoutMetrics*)layoutMetrics { | 680 - (void)adjustMetricsForMenuTopChanges:(LayoutMetrics*)layoutMetrics { |
| 701 LayoutMetrics& metrics(*layoutMetrics); | 681 LayoutMetrics& metrics(*layoutMetrics); |
| 702 if (metrics.canScrollDown == metrics.couldScrollDown) { | 682 if (metrics.canScrollDown == metrics.couldScrollDown) { |
| 703 if (!metrics.canScrollDown) { | 683 if (!metrics.canScrollDown) { |
| 704 // Not scroll-down-able but the menu top has changed. | 684 // Not scroll-down-able but the menu top has changed. |
| 705 metrics.deltaWindowHeight += metrics.scrollDelta; | 685 metrics.deltaWindowHeight += metrics.scrollDelta; |
| 706 } | 686 } |
| 707 } else { | 687 } else { |
| 708 if (metrics.canScrollDown) { | 688 if (metrics.canScrollDown) { |
| 709 // Couldn't -> Can | 689 // Couldn't -> Can |
| 710 const CGFloat maximumY = NSMaxY([screen_ visibleFrame]); | 690 const CGFloat maximumY = NSMaxY([[self menuScreen] visibleFrame]); |
| 711 metrics.deltaWindowHeight += (maximumY - NSMaxY(metrics.windowFrame)); | 691 metrics.deltaWindowHeight += (maximumY - NSMaxY(metrics.windowFrame)); |
| 712 metrics.deltaVisibleHeight -= bookmarks::kScrollWindowVerticalMargin; | 692 metrics.deltaVisibleHeight -= bookmarks::kScrollWindowVerticalMargin; |
| 713 metrics.deltaScrollerHeight -= verticalScrollArrowHeight_; | 693 metrics.deltaScrollerHeight -= verticalScrollArrowHeight_; |
| 714 } else { | 694 } else { |
| 715 // Could -> Can't | 695 // Could -> Can't |
| 716 metrics.deltaWindowHeight -= bookmarks::kScrollWindowVerticalMargin; | 696 metrics.deltaWindowHeight -= bookmarks::kScrollWindowVerticalMargin; |
| 717 metrics.deltaVisibleHeight += bookmarks::kScrollWindowVerticalMargin; | 697 metrics.deltaVisibleHeight += bookmarks::kScrollWindowVerticalMargin; |
| 718 metrics.deltaScrollerHeight += verticalScrollArrowHeight_; | 698 metrics.deltaScrollerHeight += verticalScrollArrowHeight_; |
| 719 } | 699 } |
| 720 } | 700 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 // Lay out the window by adjusting all button widths to be consistent, then | 812 // Lay out the window by adjusting all button widths to be consistent, then |
| 833 // base the window width on this ideal button width. | 813 // base the window width on this ideal button width. |
| 834 CGFloat buttonWidth = [self adjustButtonWidths]; | 814 CGFloat buttonWidth = [self adjustButtonWidths]; |
| 835 CGFloat windowWidth = buttonWidth + padding_; | 815 CGFloat windowWidth = buttonWidth + padding_; |
| 836 NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth | 816 NSPoint newWindowTopLeft = [self windowTopLeftForWidth:windowWidth |
| 837 height:height]; | 817 height:height]; |
| 838 | 818 |
| 839 // Make sure as much of a submenu is exposed (which otherwise would be a | 819 // Make sure as much of a submenu is exposed (which otherwise would be a |
| 840 // problem if the parent button is close to the bottom of the screen). | 820 // problem if the parent button is close to the bottom of the screen). |
| 841 if ([parentController_ isKindOfClass:[self class]]) { | 821 if ([parentController_ isKindOfClass:[self class]]) { |
| 842 CGFloat minimumY = NSMinY([screen_ visibleFrame]) + | 822 CGFloat minimumY = NSMinY([[self menuScreen] visibleFrame]) + |
| 843 bookmarks::kScrollWindowVerticalMargin + | 823 bookmarks::kScrollWindowVerticalMargin + |
| 844 height; | 824 height; |
| 845 newWindowTopLeft.y = MAX(newWindowTopLeft.y, minimumY); | 825 newWindowTopLeft.y = MAX(newWindowTopLeft.y, minimumY); |
| 846 } | 826 } |
| 847 | 827 |
| 848 NSWindow* window = [self window]; | 828 NSWindow* window = [self window]; |
| 849 NSRect windowFrame = NSMakeRect(newWindowTopLeft.x, | 829 NSRect windowFrame = NSMakeRect(newWindowTopLeft.x, |
| 850 newWindowTopLeft.y - height, | 830 newWindowTopLeft.y - height, |
| 851 windowWidth, height); | 831 windowWidth, height); |
| 852 [window setFrame:windowFrame display:NO]; | 832 [window setFrame:windowFrame display:NO]; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 index++; | 957 index++; |
| 978 } | 958 } |
| 979 } | 959 } |
| 980 } | 960 } |
| 981 | 961 |
| 982 - (CGFloat)determineFinalScrollDelta:(CGFloat)delta { | 962 - (CGFloat)determineFinalScrollDelta:(CGFloat)delta { |
| 983 if ((delta > 0.0 && ![scrollUpArrowView_ isHidden]) || | 963 if ((delta > 0.0 && ![scrollUpArrowView_ isHidden]) || |
| 984 (delta < 0.0 && ![scrollDownArrowView_ isHidden])) { | 964 (delta < 0.0 && ![scrollDownArrowView_ isHidden])) { |
| 985 NSWindow* window = [self window]; | 965 NSWindow* window = [self window]; |
| 986 NSRect windowFrame = [window frame]; | 966 NSRect windowFrame = [window frame]; |
| 967 NSRect screenVisibleFrame = [[self menuScreen] visibleFrame]; |
| 987 NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin; | 968 NSPoint scrollPosition = [scrollView_ documentVisibleRect].origin; |
| 988 CGFloat scrollY = scrollPosition.y; | 969 CGFloat scrollY = scrollPosition.y; |
| 989 NSRect scrollerFrame = [scrollView_ frame]; | 970 NSRect scrollerFrame = [scrollView_ frame]; |
| 990 CGFloat scrollerY = NSMinY(scrollerFrame); | 971 CGFloat scrollerY = NSMinY(scrollerFrame); |
| 991 NSRect visibleFrame = [visibleView_ frame]; | 972 NSRect visibleFrame = [visibleView_ frame]; |
| 992 CGFloat visibleY = NSMinY(visibleFrame); | 973 CGFloat visibleY = NSMinY(visibleFrame); |
| 993 CGFloat windowY = NSMinY(windowFrame); | 974 CGFloat windowY = NSMinY(windowFrame); |
| 994 CGFloat offset = scrollerY + visibleY + windowY; | 975 CGFloat offset = scrollerY + visibleY + windowY; |
| 995 | 976 |
| 996 if (delta > 0.0) { | 977 if (delta > 0.0) { |
| 997 // Scrolling up. | 978 // Scrolling up. |
| 998 CGFloat minimumY = NSMinY([screen_ visibleFrame]) + | 979 CGFloat minimumY = NSMinY(screenVisibleFrame) + |
| 999 bookmarks::kScrollWindowVerticalMargin; | 980 bookmarks::kScrollWindowVerticalMargin; |
| 1000 CGFloat maxUpDelta = scrollY - offset + minimumY; | 981 CGFloat maxUpDelta = scrollY - offset + minimumY; |
| 1001 delta = MIN(delta, maxUpDelta); | 982 delta = MIN(delta, maxUpDelta); |
| 1002 } else { | 983 } else { |
| 1003 // Scrolling down. | 984 // Scrolling down. |
| 1004 NSRect screenFrame = [screen_ visibleFrame]; | 985 CGFloat topOfScreen = NSMaxY(screenVisibleFrame); |
| 1005 CGFloat topOfScreen = NSMaxY(screenFrame); | |
| 1006 NSRect folderFrame = [folderView_ frame]; | 986 NSRect folderFrame = [folderView_ frame]; |
| 1007 CGFloat folderHeight = NSHeight(folderFrame); | 987 CGFloat folderHeight = NSHeight(folderFrame); |
| 1008 CGFloat folderTop = folderHeight - scrollY + offset; | 988 CGFloat folderTop = folderHeight - scrollY + offset; |
| 1009 CGFloat maxDownDelta = | 989 CGFloat maxDownDelta = |
| 1010 topOfScreen - folderTop - bookmarks::kScrollWindowVerticalMargin; | 990 topOfScreen - folderTop - bookmarks::kScrollWindowVerticalMargin; |
| 1011 delta = MAX(delta, maxDownDelta); | 991 delta = MAX(delta, maxDownDelta); |
| 1012 } | 992 } |
| 1013 } else { | 993 } else { |
| 1014 delta = 0.0; | 994 delta = 0.0; |
| 1015 } | 995 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1033 verticalScrollDelta_ = delta; | 1013 verticalScrollDelta_ = delta; |
| 1034 scrollTimer_ = [NSTimer timerWithTimeInterval:kBookmarkBarFolderScrollInterval | 1014 scrollTimer_ = [NSTimer timerWithTimeInterval:kBookmarkBarFolderScrollInterval |
| 1035 target:self | 1015 target:self |
| 1036 selector:@selector(performScroll:) | 1016 selector:@selector(performScroll:) |
| 1037 userInfo:nil | 1017 userInfo:nil |
| 1038 repeats:YES]; | 1018 repeats:YES]; |
| 1039 | 1019 |
| 1040 [[NSRunLoop mainRunLoop] addTimer:scrollTimer_ forMode:NSRunLoopCommonModes]; | 1020 [[NSRunLoop mainRunLoop] addTimer:scrollTimer_ forMode:NSRunLoopCommonModes]; |
| 1041 } | 1021 } |
| 1042 | 1022 |
| 1023 - (NSScreen*)menuScreen { |
| 1024 // Return the parent button's screen for use as the screen upon which all |
| 1025 // display happens. This loop over all screens is not equivalent to |
| 1026 // |[[button window] screen]|. BookmarkButtons are commonly positioned near |
| 1027 // the edge of their windows (both in the bookmark bar and in other bookmark |
| 1028 // menus), and |[[button window] screen]| would return the screen that the |
| 1029 // majority of their window was on even if the parent button were clearly |
| 1030 // contained within a different screen. |
| 1031 NSButton* button = parentButton_.get(); |
| 1032 NSRect parentButtonGlobalFrame = |
| 1033 [button convertRect:[button bounds] toView:nil]; |
| 1034 parentButtonGlobalFrame.origin = |
| 1035 [[button window] convertBaseToScreen:parentButtonGlobalFrame.origin]; |
| 1036 for (NSScreen* screen in [NSScreen screens]) { |
| 1037 if (NSIntersectsRect([screen frame], parentButtonGlobalFrame)) |
| 1038 return screen; |
| 1039 } |
| 1040 |
| 1041 // The parent button is offscreen. The ideal thing to do would be to calculate |
| 1042 // the "closest" screen, the screen which has an edge parallel to, and the |
| 1043 // least distance from, one of the edges of the button. However, popping a |
| 1044 // subfolder from an offscreen button is an unrealistic edge case and so this |
| 1045 // ideal remains unrealized. Cheat instead; this code is wrong but a lot |
| 1046 // simpler. |
| 1047 return [[button window] screen]; |
| 1048 } |
| 1043 | 1049 |
| 1044 // Called as a result of our tracking area. Warning: on the main | 1050 // Called as a result of our tracking area. Warning: on the main |
| 1045 // screen (of a single-screened machine), the minimum mouse y value is | 1051 // screen (of a single-screened machine), the minimum mouse y value is |
| 1046 // 1, not 0. Also, we do not get events when the mouse is above the | 1052 // 1, not 0. Also, we do not get events when the mouse is above the |
| 1047 // menubar (to be fixed by setting the proper window level; see | 1053 // menubar (to be fixed by setting the proper window level; see |
| 1048 // initializer). | 1054 // initializer). |
| 1049 // Note [theEvent window] may not be our window, as we also get these messages | 1055 // Note [theEvent window] may not be our window, as we also get these messages |
| 1050 // forwarded from BookmarkButton's mouse tracking loop. | 1056 // forwarded from BookmarkButton's mouse tracking loop. |
| 1051 - (void)mouseMovedOrDragged:(NSEvent*)theEvent { | 1057 - (void)mouseMovedOrDragged:(NSEvent*)theEvent { |
| 1052 NSPoint eventScreenLocation = | 1058 NSPoint eventScreenLocation = |
| (...skipping 960 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 | 2019 |
| 2014 - (void)setIgnoreAnimations:(BOOL)ignore { | 2020 - (void)setIgnoreAnimations:(BOOL)ignore { |
| 2015 ignoreAnimations_ = ignore; | 2021 ignoreAnimations_ = ignore; |
| 2016 } | 2022 } |
| 2017 | 2023 |
| 2018 - (BookmarkButton*)buttonThatMouseIsIn { | 2024 - (BookmarkButton*)buttonThatMouseIsIn { |
| 2019 return buttonThatMouseIsIn_; | 2025 return buttonThatMouseIsIn_; |
| 2020 } | 2026 } |
| 2021 | 2027 |
| 2022 @end // BookmarkBarFolderController | 2028 @end // BookmarkBarFolderController |
| OLD | NEW |