From fb8d8340361bee82c7ade37963dcf79a7994b6d1 Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Tue, 16 Nov 2010 19:33:08 -0800 Subject: [PATCH] Improved key view loop algorithm. Reviewed by me. --- AppKit/CPWindow/CPWindow.j | 78 +++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 22fc98386..032b19382 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -2362,45 +2362,31 @@ CPTexturedBackgroundWindowMask - (BOOL)_hasKeyViewLoop { - var subviews = []; + var views = allViews(self), + index = [views count]; - [self _appendSubviewsOf:_contentView toArray:subviews]; - - for (var i = 0, count = [subviews count]; i < count; i++) - { - if (subviews[i]._nextKeyView) + while (index--) + if ([views[index] nextKeyView]) return YES; - } return NO; } - (void)recalculateKeyViewLoop { - var subviews = []; + var views = allViews(self); - [self _appendSubviewsOf:_contentView toArray:subviews]; + [views sortUsingFunction:keyViewComparator context:nil]; - var keyViewOrder = [subviews sortedArrayUsingFunction:keyViewComparator context:_contentView], - count = [keyViewOrder count]; + var index = 0, + count = [views count]; - for (var i = 0; i < count; i++) - [keyViewOrder[i] setNextKeyView:keyViewOrder[(i + 1) % count]]; + for (; index < count; ++index) + [views[index] setNextKeyView:views[(index + 1) % count]]; _keyViewLoopIsDirty = NO; } -- (void)_appendSubviewsOf:(CPView)aView toArray:(CPArray)anArray -{ - var subviews = [aView subviews], - count = [subviews count]; - - while (count--) - [self _appendSubviewsOf:subviews[count] toArray:anArray]; - - [anArray addObject:aView]; -} - - (void)setAutorecalculatesKeyViewLoop:(BOOL)shouldRecalculate { if (_autorecalculatesKeyViewLoop === shouldRecalculate) @@ -2498,24 +2484,46 @@ CPTexturedBackgroundWindowMask @end +var allViews = function(aWindow) +{ + var views = [[aWindow contentView] subviews], + index = 0; + + for (; index < views.length; ++index) + views = views.concat([views[index] subviews]); + + return views; +} + var keyViewComparator = function(lhs, rhs, context) { - var lhsOrigin = [lhs convertRect:[lhs bounds] toView:nil].origin, - rhsOrigin = [rhs convertRect:[rhs bounds] toView:nil].origin; + var lhsBounds = [lhs convertRect:[lhs bounds] toView:nil], + rhsBounds = [rhs convertRect:[rhs bounds] toView:nil], + lhsY = _CGRectGetMinY(lhsBounds), + rhsY = _CGRectGetMinY(rhsBounds), + lhsX = _CGRectGetMinX(lhsBounds), + rhsX = _CGRectGetMinX(rhsBounds), + intersectsVertically = MIN(_CGRectGetMaxY(lhsBounds), _CGRectGetMaxY(rhsBounds)) - MAX(lhsY, rhsY); - if (lhsOrigin.y < rhsOrigin.y) - return -1; + // If two views are "on the same line" (intersect vertically), then rely on the x comparison. + if (intersectsVertically > 0) + { + if (lhsX < rhsX) + return CPOrderedAscending; - if (lhsOrigin.y === rhsOrigin.y) - if (lhsOrigin.x < rhsOrigin.x) - return -1; + if (lhsX === rhsX) + return CPOrderedSame; - else if (lhsOrigin.x === rhsOrigin.x) - return 0; + return CPOrderedDescending; + } - // lhsOrigin.y === rhsOrigin.y && lhsOrigin.x > rhsOrigin.x || lhsOrigin.y > rhsOrigin.y + if (lhsY < rhsY) + return CPOrderedAscending; - return 1; + if (lhsY === rhsY) + return CPOrderedSame; + + return CPOrderedDescending; } @implementation CPWindow (MenuBar)