From aebd28dbef4af34cc3096fb72c6375c3bf8ab827 Mon Sep 17 00:00:00 2001 From: Didier Korthoudt Date: Mon, 16 May 2016 21:38:46 +0200 Subject: [PATCH 1/4] CPTextField and CPTrackingArea: optimization and cursor management. --- AppKit/CPTextField.j | 63 ++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 09ed728f4..78d7180db 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -410,6 +410,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [self setThemeState:CPThemeStateEditable]; else [self unsetThemeState:CPThemeStateEditable]; + + [self updateTrackingAreas]; } /*! @@ -431,6 +433,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); // We only allow first responder status if the field is enabled. if (!shouldBeEnabled && [[self window] firstResponder] === self) [[self window] makeFirstResponder:nil]; + + [self updateTrackingAreas]; } /*! @@ -440,6 +444,8 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); - (void)setSelectable:(BOOL)aFlag { _isSelectable = aFlag; + + [self updateTrackingAreas]; } /*! @@ -997,14 +1003,11 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [self textDidChange:[CPNotification notificationWithName:CPControlTextDidChangeNotification object:self userInfo:nil]]; } -- (void)mouseMoved:(CPEvent)anEvent -{ - [super mouseMoved:anEvent]; - [self _updateCursorForEvent:anEvent]; -} - - (void)mouseDown:(CPEvent)anEvent { + if (![self isEnabled]) + return [[self nextResponder] mouseDown:anEvent]; + // Don't track! (ever?) if ([self isEditable] && [self isEnabled]) { @@ -1259,27 +1262,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [_delegate controlTextDidEndEditing:note]; } -- (void)_updateCursorForEvent:(CPEvent)anEvent -{ - var frame = CGRectMakeCopy([self frame]), - contentInset = [self currentValueForThemeAttribute:@"content-inset"]; - - frame = [[self superview] convertRectToBase:CGRectInsetByInset(frame, contentInset)]; - - if ([self isEnabled] && ([self isSelectable] || [self isEditable]) && CGRectContainsPoint(frame, [anEvent locationInWindow])) - { -#if PLATFORM(DOM) - self._DOMElement.style.cursor = "text"; -#endif - } - else - { -#if PLATFORM(DOM) - self._DOMElement.style.cursor = "default"; -#endif - } -} - /*! Returns the string in the text field. */ @@ -2200,4 +2182,29 @@ var CPTextFieldIsEditableKey = "CPTextFieldIsEditableKey", [_source setObjectValue:aValue]; } -@end \ No newline at end of file +@end + +@implementation CPTextField (CPTrackingArea) + +- (void)updateTrackingAreas +{ + [self removeAllTrackingAreas]; + + if ([self isEnabled] && (_isEditable || _isSelectable)) + { + var myBounds = CGRectMakeCopy([self bounds]), + contentInset = [self currentValueForThemeAttribute:@"content-inset"]; + + [self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectInsetByInset(myBounds, contentInset) + options:CPTrackingMouseEnteredAndExited | CPTrackingCursorUpdate | CPTrackingActiveInKeyWindow + owner:self + userInfo:nil]]; + } +} + +- (void)cursorUpdate:(CPEvent)anEvent +{ + [[CPCursor IBeamCursor] set]; +} + +@end From 7454620aa2382d12f9c1da9877af43c81e137122 Mon Sep 17 00:00:00 2001 From: Didier Korthoudt Date: Wed, 18 May 2016 19:43:19 +0200 Subject: [PATCH 2/4] Fixed: color panel always open in main platform window --- AppKit/CPColorWell.j | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AppKit/CPColorWell.j b/AppKit/CPColorWell.j index 15fa5343b..fb1b0f0dc 100644 --- a/AppKit/CPColorWell.j +++ b/AppKit/CPColorWell.j @@ -255,6 +255,8 @@ var _CPColorWellDidBecomeExclusiveNotification = @"_CPColorWellDidBecomeExclusiv var colorPanel = [CPColorPanel sharedColorPanel]; + [colorPanel setPlatformWindow:[[self window] platformWindow]]; + [colorPanel setColor:_color]; [colorPanel orderFront:self]; } From 24313d67096a957b7970ca558abbbdf3b92167a5 Mon Sep 17 00:00:00 2001 From: Didier Korthoudt Date: Sun, 22 May 2016 22:14:05 +0200 Subject: [PATCH 3/4] Fixed: right mouse clic during a drag operation cancels it --- AppKit/Platform/CPPlatformWindow.j | 1 + AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/AppKit/Platform/CPPlatformWindow.j b/AppKit/Platform/CPPlatformWindow.j index f73c9205f..16b1a4954 100644 --- a/AppKit/Platform/CPPlatformWindow.j +++ b/AppKit/Platform/CPPlatformWindow.j @@ -60,6 +60,7 @@ var PrimaryPlatformWindow = NULL; BOOL _mouseIsDown; BOOL _mouseDownIsRightClick; + int _firstMouseDownButton; CGPoint _lastMouseEventLocation; CPWindow _mouseDownWindow; CPTimeInterval _lastMouseUp; diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index bb183bd99..c1bb3020b 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -1245,12 +1245,16 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio { if (_mouseIsDown) { + if (aDOMEvent.button !== _firstMouseDownButton) + return; + event = _CPEventFromNativeMouseEvent(aDOMEvent, _mouseDownIsRightClick ? CPRightMouseUp : CPLeftMouseUp, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseUp, timestamp, location), 0, nil); _mouseIsDown = NO; _lastMouseUp = event; _mouseDownWindow = nil; _mouseDownIsRightClick = NO; + _firstMouseDownButton = -1; } if (_DOMEventMode) @@ -1270,6 +1274,16 @@ _CPPlatformWindowWillCloseNotification = @"_CPPlatformWindowWillCloseNotificatio _mouseDownIsRightClick = button == 2 || (CPBrowserIsOperatingSystem(CPMacOperatingSystem) && button == 0 && modifierFlags & CPControlKeyMask); + // If mouse is already down, that means that a second mouse button is pushed. This could interfere in mouse events treatment. Just ignore it. + // BUT we have to track which button will be first released. + if (_mouseIsDown) + { + _mouseDownIsRightClick = !_mouseDownIsRightClick; + return; + } + + _firstMouseDownButton = button; + if ((sourceElement.tagName === "INPUT" || sourceElement.tagName === "TEXTAREA") && sourceElement != _DOMFocusElement) { if ([CPPlatform supportsDragAndDrop]) From e58420b03189c4a0fdec839aee28067f2f9a184d Mon Sep 17 00:00:00 2001 From: cacaodev Date: Fri, 8 Apr 2016 18:45:15 +0200 Subject: [PATCH 4/4] FIXED: CPView received multiple -viewDidHide/Unhide messages FIXED: when a view is hidden by a hidden superview and added to a non hidden superview, the -viewDidUnhide message is sent. With test : CPViewTest.j --- AppKit/CPView.j | 88 ++++++++++++-------- Tests/AppKit/CPViewTest.j | 165 +++++++++++++++++++++++++++++++------- 2 files changed, 190 insertions(+), 63 deletions(-) diff --git a/AppKit/CPView.j b/AppKit/CPView.j index 669f21122..a142e82a9 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -172,6 +172,7 @@ var CPViewHighDPIDrawingEnabled = YES; CPArray _registeredDraggedTypesArray; BOOL _isHidden; + BOOL _isHiddenOrHasHiddenAncestor; BOOL _hitTests; BOOL _clipsToBounds; @@ -372,6 +373,7 @@ var CPViewHighDPIDrawingEnabled = YES; _opacity = 1.0; _isHidden = NO; + _isHiddenOrHasHiddenAncestor = NO; _hitTests = YES; _hierarchyScaleSize = CGSizeMake(1.0 , 1.0); @@ -598,7 +600,7 @@ var CPViewHighDPIDrawingEnabled = YES; [aSubview _removeFromSuperview]; // Set ourselves as the superview. - aSubview._superview = self; + [aSubview _setSuperview:self]; } if (anIndex === CPNotFound || anIndex >= count) @@ -623,11 +625,6 @@ var CPViewHighDPIDrawingEnabled = YES; [aSubview setNextResponder:self]; [aSubview _scaleSizeUnitSquareToSize:[self _hierarchyScaleSize]]; - // If the subview is not hidden and one of its ancestors is hidden, - // notify the subview that it is now hidden. - if (![aSubview isHidden] && [self isHiddenOrHasHiddenAncestor]) - [aSubview _notifyViewDidHide]; - [aSubview viewDidMoveToSuperview]; // Set the subview's window to our own. @@ -697,13 +694,10 @@ var CPViewHighDPIDrawingEnabled = YES; // If the view is not hidden and one of its ancestors is hidden, // notify the view that it is now unhidden. - if (!_isHidden && [_superview isHiddenOrHasHiddenAncestor]) - [self _notifyViewDidUnhide]; + [self _setSuperview:nil]; [self _notifyWindowDidResignKey]; [self _notifyViewDidResignFirstResponder]; - - _superview = nil; } /*! @@ -1599,7 +1593,7 @@ var CPViewHighDPIDrawingEnabled = YES; // FIXME: Should we return to visibility? This breaks in FireFox, Opera, and IE. // _DOMElement.style.visibility = (_isHidden = aFlag) ? "hidden" : "visible"; - _isHidden = aFlag; + #if PLATFORM(DOM) _DOMElement.style.display = _isHidden ? "none" : "block"; @@ -1622,33 +1616,61 @@ var CPViewHighDPIDrawingEnabled = YES; while (view = [view superview]); } - [self _notifyViewDidHide]; + [self _recursiveGainedHiddenAncestor]; } else { [self setNeedsDisplay:YES]; - [self _notifyViewDidUnhide]; + + [self _recursiveLostHiddenAncestor]; } + + _isHidden = aFlag; } -- (void)_notifyViewDidHide +- (void)_setSuperview:(CPView)aSuperview { - [self viewDidHide]; + var hasOldSuperview = (_superview !== nil), + hasNewSuperview = (aSuperview !== nil), + oldSuperviewIsHidden = hasOldSuperview && [_superview isHiddenOrHasHiddenAncestor], + newSuperviewIsHidden = hasNewSuperview && [aSuperview isHiddenOrHasHiddenAncestor]; - var count = [_subviews count]; + if (!newSuperviewIsHidden && oldSuperviewIsHidden) + [self _recursiveLostHiddenAncestor]; - while (count--) - [_subviews[count] _notifyViewDidHide]; + if (newSuperviewIsHidden && !oldSuperviewIsHidden) + [self _recursiveGainedHiddenAncestor]; + + _superview = aSuperview; } -- (void)_notifyViewDidUnhide +- (void)_recursiveLostHiddenAncestor { - [self viewDidUnhide]; + if (_isHiddenOrHasHiddenAncestor) + { + _isHiddenOrHasHiddenAncestor = NO; + [self viewDidUnhide]; + } - var count = [_subviews count]; + [_subviews enumerateObjectsUsingBlock:function(view, idx, stop) + { + [view _recursiveLostHiddenAncestor]; + }]; +} - while (count--) - [_subviews[count] _notifyViewDidUnhide]; +- (void)_recursiveGainedHiddenAncestor +{ + if (!_isHidden) + { + [self viewDidHide]; + } + + _isHiddenOrHasHiddenAncestor = YES; + + [_subviews enumerateObjectsUsingBlock:function(view, idx, stop) + { + [view _recursiveGainedHiddenAncestor]; + }]; } /*! @@ -1718,12 +1740,7 @@ var CPViewHighDPIDrawingEnabled = YES; */ - (BOOL)isHiddenOrHasHiddenAncestor { - var view = self; - - while (view && ![view isHidden]) - view = [view superview]; - - return view !== nil; + return _isHiddenOrHasHiddenAncestor; } /*! @@ -3494,14 +3511,14 @@ setBoundsOrigin: Invoked automatically when the view’s geometry changes such that its tracking areas need to be recalculated. You should override this method to remove out of date tracking areas and add recomputed tracking areas; - + Cocoa calls this on every view, whereas they have tracking area(s) or not. Cappuccino behaves differently : - updateTrackingAreas is called when placing a view in the view hierarchy (that is in a window) - if you have only CPTrackingInVisibleRect tracking areas attached to a view, it will not be called again (until you move the view in the hierarchy) - if you have at least one non-CPTrackingInVisibleRect tracking area attached, it will be called every time the view geometry could be modified You don't have to touch to CPTrackingInVisibleRect tracking areas, they will be automatically updated - + Please note that it is the owner of a tracking area who is called for updateTrackingAreas. But, if a view without any tracking area is inserted in the view hierarchy (that is, in a window), the view is called for updateTrackingAreas. This enables you to use updateTrackingArea to initially attach your tracking areas to the view. @@ -3513,16 +3530,16 @@ setBoundsOrigin: /*! This utility method is intended for CPView subclasses overriding updateTrackingAreas - + Typical use would be : - + - (void)updateTrackingAreas { [self removeAllTrackingAreas]; - + ... add your specific updated tracking areas ... } - + */ - (void)removeAllTrackingAreas { @@ -3707,6 +3724,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask", #endif [self setHidden:[aCoder decodeBoolForKey:CPViewIsHiddenKey]]; + _isHiddenOrHasHiddenAncestor = NO; if ([aCoder containsValueForKey:CPViewOpacityKey]) [self setAlphaValue:[aCoder decodeIntForKey:CPViewOpacityKey]]; diff --git a/Tests/AppKit/CPViewTest.j b/Tests/AppKit/CPViewTest.j index 383db1a99..78812d2fc 100644 --- a/Tests/AppKit/CPViewTest.j +++ b/Tests/AppKit/CPViewTest.j @@ -895,70 +895,167 @@ var updateTrackingAreasCalls, [self assert:nil equals:[view effectiveAppearance]]; } +- (void)testViewDidHideDidUnhide +{ + var expectedResult = [@"viewDidHide_view1", @"viewDidUnhide_view1"]; + + [view1 setHidden:YES]; + [view1 setHidden:NO]; + + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testViewGainedHiddenAncestor +{ + var expectedResult = [@"viewDidHide_view1", + @"viewWillMoveToSuperview_view3", + @"viewDidMoveToSuperview_view3", + @"viewWillMoveToSuperview_view2", + @"viewDidHide_view2", + @"viewDidHide_view3", + @"viewDidMoveToSuperview_view2"]; + + [view1 setHidden:YES]; + [view2 addSubview:view3]; + [view1 addSubview:view2]; + + [self assert:expectedResult equals:methodCalled]; + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"]; + [self assertTrue: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES"]; + + [self assertFalse:[view2 isHidden]]; + [self assertFalse:[view3 isHidden]]; +} + +- (void)testRemoveViewsHiddenByAncestor +{ + var expectedResult = @[ + @"viewWillMoveToSuperview_view2", + @"viewDidUnhide_view2", + @"viewDidUnhide_view3", + @"viewDidMoveToSuperview_view2", + @"viewWillMoveToWindow_view2", + @"viewWillMoveToWindow_view3", + @"viewDidMoveToWindow_view3", + @"viewDidMoveToWindow_view2" +]; + + [view1 setHidden:YES]; + [view1 addSubview:view2]; + [view2 addSubview:view3]; + + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assertFalse:[view2 isHidden]]; + + [self assertTrue: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assertFalse:[view3 isHidden]]; + + methodCalled = []; + + [view2 removeFromSuperview]; + + [self assertFalse: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = NO" ]; + [self assertFalse: [view3 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = NO" ]; + + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testRemoveHiddenView +{ + var expectedResult = [@"viewWillMoveToSuperview_view2", @"viewDidMoveToSuperview_view2", @"viewWillMoveToWindow_view2", @"viewDidMoveToWindow_view2"]; + + [view1 addSubview:view2]; + [view2 setHidden:YES]; + + methodCalled = []; + + [view2 removeFromSuperview]; + [self assertTrue: [view2 isHiddenOrHasHiddenAncestor] message:@"Expected isHiddenOrHasHiddenAncestor = YES" ]; + [self assert:expectedResult equals:methodCalled]; +} + +- (void)testLostHiddenAncestorAfterMovingToNewSuperview +{ + var expectedResult = @[ + @"viewWillMoveToSuperview_view2", + @"viewDidMoveToSuperview_view2", + @"viewDidHide_view1", + @"viewDidHide_view2", + @"viewWillMoveToSuperview_view2", + @"viewDidUnhide_view2", + @"viewDidMoveToSuperview_view2" +]; + + [view1 addSubview:view2]; + [view1 setHidden:YES]; + [view3 addSubview:view2]; + + [self assert:expectedResult equals:methodCalled]; +} // TrackingAreaAdditions - (void)testTrackingAreas { var trackingArea = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect owner:self userInfo:nil]; - + [self assert:0 equals:[[view trackingAreas] count] message:@"Initially, a view has no tracking area"]; // - + [view addTrackingArea:trackingArea]; [self assert:1 equals:[[view trackingAreas] count] message:@"After adding a tracking area"]; [self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"]; // - + [view removeTrackingArea:trackingArea]; [self assert:0 equals:[[view trackingAreas] count] message:@"After removing the only tracking area"]; [self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"]; - + // - + [view addTrackingArea:trackingArea]; [view addTrackingArea:trackingArea]; [view addTrackingArea:trackingArea]; [self assert:1 equals:[[view trackingAreas] count] message:@"Adding the same tracking area multiple times should add it once"]; [self assert:view equals:[trackingArea view] message:@"Tracking area should be linked to view"]; - + var trackingArea2 = [[CPTrackingArea alloc] initWithRect:CGRectMakeZero() options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow owner:self userInfo:nil]; // - + [view addTrackingArea:trackingArea2]; [self assert:2 equals:[[view trackingAreas] count] message:@"After adding a second tracking area"]; [self assert:view equals:[trackingArea2 view] message:@"Tracking area should be linked to view"]; // - + [view removeAllTrackingAreas]; [self assert:0 equals:[[view trackingAreas] count] message:@"After removing all tracking areas"]; [self assert:nil equals:[trackingArea view] message:@"Tracking area should be unlinked"]; [self assert:nil equals:[trackingArea2 view] message:@"Tracking area should be unlinked"]; // - + [view addTrackingArea:trackingArea]; - + var contentView = [window contentView]; [contentView addSubview:view]; [self assert:0 equals:updateTrackingAreasCalls message:@"Putting a view with a CPTrackingAreaInVisibleRect in a window should not call updateTrackingAreas"]; - + [view removeFromSuperview]; // - + [view addTrackingArea:trackingArea2]; [contentView addSubview:view]; [self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with a non CPTrackingAreaInVisibleRect in a window should call updateTrackingAreas"]; - + [view removeAllTrackingAreas]; - + // - + var viewTA = [[CPTrackingAreaView alloc] initWithFrame:CGRectMakeZero()]; updateTrackingAreasCalls = 0; @@ -966,17 +1063,17 @@ var updateTrackingAreasCalls, [self assert:1 equals:updateTrackingAreasCalls message:@"Putting a view with no tracking areas in a window should call updateTrackingAreas"]; // - + updateTrackingAreasCalls = 0; [viewTA addTrackingArea:trackingArea]; [viewTA setFrame:CGRectMake(10, 10, 10, 10)]; [self assert:0 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a CPTrackingAreaInVisibleRect should not call updateTrackingAreas"]; - + // - + updateTrackingAreasCalls = 0; - + [viewTA addTrackingArea:trackingArea2]; [viewTA setFrame:CGRectMake(20, 20, 20, 20)]; [self assert:1 equals:updateTrackingAreasCalls message:@"Changing geometry of a view with a non CPTrackingAreaInVisibleRect should call updateTrackingAreas"]; @@ -1048,7 +1145,7 @@ var updateTrackingAreasCalls, [viewTA removeAllTrackingAreas]; [viewTA addTrackingArea:trackingAreaAllWithDrag]; - + // Mouse enters the tracking area while dragging (option set) [self moveMouseAtPoint:CGPointMake(21, 21) dragging:YES]; @@ -1103,7 +1200,7 @@ var updateTrackingAreasCalls, [self assert:0 equals:mouseExitedCalls message:@"Mouse entering inner tracking area should not call mouseExited"]; [self assert:1 equals:mouseMovedCalls message:@"Mouse entering inner tracking area should call mouseMoved"]; [self assert:1 equals:cursorUpdateCalls message:@"Mouse entering inner tracking area should call cursorUpdate"]; - + // Mouse moves in inner view [self moveMouseAtPoint:CGPointMake(27, 27) dragging:NO]; @@ -1112,7 +1209,7 @@ var updateTrackingAreasCalls, [self assert:0 equals:mouseExitedCalls message:@"Mouse moving in inner tracking area should not call mouseExited"]; [self assert:2 equals:mouseMovedCalls message:@"Mouse moving in inner tracking area should call mouseMoved for both views"]; [self assert:0 equals:cursorUpdateCalls message:@"Mouse moving in inner tracking area should not call cursorUpdate"]; - + // Mouse leaves inner view but remains in outer view [self moveMouseAtPoint:CGPointMake(36, 36) dragging:NO]; @@ -1121,7 +1218,7 @@ var updateTrackingAreasCalls, [self assert:1 equals:mouseExitedCalls message:@"Mouse moving from inner to outer tracking area should call mouseExited (for inner)"]; [self assert:1 equals:mouseMovedCalls message:@"Mouse moving from inner to outer tracking area should call mouseMoved (for outer)"]; [self assert:1 equals:cursorUpdateCalls message:@"Mouse moving from inner to outer tracking area should call cursorUpdate (for outer)"]; - + [self assert:innerViewTA equals:involvedViewForMouseExited message:@"Inner view should receive mouseExited"]; [self assert:viewTA equals:involvedViewForCursorUpdate message:@"Outer view should receive cursorUpdate"]; @@ -1278,7 +1375,7 @@ var updateTrackingAreasCalls, [self mouseUpAtPoint:CGPointMake(10, 10)]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 1.7 : cursor should be an arrow"]; - + // [self moveMouseAtPoint:CGPointMake(1, 1) dragging:NO]; @@ -1292,7 +1389,7 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 2.1 : cursor should be an arrow"]; - + // Step 2.2 : inside the superview / outside the subview [self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO]; @@ -1310,7 +1407,7 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(15, 15) dragging:NO]; [self assert:[CPCursor crosshairCursor] equals:[CPCursor currentCursor] message:@"Step 2.4 : cursor should be a crosshair"]; - + // Step 2.5 : outside the superview [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; @@ -1355,14 +1452,14 @@ var updateTrackingAreasCalls, [self moveMouseAtPoint:CGPointMake(5, 5) dragging:NO]; [self assert:[CPCursor arrowCursor] equals:[CPCursor currentCursor] message:@"Step 3.5 : cursor should be an arrow"]; - + } - (void)testTrackingAreasLiveViewHierarchyModification { // 1. viewB inside viewA with mouseEntered removing itself - var viewA = [[CPTrackingAreaViewWithCursorUpdate alloc] initWithFrame:CGRectMake(20, 20, 40, 40)] + var viewA = [[CPTrackingAreaViewWithCursorUpdate alloc] initWithFrame:CGRectMake(20, 20, 40, 40)], viewB = [[CPTrackingAreaViewLiveRemoval alloc] initWithFrame:CGRectMake(10, 10, 20, 20)]; [[window contentView] setSubviews:[CPArray arrayWithObject:viewA]]; @@ -1691,6 +1788,18 @@ var updateTrackingAreasCalls, [methodCalled addObject:string]; } +- (void)viewDidUnhide +{ + var string = _cmd + @"_" + [self identifier]; + [methodCalled addObject:string]; +} + +- (void)viewDidHide +{ + var string = _cmd + @"_" + [self identifier]; + [methodCalled addObject:string]; +} + - (BOOL)acceptsFirstResponder { return YES;