mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-09-07 03:07:12 +00:00
Final fixes for popovers as child windows
- Fixed case where a dangling transition function was left when closing a popover. - Fixed case where closing a popover, moving the target view, then reopening the same popover would not reposition the popover when resizing the target view's window. - Optimized repositioning of popover on target view change. - Implemented transitional popovers via trapped mouse down events. - Implemented dequeue: argument of CPApplication -setTarget:selector:forNextEventMatchingMask:untilDate:inMode:dequeue: and -setCallback:forNextEventMatchingMask:untilDate:inMode:dequeue:. - Fixed some child window behavior when ordering/closing. - Eliminated no longer necessary window close notification in CPPopover. - Fixed window title in theme so it doesn't dim when window is main but not key.
This commit is contained in:
+16
-11
@@ -620,9 +620,13 @@ CPRunContinuesResponse = -1002;
|
||||
if (_eventListeners.length)
|
||||
{
|
||||
if (_eventListeners[_eventListeners.length - 1]._mask & (1 << [anEvent type]))
|
||||
_eventListeners.pop()._callback(anEvent);
|
||||
{
|
||||
var listener = _eventListeners.pop();
|
||||
listener._callback(anEvent);
|
||||
|
||||
return;
|
||||
if (listener._shouldDequeue)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ([anEvent type] == CPMouseMoved)
|
||||
@@ -919,7 +923,7 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (void)setCallback:(Function)aCallback forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
{
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, aCallback));
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, aCallback, shouldDequeue));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -935,7 +939,7 @@ CPRunContinuesResponse = -1002;
|
||||
*/
|
||||
- (void)setTarget:(id)aTarget selector:(SEL)aSelector forNextEventMatchingMask:(unsigned int)aMask untilDate:(CPDate)anExpiration inMode:(CPString)aMode dequeue:(BOOL)shouldDequeue
|
||||
{
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }));
|
||||
_eventListeners.push(_CPEventListenerMake(aMask, function (anEvent) { objj_msgSend(aTarget, aSelector, anEvent); }, shouldDequeue));
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1212,28 +1216,29 @@ var _CPModalSessionMake = function(aWindow, aStopCode)
|
||||
return { _window:aWindow, _state:CPRunContinuesResponse , _previous:nil };
|
||||
};
|
||||
|
||||
var _CPEventListenerMake = function(anEventMask, aCallback)
|
||||
var _CPEventListenerMake = function(anEventMask, aCallback, shouldDequeue)
|
||||
{
|
||||
return { _mask:anEventMask, _callback:aCallback };
|
||||
return { _mask:anEventMask, _callback:aCallback, _dequeue:shouldDequeue };
|
||||
};
|
||||
|
||||
// Make this a global for use in CPPlatformWindow+DOM.j.
|
||||
_CPRunModalLoop = function(anEvent)
|
||||
{
|
||||
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:NO];
|
||||
[CPApp setCallback:_CPRunModalLoop forNextEventMatchingMask:CPAnyEventMask untilDate:nil inMode:0 dequeue:YES];
|
||||
|
||||
var theWindow = [anEvent window],
|
||||
modalSession = CPApp._currentSession;
|
||||
|
||||
// The special case for popovers here is not clear. In Cocoa the popover window does not respond YES to worksWhenModal,
|
||||
// yet it works when there is a modal window. Maybe it starts its own modal session, but interaction with the original
|
||||
// modal window seems to continue working as well. Regardless of correctness, this solution beats popovers not working
|
||||
// at all from sheets.
|
||||
/*
|
||||
The special case for popovers here is not clear. In Cocoa the popover window does not respond YES to worksWhenModal, yet it works when there is a modal window. Maybe it starts its own modal session, but interaction with the original modal window seems to continue working as well. Regardless of correctness, this solution beats popovers not working at all from sheets.
|
||||
*/
|
||||
if (theWindow == modalSession._window ||
|
||||
[theWindow worksWhenModal] ||
|
||||
[theWindow attachedSheet] == modalSession._window || // -dw- allow modal parent of sheet to be repositioned
|
||||
([theWindow isKindOfClass:_CPPopoverWindow] && [[theWindow targetView] window] === modalSession._window))
|
||||
{
|
||||
[theWindow sendEvent:anEvent];
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -455,6 +455,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
else if (type === CPKeyDown)
|
||||
{
|
||||
var characters = [anEvent characters];
|
||||
|
||||
if (characters === CPEscapeFunctionKey)
|
||||
{
|
||||
_dragOperation = CPDragOperationNone;
|
||||
@@ -471,7 +472,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
|
||||
// If we're not a mouse up, then we're going to want to grab the next event.
|
||||
[CPApp setTarget:self selector:@selector(trackDragging:)
|
||||
forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
|
||||
untilDate:nil inMode:0 dequeue:NO];
|
||||
untilDate:nil inMode:0 dequeue:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -222,11 +222,6 @@ Set the behavior of the CPPopover. It can be:
|
||||
if (!_popoverWindow)
|
||||
{
|
||||
_popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:[self styleMaskForBehavior]];
|
||||
|
||||
var parentWindow = [positioningView window];
|
||||
|
||||
if (![parentWindow isKindOfClass:_CPPopoverWindow])
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(parentWindowWillClose:) name:CPWindowWillCloseNotification object:parentWindow];
|
||||
}
|
||||
|
||||
[_popoverWindow setAppearance:_appearance];
|
||||
@@ -321,22 +316,6 @@ Set the behavior of the CPPopover. It can be:
|
||||
[_delegate popoverDidShow:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Notifications
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
|
||||
This method is called only when a non-popover parent window
|
||||
is closing. In that case popovers should order out.
|
||||
*/
|
||||
- (void)parentWindowWillClose:(CPNotification)aNotification
|
||||
{
|
||||
[_popoverWindow orderOut:nil];
|
||||
[self performClose:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CPPopover (Deprecated)
|
||||
|
||||
@@ -804,6 +804,7 @@ CPSegmentSwitchTrackingMomentary = 2;
|
||||
return;
|
||||
|
||||
var highlighted = [self testSegment:location] === _trackingSegment;
|
||||
|
||||
if (highlighted != _trackingHighlighted)
|
||||
{
|
||||
_trackingHighlighted = highlighted;
|
||||
|
||||
+16
-24
@@ -826,6 +826,9 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
- (void)_orderOutRecursively:(BOOL)recursive
|
||||
{
|
||||
if (!_isVisible)
|
||||
return;
|
||||
|
||||
if ([self isSheet])
|
||||
{
|
||||
// -dw- as in Cocoa, orderOut: detaches the sheet and animates out
|
||||
@@ -855,13 +858,11 @@ CPTexturedBackgroundWindowMask
|
||||
{
|
||||
if (orderingMode === CPWindowOut)
|
||||
{
|
||||
var hasParent = !!_parentWindow;
|
||||
|
||||
// Directly ordering out will detach a child window
|
||||
[_parentWindow removeChildWindow:self];
|
||||
|
||||
// In Cocoa, a window orders out its child windows only if it has no parent
|
||||
[self _orderOutRecursively:!hasParent];
|
||||
[self _orderOutRecursively:!_parentWindow];
|
||||
}
|
||||
else if (orderingMode === CPWindowAbove && otherWindowNumber === 0)
|
||||
[self _orderFront];
|
||||
@@ -1650,20 +1651,9 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
case CPLeftMouseDown:
|
||||
case CPRightMouseDown:
|
||||
// This will return _windowView if it is within a resize region
|
||||
_leftMouseDownView = [_windowView hitTest:point];
|
||||
|
||||
/*
|
||||
hitTest: will only test within the window's frame.
|
||||
If that fails, check if a left mousedown is within
|
||||
the resize slop outside the frame.
|
||||
*/
|
||||
if (!_leftMouseDownView &&
|
||||
type === CPLeftMouseDown &&
|
||||
[self _isValidMousePoint:[self convertBaseToGlobal:point]])
|
||||
{
|
||||
_leftMouseDownView = _windowView;
|
||||
}
|
||||
|
||||
if (_leftMouseDownView !== _firstResponder && [_leftMouseDownView acceptsFirstResponder])
|
||||
[self makeFirstResponder:_leftMouseDownView];
|
||||
|
||||
@@ -2167,15 +2157,12 @@ CPTexturedBackgroundWindowMask
|
||||
|
||||
[[CPNotificationCenter defaultCenter] postNotificationName:CPWindowWillCloseNotification object:self];
|
||||
|
||||
var hasParent = !!_parentWindow;
|
||||
|
||||
[self orderOut:nil];
|
||||
|
||||
// If a window has no parent, close all of the children
|
||||
[self _detachFromChildrenClosing:!hasParent];
|
||||
[_parentWindow removeChildWindow:self];
|
||||
[self _orderOutRecursively:NO];
|
||||
[self _detachFromChildrenClosing:!_parentWindow];
|
||||
}
|
||||
|
||||
- (void)_detachFromChildrenClosing:(BOOL)shouldClose
|
||||
- (void)_detachFromChildrenClosing:(BOOL)shouldCloseChildren
|
||||
{
|
||||
// When a window is closed, it must detach itself from all children
|
||||
[_childWindows enumerateObjectsUsingBlock:function(child)
|
||||
@@ -2184,12 +2171,17 @@ CPTexturedBackgroundWindowMask
|
||||
}
|
||||
];
|
||||
|
||||
if (shouldClose)
|
||||
if (shouldCloseChildren)
|
||||
{
|
||||
[_childWindows enumerateObjectsUsingBlock:function(child)
|
||||
{
|
||||
[child close];
|
||||
// Cocoa does NOT call close or orderOut when closing child windows,
|
||||
// they are summarily closed.
|
||||
[child _orderOutRecursively:NO];
|
||||
[child _detachFromChildrenClosing:![child parentWindow]];
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
_childWindows = [];
|
||||
}
|
||||
|
||||
@@ -1798,6 +1798,7 @@ var themedButtonValues = nil,
|
||||
[@"title-font", [CPFont systemFontOfSize:14]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:1]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
|
||||
[@"title-text-color", [CPColor colorWithWhite:255.0 / 255.0 alpha:1], CPThemeStateMainWindow],
|
||||
[@"title-text-shadow-color", [CPColor blackColor]],
|
||||
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
|
||||
[@"title-alignment", CPCenterTextAlignment],
|
||||
@@ -1865,6 +1866,7 @@ var themedButtonValues = nil,
|
||||
[@"title-font", [CPFont boldSystemFontOfSize:CPFontCurrentSystemSize]],
|
||||
[@"title-text-color", [CPColor colorWithHexString:@"848484"]],
|
||||
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:1], CPThemeStateKeyWindow],
|
||||
[@"title-text-color", [CPColor colorWithWhite:22.0 / 255.0 alpha:1], CPThemeStateMainWindow],
|
||||
[@"title-text-shadow-color", [CPColor whiteColor]],
|
||||
[@"title-text-shadow-offset", CGSizeMake(0.0, 1.0)],
|
||||
[@"title-alignment", CPCenterTextAlignment],
|
||||
|
||||
+89
-78
@@ -25,6 +25,10 @@
|
||||
@import "CPButton.j"
|
||||
@import "CPPanel.j"
|
||||
|
||||
// Use forward declaration because this file is imported by CPPopover
|
||||
@class CPPopover
|
||||
|
||||
@global CPApp
|
||||
|
||||
CPClosableOnBlurWindowMask = 1 << 4;
|
||||
CPPopoverAppearanceMinimal = 0;
|
||||
@@ -52,6 +56,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
BOOL _browserAnimates;
|
||||
BOOL _shouldPerformAnimation;
|
||||
CPInteger _implementedDelegateMethods;
|
||||
JSObject _orderOutTransitionFunction;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,36 +78,6 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
|
||||
/*!
|
||||
Create and init a _CPPopoverWindow with the given size and view.
|
||||
|
||||
@param aSize the size of the popover window
|
||||
@param aView the target view
|
||||
@return ready to use _CPPopoverWindow
|
||||
*/
|
||||
+ (id)popoverWindowWithSize:(CGSize)aSize forView:(CPView)aView
|
||||
{
|
||||
return [_CPPopoverWindow popoverWindowWithSize:aSize forView:aView styleMask:0];
|
||||
}
|
||||
|
||||
/*!
|
||||
Create and init a _CPPopoverWindow with given the size, view and style mask.
|
||||
|
||||
@param aSize the size of the popover window
|
||||
@param aView the target view
|
||||
@param styleMask the window style mask (combine CPClosableWindowMask and CPClosableOnBlurWindowMask)
|
||||
@return ready to use _CPPopoverWindow
|
||||
*/
|
||||
+ (id)popoverWindowWithSize:(CGSize)aSize forView:(CPView)aView styleMask:(int)aMask
|
||||
{
|
||||
var popoverWindow = [[_CPPopoverWindow alloc] initWithContentRect:_CGRectMake(0.0, 0.0, aSize.width, aSize.height) styleMask:aMask];
|
||||
|
||||
// FIXME: There is no attachToView method
|
||||
// [popoverWindow attachToView:aView];
|
||||
|
||||
return popoverWindow;
|
||||
}
|
||||
|
||||
/*!
|
||||
Create and init a _CPPopoverWindow with given the given frame.
|
||||
|
||||
@@ -126,11 +101,13 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
if (self = [super initWithContentRect:aFrame styleMask:aStyleMask])
|
||||
{
|
||||
_animates = YES;
|
||||
_closeOnBlur = (aStyleMask & CPClosableOnBlurWindowMask);
|
||||
_isClosing = NO;
|
||||
_browserAnimates = [self browserSupportsAnimation];
|
||||
_shouldPerformAnimation = YES;
|
||||
_orderOutTransitionFunction = function() { [self _orderOutRecursively:YES]; };
|
||||
|
||||
|
||||
[self setStyleMask:aStyleMask];
|
||||
[self setBecomesKeyOnlyIfNeeded:YES];
|
||||
[self setMovableByWindowBackground:YES];
|
||||
[self setHasShadow:NO];
|
||||
@@ -185,18 +162,14 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
*/
|
||||
- (void)observeValueForKeyPath:(CPString)aPath ofObject:(id)anObject change:(CPDictionary)theChange context:(void)aContext
|
||||
{
|
||||
if ([aPath isEqual:@"frame"])
|
||||
if (aPath === @"frame")
|
||||
{
|
||||
// TODO: don't recompute everything, just compute the move offset
|
||||
var edge = [_windowView preferredEdge];
|
||||
|
||||
if (![_targetView window])
|
||||
{
|
||||
[self _close]
|
||||
return;
|
||||
}
|
||||
|
||||
[self positionRelativeToRect:nil ofView:_targetView preferredEdge:edge];
|
||||
var point = [self computeOriginFromRect:[_targetView bounds] ofView:_targetView preferredEdge:[_windowView preferredEdge]];
|
||||
|
||||
[self setFrameOrigin:point];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +310,8 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
*/
|
||||
- (void)positionRelativeToRect:(CGRect)aRect ofView:(CPView)positioningView preferredEdge:(int)anEdge
|
||||
{
|
||||
var wasVisible = [self isVisible];
|
||||
|
||||
if (!aRect || _CGRectIsEmpty(aRect))
|
||||
aRect = [positioningView bounds];
|
||||
|
||||
@@ -351,14 +326,23 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
{
|
||||
[[_targetView window] removeChildWindow:self];
|
||||
[_targetView removeObserver:self forKeyPath:@"frame"];
|
||||
|
||||
_targetView = positioningView;
|
||||
[_targetView addObserver:self forKeyPath:@"frame" options:0 context:nil];
|
||||
}
|
||||
|
||||
// Always add us as a child, because when we close we are detached from
|
||||
// the parent, and the parent may cache this window and reopen it.
|
||||
[[_targetView window] addChildWindow:self ordered:CPWindowAbove];
|
||||
[_targetView addObserver:self forKeyPath:@"frame" options:0 context:nil];
|
||||
|
||||
/*
|
||||
If _targetView's window is not a full platform window,
|
||||
add us as a child, because when we close we are detached from
|
||||
the parent, and the parent may cache this window and reopen it.
|
||||
*/
|
||||
var targetWindow = [_targetView window];
|
||||
|
||||
if (![targetWindow isFullPlatformWindow])
|
||||
[[_targetView window] addChildWindow:self ordered:CPWindowAbove];
|
||||
|
||||
if (!wasVisible)
|
||||
[self _trapNextMouseDown];
|
||||
}
|
||||
|
||||
/*! @ignore */
|
||||
@@ -382,6 +366,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
#pragma mark Actions
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Closes the _CPPopoverWindow
|
||||
|
||||
@param sender the sender of the action
|
||||
@@ -396,24 +381,17 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
#pragma mark Overrides
|
||||
|
||||
/*!
|
||||
Called when the window is losing focus.
|
||||
@ignore
|
||||
Show animation if necessary.
|
||||
*/
|
||||
- (void)resignKeyWindow
|
||||
- (void)close
|
||||
{
|
||||
[super resignKeyWindow];
|
||||
|
||||
if (_closeOnBlur && !_isClosing)
|
||||
{
|
||||
if (!_delegate ||
|
||||
((_implementedDelegateMethods & _CPPopoverWindow_shouldClose_) &&
|
||||
[_delegate popoverWindowShouldClose:self]))
|
||||
{
|
||||
[self close];
|
||||
}
|
||||
}
|
||||
[self orderOut:self];
|
||||
[self _detachFromChildrenClosing:YES];
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
When the window appears, show animation if necessary.
|
||||
Also take this opportunity to keep track of window moves.
|
||||
|
||||
@@ -421,7 +399,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
*/
|
||||
- (IBAction)orderFront:(is)aSender
|
||||
{
|
||||
if (![self isMainWindow])
|
||||
if (![self isKeyWindow])
|
||||
{
|
||||
[super orderFront:aSender];
|
||||
|
||||
@@ -465,10 +443,10 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
[self setCSS3Property:@"Transform" value:@"scale(1.1)"];
|
||||
[self setCSS3Property:@"Transition" value:CPBrowserCSSProperty('transform') + @" 200ms ease-in"];
|
||||
|
||||
var transitionEndFunction = function()
|
||||
var orderFrontTransitionFunction = function()
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES);
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty('transitionend'), orderFrontTransitionFunction, YES);
|
||||
#endif
|
||||
|
||||
// Now set up the pop-in to normal size transition.
|
||||
@@ -491,7 +469,7 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
};
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), transitionEndFunction, YES);
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty('transitionend'), orderFrontTransitionFunction, YES);
|
||||
#endif
|
||||
}, 0);
|
||||
}
|
||||
@@ -509,14 +487,14 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
}
|
||||
|
||||
/*!
|
||||
@ignore
|
||||
Animate window closing.
|
||||
*/
|
||||
- (void)close
|
||||
- (void)orderOut:(id)aSender
|
||||
{
|
||||
if (![self isVisible])
|
||||
return;
|
||||
|
||||
// set a flag to avoid an infinite loop in resignMainWindow
|
||||
_isClosing = YES;
|
||||
|
||||
if (_animates && _browserAnimates)
|
||||
@@ -525,30 +503,24 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
[self setCSS3Property:@"Transition" value:@"opacity 250ms linear"];
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.style.opacity = 0;
|
||||
#endif
|
||||
|
||||
var transitionEndFunction = function()
|
||||
{
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES);
|
||||
#endif
|
||||
[self _close];
|
||||
};
|
||||
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty("transitionend"), transitionEndFunction, YES);
|
||||
_DOMElement.addEventListener(CPBrowserStyleProperty("transitionend"), _orderOutTransitionFunction, YES);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _close];
|
||||
[self _orderOutRecursively:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_close
|
||||
- (void)_orderOutRecursively:(BOOL)recursive
|
||||
{
|
||||
[super close];
|
||||
// Make absolutely sure no dangling event listeners are left
|
||||
#if PLATFORM(DOM)
|
||||
_DOMElement.removeEventListener(CPBrowserStyleProperty("transitionend"), _orderOutTransitionFunction, YES);
|
||||
#endif
|
||||
|
||||
[_targetView removeObserver:self forKeyPath:@"frame"];
|
||||
[super _orderOutRecursively:recursive];
|
||||
|
||||
_shouldPerformAnimation = YES;
|
||||
_isClosing = NO;
|
||||
@@ -557,4 +529,43 @@ var _CPPopoverWindow_shouldClose_ = 1 << 0,
|
||||
[_delegate popoverWindowDidClose:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Private
|
||||
|
||||
- (void)_mouseWasClicked:(CPEvent)anEvent
|
||||
{
|
||||
/*
|
||||
If the mouse was clicked inside us, trap the next mouse down.
|
||||
If the mouse was clicked outside of us, we close and send this
|
||||
message to any parent popovers so they have a chance to close
|
||||
if necessary.
|
||||
*/
|
||||
if (![self isVisible])
|
||||
return;
|
||||
|
||||
var mouseWindow = [anEvent window];
|
||||
|
||||
if (mouseWindow === self)
|
||||
[self _trapNextMouseDown];
|
||||
else
|
||||
{
|
||||
// Send _close to the delegate so popoverWillClose is sent to the popover's delegate
|
||||
if (_closeOnBlur)
|
||||
[_delegate _close];
|
||||
|
||||
// Give a transient parent popover a chance to close
|
||||
var parent = [self parentWindow];
|
||||
|
||||
if ([parent isKindOfClass:[self class]])
|
||||
[parent _mouseWasClicked:anEvent];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_trapNextMouseDown
|
||||
{
|
||||
// Don't dequeue the event so clicks in controls will work
|
||||
[CPApp setTarget:self selector:@selector(_mouseWasClicked:) forNextEventMatchingMask:CPLeftMouseDownMask untilDate:nil inMode:CPDefaultRunLoopMode dequeue:NO];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user