First submit for CPTrackingArea

This commit is contained in:
Didier Korthoudt
2015-11-06 14:09:23 +01:00
parent d5f38fe2f2
commit 1418dd8b29
8 changed files with 480 additions and 45 deletions
+1
View File
@@ -103,6 +103,7 @@
@import "CPTokenField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
@import "CPTrackingArea.j"
@import "CPTreeNode.j"
@import "CPUserDefaultsController.j"
@import "CPView.j"
+13
View File
@@ -27,6 +27,7 @@
@import "CPShadow.j"
@import "CPView.j"
@import "CPKeyValueBinding.j"
@import "CPTrackingArea.j"
@global CPApp
@@ -195,11 +196,23 @@ var CPControlBlackColor = [CPColor blackColor];
{
_sendActionOn = CPLeftMouseUpMask;
_trackingMouseDownFlags = 0;
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
return self;
}
- (void)awakeFromCib
{
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
#pragma mark -
#pragma mark Control Size
+54
View File
@@ -29,6 +29,7 @@
@import "CPCompatibility.j"
@import "CGGeometry.j"
@import "CPText.j"
@import "CPTrackingArea.j"
@class CPTextField
@class CPWindow
@@ -82,6 +83,8 @@ var _CPEventPeriodicEventPeriod = 0,
BOOL _suppressCappuccinoCut;
BOOL _suppressCappuccinoPaste;
#endif
CPTrackingArea _trackingArea;
}
/*!
@@ -141,6 +144,27 @@ var _CPEventPeriodicEventPeriod = 0,
timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber clickCount:aClickCount pressure:aPressure];
}
/*!
Creates a new mouse tracking event.
@param anEventType the event type
@param aPoint the location of the cursor in the window specified by \c aWindowNumber
@param modifierFlags a bitwise combination of the modifiers specified in the CPEvent globals
@param aTimestamp the time the event occurred
@param aWindowNumber the number of the CPWindow where the event occurred
@param aGraphicsContext the graphics context where the event occurred
@param anEventNumber a number for this event
@param aTrackingArea the tracking area that triggered the event
@throws CPInternalInconsistencyException if an invalid event type is provided
@return the new mouse event
*/
+ (id)enterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
{
return [[self alloc] _initEnterExitEventWithType:anEventType location:aPoint modifierFlags:modifierFlags timestamp:aTimestamp windowNumber:aWindowNumber context:aGraphicsContext eventNumber:anEventNumber trackingArea:aTrackingArea];
}
/*!
Creates a new custom event.
@@ -201,6 +225,28 @@ var _CPEventPeriodicEventPeriod = 0,
return self;
}
/* @ignore */
- (id)_initEnterExitEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
eventNumber:(int)anEventNumber trackingArea:(CPTrackingArea)aTrackingArea
{
if ((anEventType != CPMouseEntered) && (anEventType != CPMouseExited) && (anEventType != CPCursorUpdate))
[CPException raise:CPInternalInconsistencyException reason:"Invalid event type"];
if (self = [self _initWithType:anEventType])
{
_location = CGPointCreateCopy(aPoint);
_modifierFlags = modifierFlags;
_timestamp = aTimestamp;
_context = aGraphicsContext;
_eventNumber = anEventNumber;
_trackingArea = aTrackingArea;
_window = [CPApp windowWithWindowNumber:aWindowNumber];
}
return self;
}
/* @ignore */
- (id)_initKeyEventWithType:(CPEventType)anEventType location:(CGPoint)aPoint modifierFlags:(unsigned int)modifierFlags
timestamp:(CPTimeInterval)aTimestamp windowNumber:(int)aWindowNumber context:(CPGraphicsContext)aGraphicsContext
@@ -583,6 +629,14 @@ var _CPEventPeriodicEventPeriod = 0,
}
}
- (CPTrackingArea)trackingArea
{
if ((_type != CPMouseEntered) && (_type != CPMouseExited) && (_type != CPCursorUpdate))
[CPException raise:CPInternalInconsistencyException reason:"You can't call trackingArea for this event type"];
return _trackingArea;
}
@end
function _CPEventFirePeriodEvent()
+14
View File
@@ -26,6 +26,7 @@
@import "CPImage.j"
@import "CPView.j"
@import "CPCursor.j"
@import "CPTrackingArea.j"
@class CPUserDefaults
@global CPApp
@@ -145,6 +146,14 @@ var ShouldSuppressResizeNotifications = 1,
};
}
- (void)awakeFromCib
{
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
- (id)initWithFrame:(CGRect)aFrame
{
if (self = [super initWithFrame:aFrame])
@@ -159,6 +168,11 @@ var ShouldSuppressResizeNotifications = 1,
_shouldAutosave = YES;
[self _setVertical:YES];
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
return self;
+15
View File
@@ -24,6 +24,7 @@
@import "CPView.j"
@import "CPCursor.j"
@import "_CPImageAndTextView.j"
@import "CPTrackingArea.j"
@class CPTableView
@@ -281,6 +282,14 @@ var CPTableHeaderViewResizeZone = 3.0,
};
}
- (void)awakeFromCib
{
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
- (void)_init
{
_mouseDownLocation = CGPointMakeZero();
@@ -305,7 +314,13 @@ var CPTableHeaderViewResizeZone = 3.0,
self = [super initWithFrame:aFrame];
if (self)
{
[self _init];
[self addTrackingArea:[[CPTrackingArea alloc] initWithRect:CGRectMakeZero()
options:CPTrackingMouseEnteredAndExited | CPTrackingMouseMoved | CPTrackingMouseMoved | CPTrackingActiveInKeyWindow | CPTrackingInVisibleRect
owner:self
userInfo:nil]];
}
return self;
}
+138
View File
@@ -0,0 +1,138 @@
/*
* CPTrackingArea.j
* AppKit
*
* Created by Didier Korthoudt.
* Copyright 2015, Cappuccino Project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@import <Foundation/Foundation.j>
@import "CPView.j"
@typedef CPTrackingAreaOptions
CPTrackingMouseEnteredAndExited = 1 << 1,
CPTrackingMouseMoved = 1 << 2,
CPTrackingCursorUpdate = 1 << 3,
CPTrackingActiveWhenFirstResponder = 1 << 4,
CPTrackingActiveInKeyWindow = 1 << 5,
CPTrackingActiveInActiveApp = 1 << 6, // both mean the same in cappuccino context
CPTrackingActiveAlways = 1 << 6,
CPTrackingAssumeInside = 1 << 7,
CPTrackingInVisibleRect = 1 << 8,
CPTrackingEnabledDuringMouseDrag = 1 << 9;
/*!
@ingroup appkit
A CPTrackingArea defines a region of view that generates mouse-tracking and
cursor-update events when the mouse is over that region.
*/
@implementation CPTrackingArea : CPObject
{
CGRect _rect @accessors(property=rect, readonly);
CPTrackingAreaOptions _options @accessors(property=options, readonly);
id _owner @accessors(property=owner, readonly);
CPDictionary _userInfo @accessors(property=userInfo, readonly);
CPView _referencingView;
}
#pragma mark -
#pragma mark Initialization
/*! Initializes and returns an object defining a region of a view to receive mouse-tracking events, mouse-moved events, cursor-update events, or possibly all these events.
*/
- (CPTrackingArea)initWithRect:(CGRect)aRect options:(CPTrackingAreaOptions)options owner:(id)owner userInfo:(CPDictionary)userInfo
{
if (self = [super init])
{
if (!(options > 0))
[CPException raise:CPInternalInconsistencyException reason:"Invalid CPTrackingArea options"];
// Temporary, waiting for cursor rect management
if (options & CPTrackingCursorUpdate)
[CPException raise:CPInternalInconsistencyException reason:"CPTrackingCursorUpdate not yet implemented"];
// Check options:
// - at least one in CPTrackingMouseEnteredAndExited, CPTrackingMouseMoved, CPTrackingCursorUpdate
// - exactly one in CPTrackingActiveWhenFirstResponder, CPTrackingActiveInKeyWindow, CPTrackingActiveAlways
// - no check on CPTrackingAssumeInside, CPTrackingInVisibleRect, CPTrackingEnableDuringMouseDrag
if (!((options & CPTrackingMouseEnteredAndExited) || (options & CPTrackingMouseMoved) || (options & CPTrackingCursorUpdate)))
[CPException raise:CPInternalInconsistencyException reason:"You must at least select a type of event message"];
if ((((options & CPTrackingActiveWhenFirstResponder) > 0) + ((options & CPTrackingActiveInKeyWindow) > 0) + ((options & CPTrackingActiveAlways) > 0)) != 1)
[CPException raise:CPInternalInconsistencyException reason:"You must select one and only one scope of tracking"];
_rect = aRect;
_options = options;
_owner = owner;
_userInfo = userInfo;
_referencingView = nil;
}
return self;
}
#pragma mark -
#pragma mark Implementation
- (void)_setReferencingView:(CPView)aView
{
_referencingView = aView;
}
- (CPView)_referencingView
{
return _referencingView;
}
- (BOOL)_isReferenced
{
return (!!_referencingView);
}
#pragma mark -
#pragma mark CPCoding
- (id)initWithCoder:(CPCoder)aCoder
{
if (self = [super init])
{
_rect = [aCoder decodeObjectForKey:@"_rect"];
_options = [aCoder decodeObjectForKey:@"_options"];
_owner = [aCoder decodeObjectForKey:@"_owner"];
_userInfo = [aCoder decodeObjectForKey:@"_userInfo"];
_referencingView = [aCoder decodeObjectForKey:@"_referencingView"];
}
return self;
}
- (void)encodeWithCoder:(CPCoder)aCoder
{
[aCoder encodeObject:_rect forKey:@"_rect"];
[aCoder encodeObject:_options forKey:@"_options"];
[aCoder encodeObject:_owner forKey:@"_owner"];
[aCoder encodeObject:_userInfo forKey:@"_userInfo"];
[aCoder encodeObject:_referencingView forKey:@"_referencingView"];
}
@end
+73
View File
@@ -32,6 +32,7 @@
@import "CPGraphicsContext.j"
@import "CPResponder.j"
@import "CPTheme.j"
@import "CPTrackingArea.j"
@import "CPWindow_Constants.j"
@import "_CPDisplayServer.j"
@@ -239,6 +240,8 @@ var CPViewHighDPIDrawingEnabled = YES;
BOOL _allowsVibrancy @accessors(property=allowsVibrancy);
CPAppearance _appearance @accessors(getter=appearance);
CPAppearance _effectiveAppearance;
CPMutableArray _trackingAreas @accessors(property=trackingAreas, readonly);
}
/*
@@ -352,6 +355,8 @@ var CPViewHighDPIDrawingEnabled = YES;
_registeredDraggedTypes = [CPSet set];
_registeredDraggedTypesArray = [];
_trackingAreas = [];
_tag = -1;
_frame = CGRectMakeCopy(aFrame);
@@ -799,8 +804,16 @@ var CPViewHighDPIDrawingEnabled = YES;
[_window _noteUnregisteredDraggedTypes:_registeredDraggedTypes];
[aWindow _noteRegisteredDraggedTypes:_registeredDraggedTypes];
}
// View must be removed from the current window viewsWithTrackingAreas
if (_window && ([_trackingAreas count] > 0))
[_window _removeFromViewsWithTrackingAreas:self];
_window = aWindow;
// View must be added to the new window viewsWithTrackingAreas
if (_window && ([_trackingAreas count] > 0))
[_window _addToViewsWithTrackingAreas:self];
var count = [_subviews count];
@@ -3390,6 +3403,60 @@ setBoundsOrigin:
}
@end
@implementation CPView (TrackingArea)
- (void)addTrackingArea:(CPTrackingArea)trackingArea
{
CPLog.trace("addTrackingArea for view:"+self);
// Consistency check
if (!trackingArea || [_trackingAreas containsObject:trackingArea])
return;
if ([trackingArea _isReferenced])
[CPException raise:CPInternalInconsistencyException reason:"TrackingArea is already associated with another view"];
CPLog.trace("addTrackingArea here we go. FYI, _window="+_window);
[_trackingAreas addObject:trackingArea];
[trackingArea _setReferencingView:self];
CPLog.trace("addTrackingArea count="+[_trackingAreas count]);
if (_window)
if ([_trackingAreas count] == 1)
[_window _addToViewsWithTrackingAreas:self];
else
[_window _addTrackingArea:trackingArea];
}
- (void)removeTrackingArea:(CPTrackingArea)trackingArea
{
// Consistency check
if (!trackingArea)
return;
if (![_trackingAreas containsObject:trackingArea])
[CPException raise:CPInternalInconsistencyException reason:"Trying to remove unreferenced trackingArea"];
if (_window)
if ([_trackingAreas count] == 1)
[_window _removeFromViewsWithTrackingAreas:self];
else
[_window _removeTrackingArea:trackingArea];
[trackingArea _setReferencingView:nil];
[_trackingAreas removeObject:trackingArea];
}
// Invoked automatically when the views geometry changes such that its tracking areas need to be recalculated.
- (void)updateTrackingAreas
{
// You should override this method to remove out of date tracking areas and add recomputed tracking areas;
// your implementation should call super.
}
@end
var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
@@ -3412,6 +3479,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
CPViewSizeScaleKey = @"CPViewSizeScaleKey",
CPViewIsScaledKey = @"CPViewIsScaledKey",
CPViewAppearanceKey = @"CPViewAppearanceKey";
CPViewTrackingAreasKey = @"CPViewTrackingAreasKey";
@implementation CPView (CPCoding)
@@ -3511,6 +3579,10 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[self _decodeThemeObjectsWithCoder:aCoder];
[self setAppearance:[aCoder decodeObjectForKey:CPViewAppearanceKey]];
_trackingAreas = [aCoder decodeObjectForKey:CPViewTrackingAreasKey];
if (!_trackingAreas)
_trackingAreas = [];
[self setNeedsDisplay:YES];
[self setNeedsLayout];
@@ -3596,6 +3668,7 @@ var CPViewAutoresizingMaskKey = @"CPViewAutoresizingMask",
[aCoder encodeSize:[self _hierarchyScaleSize] forKey:CPViewSizeScaleKey];
[aCoder encodeBool:_isScaled forKey:CPViewIsScaledKey];
[aCoder encodeObject:_appearance forKey:CPViewAppearanceKey];
[aCoder encodeObject:_trackingAreas forKey:CPViewTrackingAreasKey];
}
@end
+172 -45
View File
@@ -36,6 +36,7 @@
@import "CPResponder.j"
@import "CPScreen.j"
@import "CPText.j"
@import "CPTrackingArea.j"
@import "CPView.j"
@import "CPWindow_Constants.j"
@import "_CPBorderlessBridgeWindowView.j"
@@ -198,6 +199,8 @@ var CPWindowActionMessageKeys = [
CPView _toolbarView;
CPArray _mouseEnteredStack;
CPArray mouseEnteredStack;
CPArray _viewsWithTrackingAreas;
CPView _leftMouseDownView;
CPView _rightMouseDownView;
@@ -386,6 +389,9 @@ CPTexturedBackgroundWindowMask
selector:@selector(_didReceiveResizeStyleChange:)
name:CPWindowResizeStyleGlobalChangeNotification
object:nil];
_viewsWithTrackingAreas = [];
_mouseEnteredStack = [];
}
return self;
@@ -1958,6 +1964,74 @@ CPTexturedBackgroundWindowMask
case CPLeftMouseDragged:
case CPRightMouseDragged:
// First, we search for any tracking area requesting CPTrackingEnabledDuringMouseDrag.
// At the same time, we update the entered stack.
mouseEnteredStack = [];
for (var i = 0, nb = [_viewsWithTrackingAreas count], aView, trackingAreas, convertedPoint, event, trackingOptions; i < nb; i++)
{
aView = [_viewsWithTrackingAreas objectAtIndex:i];
trackingAreas = [aView trackingAreas];
convertedPoint = [aView convertPoint:point fromView:_windowView];
for (var j = 0, nbTA = [trackingAreas count], aTrackingArea; j < nbTA; j++)
{
aTrackingArea = [trackingAreas objectAtIndex:j];
trackingOptions = [aTrackingArea options];
if (trackingOptions & CPTrackingEnabledDuringMouseDrag)
{
if ((trackingOptions & CPTrackingActiveAlways) ||
((trackingOptions & CPTrackingActiveInKeyWindow) && ([self isKeyWindow])) ||
((trackingOptions & CPTrackingActiveWhenFirstResponder) && ([self isKeyWindow]) && (_firstResponder == aView)))
{
if (CGRectContainsPoint(((trackingOptions & CPTrackingInVisibleRect) ? [aView visibleRect] : [aTrackingArea rect]), convertedPoint))
{
[mouseEnteredStack addObject:aTrackingArea];
if (![_mouseEnteredStack containsObject:aTrackingArea])
{
// Mouse was not in this rect so it's a mouseEntered
if (trackingOptions & CPTrackingMouseEnteredAndExited)
{
event = [CPEvent enterExitEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 trackingArea:aTrackingArea];
[[aTrackingArea owner] mouseEntered:event];
}
}
}
}
}
}
}
// Search now for exited views (were in _mouseEnteredStack but no more in mouseEnteredStack)
for (var i = 0, nb = [_mouseEnteredStack count], aTrackingArea, trackingOptions; i < nb; i++)
{
aTrackingArea = [_mouseEnteredStack objectAtIndex:i];
trackingOptions = [aTrackingArea options];
if (trackingOptions & CPTrackingEnabledDuringMouseDrag)
{
if (![mouseEnteredStack containsObject:aTrackingArea])
{
// Mouse is no more in this area so it's a mouseExited
if (trackingOptions & CPTrackingMouseEnteredAndExited)
{
event = [CPEvent enterExitEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 trackingArea:aTrackingArea];
[[aTrackingArea owner] mouseExited:event];
}
}
}
}
_mouseEnteredStack = mouseEnteredStack;
// Normal mouseDragged workflow
if (!_leftMouseDownView)
return [[_windowView hitTest:point] mouseDragged:anEvent];
@@ -1981,56 +2055,73 @@ CPTexturedBackgroundWindowMask
// Ignore mouse moves for parents of sheets
if (!_acceptsMouseMovedEvents || sheet)
return;
if (!_mouseEnteredStack)
_mouseEnteredStack = [];
var hitTestView = [_windowView hitTest:point];
if ([_mouseEnteredStack count] && [_mouseEnteredStack lastObject] === hitTestView)
return [hitTestView mouseMoved:anEvent];
var view = hitTestView,
mouseEnteredStack = [];
while (view)
mouseEnteredStack = [];
for (var i = 0, nb = [_viewsWithTrackingAreas count], aView, trackingAreas, convertedPoint, event, trackingOptions; i < nb; i++)
{
mouseEnteredStack.unshift(view);
view = [view superview];
aView = [_viewsWithTrackingAreas objectAtIndex:i];
trackingAreas = [aView trackingAreas];
convertedPoint = [aView convertPoint:point fromView:_windowView];
for (var j = 0, nbTA = [trackingAreas count], aTrackingArea; j < nbTA; j++)
{
aTrackingArea = [trackingAreas objectAtIndex:j];
trackingOptions = [aTrackingArea options];
if ((trackingOptions & CPTrackingActiveAlways) ||
((trackingOptions & CPTrackingActiveInKeyWindow) && ([self isKeyWindow])) ||
((trackingOptions & CPTrackingActiveWhenFirstResponder) && ([self isKeyWindow]) && (_firstResponder == aView)))
{
if (CGRectContainsPoint(((trackingOptions & CPTrackingInVisibleRect) ? [aView visibleRect] : [aTrackingArea rect]), convertedPoint))
{
[mouseEnteredStack addObject:aTrackingArea];
if ([_mouseEnteredStack containsObject:aTrackingArea])
{
// Mouse was already in this rect so it's a mouseMoved
if (trackingOptions & CPTrackingMouseMoved)
[[aTrackingArea owner] mouseMoved:anEvent];
}
else
{
// Mouse was not in this rect so it's a mouseEntered
if (trackingOptions & CPTrackingMouseEnteredAndExited)
{
event = [CPEvent enterExitEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 trackingArea:aTrackingArea];
[[aTrackingArea owner] mouseEntered:event];
}
}
}
}
}
}
var deviation = MIN(_mouseEnteredStack.length, mouseEnteredStack.length);
while (deviation--)
if (_mouseEnteredStack[deviation] === mouseEnteredStack[deviation])
break;
var index = deviation + 1,
count = _mouseEnteredStack.length;
if (index < count)
// Search now for exited views (were in _mouseEnteredStack but no more in mouseEnteredStack)
for (var i = 0, nb = [_mouseEnteredStack count], aTrackingArea; i < nb; i++)
{
var event = [CPEvent mouseEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
for (; index < count; ++index)
[_mouseEnteredStack[index] mouseExited:event];
aTrackingArea = [_mouseEnteredStack objectAtIndex:i];
if (![mouseEnteredStack containsObject:aTrackingArea])
{
// Mouse is no more in this area so it's a mouseExited
if ([aTrackingArea options] & CPTrackingMouseEnteredAndExited)
{
event = [CPEvent enterExitEventWithType:CPMouseExited location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 trackingArea:aTrackingArea];
[[aTrackingArea owner] mouseExited:event];
}
}
}
index = deviation + 1;
count = mouseEnteredStack.length;
if (index < count)
{
var event = [CPEvent mouseEventWithType:CPMouseEntered location:point modifierFlags:[anEvent modifierFlags] timestamp:[anEvent timestamp] windowNumber:_windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
for (; index < count; ++index)
[mouseEnteredStack[index] mouseEntered:event];
}
// End of treatment
_mouseEnteredStack = mouseEnteredStack;
[hitTestView mouseMoved:anEvent];
}
}
@@ -3844,6 +3935,42 @@ var interpolate = function(fromValue, toValue, progress)
@end
@implementation CPWindow (TrackingArea)
- (void)_addToViewsWithTrackingAreas:(CPView)aView
{
[_viewsWithTrackingAreas addObject:aView];
for (var i = 0, tas = [aView trackingAreas], nb = [tas count]; i < nb; i++)
[self _addTrackingArea:[tas objectAtIndex:i]];
}
- (void)_removeFromViewsWithTrackingAreas:(CPView)aView
{
for (var i = 0, tas = [aView trackingAreas], nb = [tas count]; i < nb; i++)
[self _removeTrackingArea:[tas objectAtIndex:i]];
[_viewsWithTrackingAreas removeObject:aView];
}
- (void)_addTrackingArea:(CPTrackingArea)trackingArea
{
// If CPTrackingAssumeInside option is set, put the tracking area in the mouseEnteredStack
if ([trackingArea options] & CPTrackingAssumeInside)
[_mouseEnteredStack addObject:trackingArea];
}
- (void)_removeTrackingArea:(CPTrackingArea)trackingArea
{
// If mouse is in the tracking area, we remove it from the stack to avoid to fire a future mouseExited event
if ([_mouseEnteredStack containsObject:trackingArea])
[_mouseEnteredStack removeObject:trackingArea];
}
@end
function _CPWindowFullPlatformWindowSessionMake(aWindowView, aContentRect, hasShadow, aLevel)
{
return { windowView:aWindowView, contentRect:aContentRect, hasShadow:hasShadow, level:aLevel };