2004-06-03 22:44:12 +00:00
|
|
|
/*
|
|
|
|
GSDragView - Generic Drag and Drop code.
|
|
|
|
|
|
|
|
Copyright (C) 2004 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Author: Fred Kiefer <fredkiefer@gmx.de>
|
|
|
|
Date: May 2004
|
|
|
|
|
|
|
|
Based on X11 specific code from:
|
|
|
|
Created by: Wim Oudshoorn <woudshoo@xs4all.nl>
|
|
|
|
Date: Nov 2001
|
|
|
|
Written by: Adam Fedor <fedor@gnu.org>
|
|
|
|
Date: Nov 1998
|
|
|
|
|
|
|
|
This file is part of the GNU Objective C User Interface Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-10-29 21:16:17 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
2004-06-03 22:44:12 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-10 04:01:49 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2007-10-29 21:16:17 +00:00
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2007-10-29 21:16:17 +00:00
|
|
|
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; see the file COPYING.LIB.
|
|
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
2004-06-03 22:44:12 +00:00
|
|
|
|
2010-03-31 08:14:50 +00:00
|
|
|
#import <Foundation/NSDebug.h>
|
|
|
|
#import <Foundation/NSDictionary.h>
|
|
|
|
#import <Foundation/NSThread.h>
|
|
|
|
|
|
|
|
#import "AppKit/NSApplication.h"
|
|
|
|
#import "AppKit/NSCell.h"
|
|
|
|
#import "AppKit/NSCursor.h"
|
|
|
|
#import "AppKit/NSEvent.h"
|
|
|
|
#import "AppKit/NSGraphics.h"
|
|
|
|
#import "AppKit/NSImage.h"
|
|
|
|
#import "AppKit/NSPasteboard.h"
|
|
|
|
#import "AppKit/NSView.h"
|
|
|
|
#import "AppKit/NSWindow.h"
|
|
|
|
|
|
|
|
#import "GNUstepGUI/GSDisplayServer.h"
|
|
|
|
#import "GNUstepGUI/GSDragView.h"
|
2007-03-09 00:21:52 +00:00
|
|
|
#include <math.h>
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
/* Size of the dragged window */
|
|
|
|
#define DWZ 48
|
|
|
|
|
|
|
|
#define SLIDE_TIME_STEP .02 /* in seconds */
|
|
|
|
#define SLIDE_NR_OF_STEPS 20
|
|
|
|
|
|
|
|
@interface GSRawWindow : NSWindow
|
|
|
|
@end
|
|
|
|
|
2010-01-27 11:21:13 +00:00
|
|
|
@interface NSApplication (GNUstepPrivate)
|
|
|
|
- (void) _postAndSendEvent: (NSEvent *)anEvent;
|
|
|
|
@end
|
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
@interface NSCursor (BackendPrivate)
|
|
|
|
- (void *)_cid;
|
|
|
|
- (void) _setCid: (void *)val;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface GSDragView (Private)
|
2005-03-28 08:34:31 +00:00
|
|
|
- (void) _setupWindowFor: (NSImage*)anImage
|
|
|
|
mousePosition: (NSPoint)mPoint
|
|
|
|
imagePosition: (NSPoint)iPoint;
|
2004-06-03 22:44:12 +00:00
|
|
|
- (void) _clearupWindow;
|
|
|
|
- (BOOL) _updateOperationMask: (NSEvent*) theEvent;
|
|
|
|
- (void) _setCursor;
|
|
|
|
- (void) _sendLocalEvent: (GSAppKitSubtype)subtype
|
2005-03-28 08:34:31 +00:00
|
|
|
action: (NSDragOperation)action
|
|
|
|
position: (NSPoint)eventLocation
|
|
|
|
timestamp: (NSTimeInterval)time
|
|
|
|
toWindow: (NSWindow*)dWindow;
|
2006-05-10 21:48:15 +00:00
|
|
|
- (void) _handleDrag: (NSEvent*)theEvent slidePoint: (NSPoint)slidePoint;
|
2004-06-03 22:44:12 +00:00
|
|
|
- (void) _handleEventDuringDragging: (NSEvent *)theEvent;
|
|
|
|
- (void) _updateAndMoveImageToCorrectPosition;
|
|
|
|
- (void) _moveDraggedImageToNewPosition;
|
|
|
|
- (void) _slideDraggedImageTo: (NSPoint)screenPoint
|
2005-03-28 08:34:31 +00:00
|
|
|
numberOfSteps: (int) steps
|
|
|
|
delay: (float) delay
|
2004-06-03 22:44:12 +00:00
|
|
|
waitAfterSlide: (BOOL) waitFlag;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GSRawWindow
|
|
|
|
|
|
|
|
- (BOOL) canBecomeMainWindow
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) canBecomeKeyWindow
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _initDefaults
|
|
|
|
{
|
|
|
|
[super _initDefaults];
|
|
|
|
[self setReleasedWhenClosed: NO];
|
|
|
|
[self setExcludedFromWindowsMenu: YES];
|
|
|
|
}
|
|
|
|
|
2013-01-30 09:48:54 +00:00
|
|
|
- (void) orderWindow: (NSWindowOrderingMode)place relativeTo: (NSInteger)otherWin
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
[super orderWindow: place relativeTo: otherWin];
|
|
|
|
[self setLevel: NSPopUpMenuWindowLevel];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSDragView
|
|
|
|
|
|
|
|
static GSDragView *sharedDragView = nil;
|
|
|
|
|
2006-05-10 21:48:15 +00:00
|
|
|
+ (id) sharedDragView
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
if (sharedDragView == nil)
|
|
|
|
{
|
|
|
|
sharedDragView = [GSDragView new];
|
|
|
|
}
|
|
|
|
return sharedDragView;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (Class) windowClass
|
|
|
|
{
|
|
|
|
return [GSRawWindow class];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if (self != nil)
|
|
|
|
{
|
|
|
|
NSRect winRect = {{0, 0}, {DWZ, DWZ}};
|
2011-07-14 07:17:24 +00:00
|
|
|
NSWindow *sharedDragWindow = [[[object_getClass(self) windowClass] alloc]
|
2011-02-14 18:38:11 +00:00
|
|
|
initWithContentRect: winRect
|
|
|
|
styleMask: NSBorderlessWindowMask
|
|
|
|
backing: NSBackingStoreNonretained
|
|
|
|
defer: NO];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
dragCell = [[NSCell alloc] initImageCell: nil];
|
|
|
|
[dragCell setBordered: NO];
|
|
|
|
|
|
|
|
[sharedDragWindow setContentView: self];
|
2011-06-28 20:59:24 +00:00
|
|
|
[sharedDragWindow setBackgroundColor: [NSColor clearColor]];
|
2004-06-03 22:44:12 +00:00
|
|
|
// Kept alive by the window
|
|
|
|
RELEASE(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NSDraggingInfo protocol */
|
|
|
|
- (NSWindow*) draggingDestinationWindow
|
|
|
|
{
|
|
|
|
return destWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) draggingLocation
|
|
|
|
{
|
|
|
|
return dragPoint;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPasteboard*) draggingPasteboard
|
|
|
|
{
|
|
|
|
return dragPasteboard;
|
|
|
|
}
|
|
|
|
|
2010-12-22 16:16:14 +00:00
|
|
|
- (NSInteger) draggingSequenceNumber
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
return dragSequence;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) draggingSource
|
|
|
|
{
|
|
|
|
return dragSource;
|
|
|
|
}
|
|
|
|
|
2010-12-22 16:16:14 +00:00
|
|
|
- (NSDragOperation) draggingSourceOperationMask
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
// Mix in possible modifiers
|
|
|
|
return dragMask & operationMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSImage*) draggedImage
|
|
|
|
{
|
|
|
|
if (dragSource)
|
|
|
|
return [dragCell image];
|
|
|
|
else
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint) draggedImageLocation
|
|
|
|
{
|
2005-03-28 08:34:31 +00:00
|
|
|
NSPoint loc = dragPoint;
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
if (dragSource)
|
|
|
|
{
|
2005-03-28 08:34:31 +00:00
|
|
|
loc.x -= offset.width;
|
|
|
|
loc.y -= offset.height;
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return loc;
|
|
|
|
}
|
|
|
|
|
2010-12-27 13:40:57 +00:00
|
|
|
- (NSArray *) namesOfPromisedFilesDroppedAtDestination: (NSURL *)dropDestination
|
2007-04-27 18:54:58 +00:00
|
|
|
{
|
2010-12-27 13:40:57 +00:00
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(namesOfPromisedFilesDroppedAtDestination:)])
|
|
|
|
{
|
|
|
|
return [dragSource namesOfPromisedFilesDroppedAtDestination:
|
|
|
|
dropDestination];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
2007-04-27 18:54:58 +00:00
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
- (BOOL) isDragging
|
|
|
|
{
|
|
|
|
return isDragging;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) drawRect: (NSRect)rect
|
|
|
|
{
|
|
|
|
[dragCell drawWithFrame: [self frame] inView: self];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dragImage: (NSImage*)anImage
|
|
|
|
at: (NSPoint)screenLocation
|
|
|
|
offset: (NSSize)initialOffset
|
|
|
|
event: (NSEvent*)event
|
|
|
|
pasteboard: (NSPasteboard*)pboard
|
|
|
|
source: (id)sourceObject
|
|
|
|
slideBack: (BOOL)slideFlag
|
|
|
|
{
|
2005-03-28 08:34:31 +00:00
|
|
|
NSPoint eventPoint;
|
2005-04-01 14:10:39 +00:00
|
|
|
NSPoint imagePoint;
|
2005-03-29 10:08:50 +00:00
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
ASSIGN(dragPasteboard, pboard);
|
|
|
|
ASSIGN(dragSource, sourceObject);
|
|
|
|
dragSequence = [event timestamp];
|
|
|
|
slideBack = slideFlag;
|
|
|
|
|
|
|
|
// Unset the target window
|
|
|
|
targetWindowRef = 0;
|
2010-12-22 16:16:14 +00:00
|
|
|
targetMask = NSDragOperationEvery;
|
2004-06-03 22:44:12 +00:00
|
|
|
destExternal = NO;
|
|
|
|
|
|
|
|
NSDebugLLog(@"NSDragging", @"Start drag with %@", [pboard types]);
|
2005-03-28 08:34:31 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The position of the mouse is the event location plus any offset
|
|
|
|
* provided. We convert this from window coordinates to screen
|
2005-04-01 14:10:39 +00:00
|
|
|
* coordinates.
|
2005-03-28 08:34:31 +00:00
|
|
|
*/
|
|
|
|
eventPoint = [event locationInWindow];
|
2005-04-01 14:10:39 +00:00
|
|
|
eventPoint = [[event window] convertBaseToScreen: eventPoint];
|
2005-03-28 08:34:31 +00:00
|
|
|
eventPoint.x += initialOffset.width;
|
|
|
|
eventPoint.y += initialOffset.height;
|
2005-04-01 14:10:39 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust image location to match the mose adjustment.
|
|
|
|
*/
|
|
|
|
imagePoint = screenLocation;
|
|
|
|
imagePoint.x += initialOffset.width;
|
|
|
|
imagePoint.y += initialOffset.height;
|
2005-03-28 08:34:31 +00:00
|
|
|
|
|
|
|
[self _setupWindowFor: anImage
|
|
|
|
mousePosition: eventPoint
|
2005-04-01 14:10:39 +00:00
|
|
|
imagePosition: imagePoint];
|
2005-03-28 08:34:31 +00:00
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
isDragging = YES;
|
2005-04-01 14:10:39 +00:00
|
|
|
[self _handleDrag: event slidePoint: screenLocation];
|
2004-06-03 22:44:12 +00:00
|
|
|
isDragging = NO;
|
|
|
|
DESTROY(dragSource);
|
|
|
|
DESTROY(dragPasteboard);
|
|
|
|
}
|
|
|
|
|
2005-03-28 08:34:31 +00:00
|
|
|
- (void) slideDraggedImageTo: (NSPoint)point
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
2007-03-09 00:21:52 +00:00
|
|
|
float distx = point.x - dragPosition.x;
|
|
|
|
float disty = point.y - dragPosition.y;
|
|
|
|
float dist = sqrt((distx * distx) + (disty * disty));
|
|
|
|
NSSize imgSize = [[dragCell image] size];
|
|
|
|
float imgDist = sqrt((imgSize.width * imgSize.width) +
|
|
|
|
(imgSize.height * imgSize.height));
|
|
|
|
int steps = (int)(dist/imgDist);
|
|
|
|
|
2005-03-28 08:34:31 +00:00
|
|
|
/*
|
|
|
|
* Convert point from coordinates of image to coordinates of mouse
|
|
|
|
* cursor for internal use.
|
|
|
|
*/
|
2005-03-29 10:08:50 +00:00
|
|
|
point.x += offset.width;
|
2005-03-28 08:34:31 +00:00
|
|
|
point.y += offset.height;
|
2007-03-09 00:21:52 +00:00
|
|
|
/* [self _slideDraggedImageTo: point
|
2004-06-03 22:44:12 +00:00
|
|
|
numberOfSteps: SLIDE_NR_OF_STEPS
|
|
|
|
delay: SLIDE_TIME_STEP
|
2007-03-09 00:21:52 +00:00
|
|
|
waitAfterSlide: YES];*/
|
|
|
|
[self _slideDraggedImageTo: point
|
|
|
|
numberOfSteps: steps
|
|
|
|
delay: SLIDE_TIME_STEP
|
2004-06-03 22:44:12 +00:00
|
|
|
waitAfterSlide: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Called by NSWindow. Sends drag events to external sources
|
|
|
|
*/
|
|
|
|
- (void) postDragEvent: (NSEvent *)theEvent
|
|
|
|
{
|
|
|
|
if ([theEvent subtype] == GSAppKitDraggingStatus)
|
|
|
|
{
|
|
|
|
NSDragOperation action = [theEvent data2];
|
|
|
|
|
|
|
|
if (destExternal)
|
2007-04-27 18:54:58 +00:00
|
|
|
{
|
2004-06-03 22:44:12 +00:00
|
|
|
|
2007-04-27 18:54:58 +00:00
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
else
|
|
|
|
{
|
2007-04-27 18:54:58 +00:00
|
|
|
if (action != targetMask)
|
|
|
|
{
|
|
|
|
targetMask = action;
|
|
|
|
[self _setCursor];
|
|
|
|
}
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-10 21:48:15 +00:00
|
|
|
- (void) sendExternalEvent: (GSAppKitSubtype)subtype
|
2007-04-27 18:54:58 +00:00
|
|
|
action: (NSDragOperation)action
|
|
|
|
position: (NSPoint)eventLocation
|
|
|
|
timestamp: (NSTimeInterval)time
|
|
|
|
toWindow: (int)dWindowNumber
|
2006-05-10 21:48:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Return the window that lies below the cursor and accepts drag and drop.
|
|
|
|
In mouseWindowRef the OS reference for this window is returned, this is even
|
|
|
|
set, if there is a native window, but no GNUstep window at this location.
|
|
|
|
*/
|
|
|
|
- (NSWindow*) windowAcceptingDnDunder: (NSPoint)mouseLocation
|
2007-04-27 18:54:58 +00:00
|
|
|
windowRef: (int*)mouseWindowRef
|
2006-05-10 21:48:15 +00:00
|
|
|
{
|
2013-02-13 08:40:36 +00:00
|
|
|
NSInteger win;
|
2006-05-10 21:48:15 +00:00
|
|
|
|
|
|
|
*mouseWindowRef = 0;
|
|
|
|
win = [GSServerForWindow(_window) findWindowAt: mouseLocation
|
|
|
|
windowRef: mouseWindowRef
|
|
|
|
excluding: [_window windowNumber]];
|
|
|
|
|
|
|
|
return GSWindowWithNumber(win);
|
|
|
|
}
|
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GSDragView (Private)
|
|
|
|
|
|
|
|
/*
|
|
|
|
Method to initialize the dragview before it is put on the screen.
|
|
|
|
It only initializes the instance variables that have to do with
|
|
|
|
moving the image over the screen and variables that are used
|
|
|
|
to keep track where we are.
|
|
|
|
|
|
|
|
So it is typically used just before the dragview is actually displayed.
|
|
|
|
|
|
|
|
Post conditions:
|
|
|
|
- dragCell is initialized with the image to drag.
|
|
|
|
- all instance variables pertaining to moving the window are initialized
|
|
|
|
*/
|
2005-03-28 08:34:31 +00:00
|
|
|
- (void) _setupWindowFor: (NSImage*)anImage
|
2007-04-27 18:54:58 +00:00
|
|
|
mousePosition: (NSPoint)mPoint
|
|
|
|
imagePosition: (NSPoint)iPoint
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
2013-02-13 08:40:36 +00:00
|
|
|
NSSize imageSize;
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
if (anImage == nil)
|
|
|
|
{
|
|
|
|
anImage = [NSImage imageNamed: @"common_Close"];
|
|
|
|
}
|
|
|
|
imageSize = [anImage size];
|
2005-03-28 08:34:31 +00:00
|
|
|
[dragCell setImage: anImage];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
/* setup the coordinates, used for moving the view around */
|
2005-03-28 08:34:31 +00:00
|
|
|
dragPosition = mPoint;
|
|
|
|
newPosition = mPoint;
|
|
|
|
offset.width = mPoint.x - iPoint.x;
|
|
|
|
offset.height = mPoint.y - iPoint.y;
|
|
|
|
|
|
|
|
[_window setFrame:
|
|
|
|
NSMakeRect (iPoint.x, iPoint.y, imageSize.width, imageSize.height)
|
|
|
|
display: NO];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
// Only display the image
|
|
|
|
[GSServerForWindow(_window) restrictWindow: [_window windowNumber]
|
|
|
|
toImage: [dragCell image]];
|
|
|
|
|
|
|
|
[_window orderFront: nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _clearupWindow
|
|
|
|
{
|
2012-09-14 01:01:23 +00:00
|
|
|
[_window setFrame: NSZeroRect display: NO];
|
2004-06-03 22:44:12 +00:00
|
|
|
[_window orderOut: nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
updates the operationMask by examining modifier keys
|
|
|
|
pressed during -theEvent-.
|
|
|
|
|
|
|
|
If the current value of operationMask == NSDragOperationIgnoresModifiers
|
|
|
|
it will return immediately without updating the operationMask
|
|
|
|
|
|
|
|
This method will return YES if the operationMask
|
|
|
|
is changed, NO if it is still the same.
|
|
|
|
*/
|
|
|
|
- (BOOL) _updateOperationMask: (NSEvent*) theEvent
|
|
|
|
{
|
2013-02-13 08:40:36 +00:00
|
|
|
NSUInteger mod = [theEvent modifierFlags];
|
2010-12-22 16:16:14 +00:00
|
|
|
NSDragOperation oldOperationMask = operationMask;
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
if (operationMask == NSDragOperationIgnoresModifiers)
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mod & NSControlKeyMask)
|
|
|
|
{
|
|
|
|
operationMask = NSDragOperationLink;
|
|
|
|
}
|
|
|
|
else if (mod & NSAlternateKeyMask)
|
|
|
|
{
|
|
|
|
operationMask = NSDragOperationCopy;
|
|
|
|
}
|
|
|
|
else if (mod & NSCommandKeyMask)
|
|
|
|
{
|
|
|
|
operationMask = NSDragOperationGeneric;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-22 16:16:14 +00:00
|
|
|
operationMask = NSDragOperationEvery;
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (operationMask != oldOperationMask);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
_setCursor examines the state of the dragging and update
|
|
|
|
the cursor accordingly. It will not save the current cursor,
|
|
|
|
if you want to keep the original you have to save it yourself.
|
|
|
|
|
|
|
|
The code recogines 4 cursors:
|
|
|
|
|
|
|
|
- NONE - when the source does not allow dragging
|
|
|
|
- COPY - when the current operation is ONLY Copy
|
|
|
|
- LINK - when the current operation is ONLY Link
|
|
|
|
- GENERIC - all other cases
|
|
|
|
|
|
|
|
And two colors
|
|
|
|
|
|
|
|
- GREEN - when the target accepts the drop
|
|
|
|
- BLACK - when the target does not accept the drop
|
|
|
|
|
|
|
|
Note that the code to figure out which of the 4 cursor to use
|
|
|
|
depends on the fact that
|
|
|
|
|
|
|
|
{NSDragOperationNone, NSDragOperationCopy, NSDragOperationLink} = {0, 1, 2}
|
|
|
|
*/
|
|
|
|
- (void) _setCursor
|
|
|
|
{
|
|
|
|
NSCursor *newCursor;
|
2010-12-22 16:16:14 +00:00
|
|
|
NSDragOperation mask;
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
mask = dragMask & operationMask;
|
|
|
|
|
|
|
|
if (targetWindowRef != 0)
|
|
|
|
mask &= targetMask;
|
|
|
|
|
|
|
|
NSDebugLLog (@"NSDragging",
|
|
|
|
@"drag, operation, target mask = (%x, %x, %x), dnd aware = %d\n",
|
2019-04-17 14:44:54 +00:00
|
|
|
(unsigned int)dragMask, (unsigned int)operationMask,
|
|
|
|
(unsigned int)targetMask, (targetWindowRef != 0));
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
switch (mask)
|
|
|
|
{
|
|
|
|
case NSDragOperationNone:
|
2019-04-17 14:44:54 +00:00
|
|
|
newCursor = [NSCursor operationNotAllowedCursor];
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
2019-04-17 14:44:54 +00:00
|
|
|
case NSDragOperationGeneric:
|
2004-06-03 22:44:12 +00:00
|
|
|
case NSDragOperationCopy:
|
2019-04-17 14:44:54 +00:00
|
|
|
newCursor = [NSCursor dragCopyCursor];
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
case NSDragOperationLink:
|
2019-04-17 14:44:54 +00:00
|
|
|
newCursor = [NSCursor dragLinkCursor];
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
2019-04-17 14:44:54 +00:00
|
|
|
case NSDragOperationDelete:
|
|
|
|
newCursor = [NSCursor disappearingItemCursor];
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
2019-04-17 14:44:54 +00:00
|
|
|
// NSDragOperationEvery, NSDragOperationPrivate
|
|
|
|
if (targetWindowRef != 0)
|
|
|
|
{
|
|
|
|
newCursor = [NSCursor greenArrowCursor];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newCursor = [NSCursor arrowCursor];
|
|
|
|
}
|
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-02-15 22:54:23 +00:00
|
|
|
[newCursor set];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _sendLocalEvent: (GSAppKitSubtype)subtype
|
|
|
|
action: (NSDragOperation)action
|
|
|
|
position: (NSPoint)eventLocation
|
|
|
|
timestamp: (NSTimeInterval)time
|
|
|
|
toWindow: (NSWindow*)dWindow
|
|
|
|
{
|
|
|
|
NSEvent *e;
|
|
|
|
NSGraphicsContext *context = GSCurrentContext();
|
|
|
|
// FIXME: Should store this once
|
2013-02-13 08:40:36 +00:00
|
|
|
NSInteger dragWindowRef = (NSInteger)(intptr_t)[GSServerForWindow(_window) windowDevice: [_window windowNumber]];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
eventLocation = [dWindow convertScreenToBase: eventLocation];
|
|
|
|
e = [NSEvent otherEventWithType: NSAppKitDefined
|
|
|
|
location: eventLocation
|
|
|
|
modifierFlags: 0
|
|
|
|
timestamp: time
|
|
|
|
windowNumber: [dWindow windowNumber]
|
|
|
|
context: context
|
|
|
|
subtype: subtype
|
|
|
|
data1: dragWindowRef
|
|
|
|
data2: action];
|
2010-01-27 11:21:13 +00:00
|
|
|
[NSApp _postAndSendEvent: e];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
The dragging support works by hijacking the NSApp event loop.
|
|
|
|
|
|
|
|
- this function loops until the dragging operation is finished
|
|
|
|
and consumes all NSEvents during the drag operation.
|
|
|
|
|
|
|
|
- It sets up periodic events. The drawing and communication
|
|
|
|
with DraggingSource and DraggingTarget is handled in the
|
|
|
|
periodic event code. The use of periodic events is purely
|
|
|
|
a performance improvement. If no periodic events are used
|
|
|
|
the system can not process them all on time.
|
|
|
|
At least on a 333Mhz laptop, using fairly simple
|
|
|
|
DraggingTarget code.
|
|
|
|
|
|
|
|
PROBLEMS:
|
|
|
|
|
|
|
|
- No autoreleasePools are created. So long drag operations can consume
|
|
|
|
memory
|
|
|
|
|
|
|
|
- It seems that sometimes a periodic event get lost.
|
|
|
|
*/
|
2005-04-01 14:10:39 +00:00
|
|
|
- (void) _handleDrag: (NSEvent*)theEvent slidePoint: (NSPoint)slidePoint
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
// Caching some often used values. These values do not
|
|
|
|
// change in this method.
|
|
|
|
// Use eWindow for coordination transformation
|
|
|
|
NSWindow *eWindow = [theEvent window];
|
|
|
|
NSDate *theDistantFuture = [NSDate distantFuture];
|
2013-02-13 08:40:36 +00:00
|
|
|
NSUInteger eventMask = NSLeftMouseDownMask | NSLeftMouseUpMask
|
2004-06-03 22:44:12 +00:00
|
|
|
| NSLeftMouseDraggedMask | NSMouseMovedMask
|
|
|
|
| NSPeriodicMask | NSAppKitDefinedMask | NSFlagsChangedMask;
|
|
|
|
NSPoint startPoint;
|
|
|
|
// Storing values, to restore after we have finished.
|
|
|
|
NSCursor *cursorBeforeDrag = [NSCursor currentCursor];
|
|
|
|
BOOL deposited;
|
|
|
|
|
|
|
|
startPoint = [eWindow convertBaseToScreen: [theEvent locationInWindow]];
|
2005-03-28 08:34:31 +00:00
|
|
|
startPoint.x -= offset.width;
|
|
|
|
startPoint.y -= offset.height;
|
2010-04-10 17:48:46 +00:00
|
|
|
NSDebugLLog(@"NSDragging", @"Drag window origin %@\n", NSStringFromPoint(startPoint));
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
// Notify the source that dragging has started
|
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(draggedImage:beganAt:)])
|
|
|
|
{
|
|
|
|
[dragSource draggedImage: [self draggedImage]
|
2005-03-28 08:34:31 +00:00
|
|
|
beganAt: startPoint];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// --- Setup up the masks for the drag operation ---------------------
|
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(ignoreModifierKeysWhileDragging)]
|
|
|
|
&& [dragSource ignoreModifierKeysWhileDragging])
|
|
|
|
{
|
|
|
|
operationMask = NSDragOperationIgnoresModifiers;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
operationMask = 0;
|
|
|
|
[self _updateOperationMask: theEvent];
|
|
|
|
}
|
|
|
|
|
2010-12-27 13:40:57 +00:00
|
|
|
|
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(draggingSourceOperationMaskForLocal:)])
|
|
|
|
{
|
|
|
|
dragMask = [dragSource draggingSourceOperationMaskForLocal: !destExternal];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dragMask = NSDragOperationCopy | NSDragOperationLink |
|
|
|
|
NSDragOperationGeneric | NSDragOperationPrivate;
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
// --- Setup the event loop ------------------------------------------
|
|
|
|
[self _updateAndMoveImageToCorrectPosition];
|
|
|
|
[NSEvent startPeriodicEventsAfterDelay: 0.02 withPeriod: 0.03];
|
|
|
|
|
|
|
|
// --- Loop that handles all events during drag operation -----------
|
|
|
|
while ([theEvent type] != NSLeftMouseUp)
|
|
|
|
{
|
|
|
|
[self _handleEventDuringDragging: theEvent];
|
|
|
|
|
|
|
|
theEvent = [NSApp nextEventMatchingMask: eventMask
|
|
|
|
untilDate: theDistantFuture
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
dequeue: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
// --- Event loop for drag operation stopped ------------------------
|
|
|
|
[NSEvent stopPeriodicEvents];
|
|
|
|
[self _updateAndMoveImageToCorrectPosition];
|
|
|
|
|
|
|
|
NSDebugLLog(@"NSDragging", @"dnd ending %d\n", targetWindowRef);
|
|
|
|
|
|
|
|
// --- Deposit the drop ----------------------------------------------
|
|
|
|
if ((targetWindowRef != 0)
|
|
|
|
&& ((targetMask & dragMask & operationMask) != NSDragOperationNone))
|
|
|
|
{
|
2005-03-28 08:34:31 +00:00
|
|
|
/* FIXME:
|
|
|
|
* We remove the dragged image from the screen before
|
|
|
|
* sending the dnd drop event to the destination.
|
|
|
|
* This code should actually be rewritten, because
|
|
|
|
* the depositing of the drop consist of three steps
|
|
|
|
* - prepareForDragOperation
|
|
|
|
* - performDragOperation
|
|
|
|
* - concludeDragOperation.
|
|
|
|
* The dragged image should be removed from the screen
|
|
|
|
* between the prepare and the perform operation.
|
|
|
|
* The three steps are now executed in the NSWindow class
|
|
|
|
* and the NSWindow class does not have access to
|
|
|
|
* the image.
|
|
|
|
*/
|
2004-06-03 22:44:12 +00:00
|
|
|
[self _clearupWindow];
|
|
|
|
[cursorBeforeDrag set];
|
|
|
|
NSDebugLLog(@"NSDragging", @"sending dnd drop\n");
|
|
|
|
if (!destExternal)
|
2007-04-27 18:54:58 +00:00
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingDrop
|
|
|
|
action: 0
|
2010-02-14 12:15:05 +00:00
|
|
|
position: dragPosition
|
2007-04-27 18:54:58 +00:00
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: destWindow];
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
else
|
2007-04-27 18:54:58 +00:00
|
|
|
{
|
|
|
|
[self sendExternalEvent: GSAppKitDraggingDrop
|
|
|
|
action: 0
|
2010-02-14 12:15:05 +00:00
|
|
|
position: dragPosition
|
2007-04-27 18:54:58 +00:00
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: targetWindowRef];
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
deposited = YES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (slideBack)
|
|
|
|
{
|
2005-04-01 14:10:39 +00:00
|
|
|
[self slideDraggedImageTo: slidePoint];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
[self _clearupWindow];
|
|
|
|
[cursorBeforeDrag set];
|
|
|
|
deposited = NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([dragSource respondsToSelector:
|
2007-04-27 18:54:58 +00:00
|
|
|
@selector(draggedImage:endedAt:operation:)])
|
|
|
|
{
|
|
|
|
NSPoint point;
|
|
|
|
|
|
|
|
point = [theEvent locationInWindow];
|
|
|
|
// Convert from mouse cursor coordinate to image coordinate
|
|
|
|
point.x -= offset.width;
|
|
|
|
point.y -= offset.height;
|
|
|
|
point = [[theEvent window] convertBaseToScreen: point];
|
|
|
|
[dragSource draggedImage: [self draggedImage]
|
|
|
|
endedAt: point
|
|
|
|
operation: targetMask & dragMask & operationMask];
|
|
|
|
}
|
|
|
|
else if ([dragSource respondsToSelector:
|
|
|
|
@selector(draggedImage:endedAt:deposited:)])
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
NSPoint point;
|
|
|
|
|
|
|
|
point = [theEvent locationInWindow];
|
2005-03-28 08:34:31 +00:00
|
|
|
// Convert from mouse cursor coordinate to image coordinate
|
|
|
|
point.x -= offset.width;
|
|
|
|
point.y -= offset.height;
|
2004-06-03 22:44:12 +00:00
|
|
|
point = [[theEvent window] convertBaseToScreen: point];
|
|
|
|
[dragSource draggedImage: [self draggedImage]
|
2007-04-27 18:54:58 +00:00
|
|
|
endedAt: point
|
|
|
|
deposited: deposited];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle the events for the event loop during drag and drop
|
|
|
|
*/
|
|
|
|
- (void) _handleEventDuringDragging: (NSEvent *)theEvent
|
|
|
|
{
|
|
|
|
switch ([theEvent type])
|
|
|
|
{
|
|
|
|
case NSAppKitDefined:
|
|
|
|
{
|
|
|
|
GSAppKitSubtype sub = [theEvent subtype];
|
|
|
|
|
|
|
|
switch (sub)
|
|
|
|
{
|
|
|
|
case GSAppKitWindowMoved:
|
2005-03-28 08:34:31 +00:00
|
|
|
case GSAppKitWindowResized:
|
2007-04-27 18:54:58 +00:00
|
|
|
case GSAppKitRegionExposed:
|
2004-06-03 22:44:12 +00:00
|
|
|
/*
|
|
|
|
* Keep window up-to-date with its current position.
|
|
|
|
*/
|
|
|
|
[NSApp sendEvent: theEvent];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSAppKitDraggingStatus:
|
|
|
|
NSDebugLLog(@"NSDragging", @"got GSAppKitDraggingStatus\n");
|
|
|
|
if ((int)[theEvent data1] == targetWindowRef)
|
|
|
|
{
|
2010-12-22 16:16:14 +00:00
|
|
|
NSDragOperation newTargetMask = (NSDragOperation)[theEvent data2];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
if (newTargetMask != targetMask)
|
|
|
|
{
|
|
|
|
targetMask = newTargetMask;
|
|
|
|
[self _setCursor];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSAppKitDraggingFinished:
|
|
|
|
NSLog(@"Internal: got GSAppKitDraggingFinished out of seq");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GSAppKitWindowFocusIn:
|
2007-04-27 18:54:58 +00:00
|
|
|
case GSAppKitWindowFocusOut:
|
|
|
|
case GSAppKitWindowLeave:
|
|
|
|
case GSAppKitWindowEnter:
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
2006-09-24 08:27:21 +00:00
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
default:
|
2006-11-01 09:50:00 +00:00
|
|
|
NSDebugLLog(@"NSDragging", @"dropped NSAppKitDefined (%d) event", sub);
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NSMouseMoved:
|
|
|
|
case NSLeftMouseDragged:
|
|
|
|
case NSLeftMouseDown:
|
|
|
|
case NSLeftMouseUp:
|
|
|
|
newPosition = [[theEvent window] convertBaseToScreen:
|
2007-04-27 18:54:58 +00:00
|
|
|
[theEvent locationInWindow]];
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
case NSFlagsChanged:
|
|
|
|
if ([self _updateOperationMask: theEvent])
|
|
|
|
{
|
2007-04-27 18:54:58 +00:00
|
|
|
// If flags change, send update to allow
|
|
|
|
// destination to take note.
|
|
|
|
if (destWindow)
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingUpdate
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask & operationMask
|
|
|
|
position: newPosition
|
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: destWindow];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-01 14:10:39 +00:00
|
|
|
[self sendExternalEvent: GSAppKitDraggingUpdate
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask & operationMask
|
|
|
|
position: newPosition
|
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: targetWindowRef];
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
[self _setCursor];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NSPeriodic:
|
2004-06-19 15:27:03 +00:00
|
|
|
newPosition = [NSEvent mouseLocation];
|
2004-06-03 22:44:12 +00:00
|
|
|
if (newPosition.x != dragPosition.x || newPosition.y != dragPosition.y)
|
|
|
|
{
|
|
|
|
[self _updateAndMoveImageToCorrectPosition];
|
|
|
|
}
|
2008-12-16 21:13:21 +00:00
|
|
|
else if (destWindow)
|
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingUpdate
|
|
|
|
action: dragMask & operationMask
|
|
|
|
position: newPosition
|
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: destWindow];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[self sendExternalEvent: GSAppKitDraggingUpdate
|
|
|
|
action: dragMask & operationMask
|
|
|
|
position: newPosition
|
|
|
|
timestamp: [theEvent timestamp]
|
|
|
|
toWindow: targetWindowRef];
|
|
|
|
}
|
2004-06-03 22:44:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-02-14 08:58:05 +00:00
|
|
|
NSLog(@"Internal: dropped event (%d) during dragging", (int)[theEvent type]);
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This method will move the drag image and update all associated data
|
|
|
|
*/
|
|
|
|
- (void) _updateAndMoveImageToCorrectPosition
|
|
|
|
{
|
|
|
|
//--- Store old values -----------------------------------------------------
|
|
|
|
NSWindow *oldDestWindow = destWindow;
|
|
|
|
BOOL oldDestExternal = destExternal;
|
|
|
|
int mouseWindowRef;
|
|
|
|
BOOL changeCursor = NO;
|
|
|
|
|
|
|
|
//--- Move drag image to the new position -----------------------------------
|
|
|
|
[self _moveDraggedImageToNewPosition];
|
2010-12-27 13:40:57 +00:00
|
|
|
|
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(draggedImage:movedTo:)])
|
|
|
|
{
|
|
|
|
[dragSource draggedImage: [self draggedImage] movedTo: dragPosition];
|
|
|
|
}
|
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
//--- Determine target window ---------------------------------------------
|
2005-04-01 14:10:39 +00:00
|
|
|
destWindow = [self windowAcceptingDnDunder: dragPosition
|
|
|
|
windowRef: &mouseWindowRef];
|
2004-06-03 22:44:12 +00:00
|
|
|
|
2007-04-27 18:54:58 +00:00
|
|
|
// If we are not hovering above a window that we own
|
2004-06-03 22:44:12 +00:00
|
|
|
// we are dragging to an external application.
|
|
|
|
destExternal = (mouseWindowRef != 0) && (destWindow == nil);
|
|
|
|
|
|
|
|
if (destWindow != nil)
|
|
|
|
{
|
|
|
|
dragPoint = [destWindow convertScreenToBase: dragPosition];
|
|
|
|
}
|
|
|
|
|
2010-04-10 17:48:46 +00:00
|
|
|
NSDebugLLog(@"NSDragging", @"mouse window %d (%@) at %@\n",
|
2005-03-28 08:34:31 +00:00
|
|
|
mouseWindowRef, destWindow, NSStringFromPoint(dragPosition));
|
2004-06-03 22:44:12 +00:00
|
|
|
|
|
|
|
//--- send exit message if necessary -------------------------------------
|
|
|
|
if ((mouseWindowRef != targetWindowRef) && targetWindowRef)
|
|
|
|
{
|
|
|
|
/* If we change windows and the old window is dnd aware, we send an
|
|
|
|
dnd exit */
|
|
|
|
NSDebugLLog(@"NSDragging", @"sending dnd exit\n");
|
|
|
|
|
|
|
|
if (oldDestWindow != nil)
|
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingExit
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask & operationMask
|
|
|
|
position: NSZeroPoint
|
2004-06-03 22:44:12 +00:00
|
|
|
timestamp: dragSequence
|
2007-04-27 18:54:58 +00:00
|
|
|
toWindow: oldDestWindow];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-01 14:10:39 +00:00
|
|
|
[self sendExternalEvent: GSAppKitDraggingExit
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask & operationMask
|
|
|
|
position: NSZeroPoint
|
|
|
|
timestamp: dragSequence
|
|
|
|
toWindow: targetWindowRef];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset drag mask when we switch from external to internal or back
|
|
|
|
if (oldDestExternal != destExternal)
|
|
|
|
{
|
2010-12-22 16:16:14 +00:00
|
|
|
NSDragOperation newMask;
|
2004-06-03 22:44:12 +00:00
|
|
|
|
2010-12-27 13:40:57 +00:00
|
|
|
if ([dragSource respondsToSelector:
|
|
|
|
@selector(draggingSourceOperationMaskForLocal:)])
|
|
|
|
{
|
|
|
|
newMask = [dragSource draggingSourceOperationMaskForLocal: !destExternal];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newMask = NSDragOperationCopy | NSDragOperationLink |
|
|
|
|
NSDragOperationGeneric | NSDragOperationPrivate;
|
|
|
|
}
|
|
|
|
|
2004-06-03 22:44:12 +00:00
|
|
|
if (newMask != dragMask)
|
|
|
|
{
|
|
|
|
dragMask = newMask;
|
|
|
|
changeCursor = YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mouseWindowRef == targetWindowRef && targetWindowRef)
|
|
|
|
{
|
|
|
|
// same window, sending update
|
|
|
|
NSDebugLLog(@"NSDragging", @"sending dnd pos\n");
|
|
|
|
|
2007-04-27 18:54:58 +00:00
|
|
|
// FIXME: We should only send this when the destination wantsPeriodicDraggingUpdates
|
2004-06-03 22:44:12 +00:00
|
|
|
if (destWindow != nil)
|
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingUpdate
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask & operationMask
|
|
|
|
position: dragPosition
|
|
|
|
timestamp: dragSequence
|
|
|
|
toWindow: destWindow];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-27 18:54:58 +00:00
|
|
|
[self sendExternalEvent: GSAppKitDraggingUpdate
|
|
|
|
action: dragMask & operationMask
|
|
|
|
position: dragPosition
|
|
|
|
timestamp: dragSequence
|
|
|
|
toWindow: targetWindowRef];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mouseWindowRef != 0)
|
|
|
|
{
|
|
|
|
// FIXME: We might force the cursor update here, if the
|
|
|
|
// target wants to change the cursor.
|
|
|
|
NSDebugLLog(@"NSDragging", @"sending dnd enter/pos\n");
|
|
|
|
|
|
|
|
if (destWindow != nil)
|
|
|
|
{
|
|
|
|
[self _sendLocalEvent: GSAppKitDraggingEnter
|
2007-04-27 18:54:58 +00:00
|
|
|
action: dragMask
|
|
|
|
position: dragPosition
|
|
|
|
timestamp: dragSequence
|
|
|
|
toWindow: destWindow];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-01 14:10:39 +00:00
|
|
|
[self sendExternalEvent: GSAppKitDraggingEnter
|
|
|
|
action: dragMask
|
|
|
|
position: dragPosition
|
|
|
|
timestamp: dragSequence
|
|
|
|
toWindow: mouseWindowRef];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (targetWindowRef != mouseWindowRef)
|
|
|
|
{
|
|
|
|
targetWindowRef = mouseWindowRef;
|
|
|
|
changeCursor = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changeCursor)
|
|
|
|
{
|
|
|
|
[self _setCursor];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the dragged image immediately to the position indicated by
|
|
|
|
* the instance variable newPosition.
|
|
|
|
*
|
|
|
|
* In doing so it will update the dragPosition instance variables.
|
|
|
|
*/
|
|
|
|
- (void) _moveDraggedImageToNewPosition
|
|
|
|
{
|
|
|
|
dragPosition = newPosition;
|
2005-03-28 08:34:31 +00:00
|
|
|
[GSServerForWindow(_window) movewindow:
|
|
|
|
NSMakePoint(newPosition.x - offset.width, newPosition.y - offset.height)
|
|
|
|
: [_window windowNumber]];
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-28 08:34:31 +00:00
|
|
|
/*
|
|
|
|
* NB. screenPoint here is the position of the mouse cursor.
|
|
|
|
*/
|
2004-06-03 22:44:12 +00:00
|
|
|
- (void) _slideDraggedImageTo: (NSPoint)screenPoint
|
2005-03-28 08:34:31 +00:00
|
|
|
numberOfSteps: (int)steps
|
|
|
|
delay: (float)delay
|
|
|
|
waitAfterSlide: (BOOL)waitFlag
|
2004-06-03 22:44:12 +00:00
|
|
|
{
|
2005-03-28 08:34:31 +00:00
|
|
|
/* If we do not need multiple redrawing, just move the image immediately
|
|
|
|
* to its desired spot.
|
|
|
|
*/
|
2004-06-03 22:44:12 +00:00
|
|
|
if (steps < 2)
|
|
|
|
{
|
|
|
|
newPosition = screenPoint;
|
|
|
|
[self _moveDraggedImageToNewPosition];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[NSEvent startPeriodicEventsAfterDelay: delay withPeriod: delay];
|
|
|
|
|
|
|
|
// Use the event loop to redraw the image repeatedly.
|
|
|
|
// Using the event loop to allow the application to process
|
|
|
|
// expose events.
|
|
|
|
while (steps)
|
|
|
|
{
|
|
|
|
NSEvent *theEvent = [NSApp nextEventMatchingMask: NSPeriodicMask
|
|
|
|
untilDate: [NSDate distantFuture]
|
|
|
|
inMode: NSEventTrackingRunLoopMode
|
|
|
|
dequeue: YES];
|
|
|
|
|
|
|
|
if ([theEvent type] != NSPeriodic)
|
|
|
|
{
|
|
|
|
NSDebugLLog (@"NSDragging",
|
|
|
|
@"Unexpected event type: %d during slide",
|
2013-02-14 08:58:05 +00:00
|
|
|
(int)[theEvent type]);
|
2004-06-03 22:44:12 +00:00
|
|
|
}
|
|
|
|
newPosition.x = (screenPoint.x + ((float) steps - 1.0)
|
|
|
|
* dragPosition.x) / ((float) steps);
|
|
|
|
newPosition.y = (screenPoint.y + ((float) steps - 1.0)
|
|
|
|
* dragPosition.y) / ((float) steps);
|
|
|
|
|
|
|
|
[self _moveDraggedImageToNewPosition];
|
|
|
|
steps--;
|
|
|
|
}
|
|
|
|
[NSEvent stopPeriodicEvents];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (waitFlag)
|
|
|
|
{
|
|
|
|
[NSThread sleepUntilDate:
|
|
|
|
[NSDate dateWithTimeIntervalSinceNow: delay * 2.0]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|