mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1476195 - Allow invoking drag sessions outside of mouseDragged. r=mstange,spohl
The parent process usually starts a native drag session during the processing of a Gecko mouse move event while the mouse is down. Usually, these Gecko mouse move events are processed synchronously during -[ChildView mouseDragged:]. But in some cases, the Gecko mouse move event can be a synthetic mouse move event that was generated in response to a reflow. Those get processed during refresh driver ticks, which run at a time that's completely unrelated to when mouseDragged is invoked. So the widget should just assume that drags can be started at any time between mouseDown and mouseUp. Differential Revision: https://phabricator.services.mozilla.com/D36151 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
785fe64f03
commit
18076b6f51
@ -3078,9 +3078,10 @@ NSPasteboard* globalDragPboard = nil;
|
||||
|
||||
// gLastDragView and gLastDragMouseDownEvent are used to communicate information
|
||||
// to the drag service during drag invocation (starting a drag in from the view).
|
||||
// gLastDragView is only non-null while mouseDragged is on the call stack.
|
||||
NSView* gLastDragView = nil;
|
||||
NSEvent* gLastDragMouseDownEvent = nil;
|
||||
// gLastDragView is only non-null while a mouse button is pressed, so between
|
||||
// mouseDown and mouseUp.
|
||||
NSView* gLastDragView = nil; // [weak]
|
||||
NSEvent* gLastDragMouseDownEvent = nil; // [strong]
|
||||
|
||||
+ (void)initialize {
|
||||
static BOOL initialized = NO;
|
||||
@ -3321,6 +3322,10 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
[mPixelHostingView removeFromSuperview];
|
||||
[mPixelHostingView release];
|
||||
|
||||
if (gLastDragView == self) {
|
||||
gLastDragView = nil;
|
||||
}
|
||||
|
||||
[super dealloc];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
@ -4235,6 +4240,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
|
||||
[gLastDragMouseDownEvent release];
|
||||
gLastDragMouseDownEvent = [theEvent retain];
|
||||
gLastDragView = self;
|
||||
|
||||
// We need isClickThrough because at this point the window we're in might
|
||||
// already have become main, so the check for isMainWindow in
|
||||
@ -4287,6 +4293,8 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
- (void)mouseUp:(NSEvent*)theEvent {
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
gLastDragView = nil;
|
||||
|
||||
if (!mGeckoChild || mBlockedLastMouseDown) return;
|
||||
if (mTextInputHandler->OnHandleEvent(theEvent)) {
|
||||
return;
|
||||
@ -4369,8 +4377,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
gLastDragView = self;
|
||||
|
||||
WidgetMouseEvent geckoEvent(true, eMouseMove, mGeckoChild, WidgetMouseEvent::eReal);
|
||||
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
|
||||
|
||||
@ -4378,7 +4384,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
||||
|
||||
// Note, sending the above event might have destroyed our widget since we didn't retain.
|
||||
// Fine so long as we don't access any local variables from here on.
|
||||
gLastDragView = nil;
|
||||
|
||||
// XXX maybe call markedTextSelectionChanged:client: here?
|
||||
|
||||
|
@ -252,13 +252,10 @@ nsresult nsDragService::InvokeDragSessionImpl(nsIArray* aTransferableArray,
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
if (!gLastDragView) {
|
||||
// gLastDragView is only set during -[ChildView mouseDragged:].
|
||||
// InvokeDragSessionImpl is only called while Gecko processes a mouse move
|
||||
// event. So if we get here with gLastDragView being null, that means that
|
||||
// the mouse button has already been released, and mouseMoved is on the
|
||||
// stack instead of mouseDragged. In that case we need to abort the drag
|
||||
// because the OS won't know where to drop whatever's being dragged, and we
|
||||
// might end up with a stuck drag & drop session.
|
||||
// gLastDragView is non-null between -[ChildView mouseDown:] and -[ChildView mouseUp:].
|
||||
// If we get here with gLastDragView being null, that means that the mouse button has already
|
||||
// been released. In that case we need to abort the drag because the OS won't know where to drop
|
||||
// whatever's being dragged, and we might end up with a stuck drag & drop session.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user