mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 03:21:04 +00:00
DnD bugfixes and cleanups
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@20985 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0f37b71ea6
commit
bd3e29cb15
3 changed files with 165 additions and 98 deletions
|
@ -1,3 +1,11 @@
|
|||
2005-03-28 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/GSDragView.m: Fix a few bugs exposed by windows port and
|
||||
tidy/add comments to clarify operation. When initiating DnD session,
|
||||
take offset argument into account rather than ignoring it.
|
||||
* Headers/Additions/GNUstepGUI/GSDrafView.h: Improve comments and
|
||||
change offset to be NSSize rather thgan NSPoint.
|
||||
|
||||
2005-03-21 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Tools/gsnd/portaudio/pa_unix_oss/pa_unix_oss.c: Fix for FreeBSD
|
||||
|
|
|
@ -37,41 +37,71 @@
|
|||
@class NSMutableDictionary;
|
||||
|
||||
/*
|
||||
used in the operation mask to indicate that the
|
||||
user can not change the drag action by
|
||||
pressing modifiers.
|
||||
*/
|
||||
* used in the operation mask to indicate that the
|
||||
* user can not change the drag action by
|
||||
* pressing modifiers.
|
||||
*/
|
||||
|
||||
#define NSDragOperationIgnoresModifiers 0xffff
|
||||
|
||||
@interface GSDragView : NSView <NSDraggingInfo>
|
||||
{
|
||||
NSCell *dragCell; // the graphics that is dragged
|
||||
NSPasteboard *dragPasteboard; // the pasteboard with the dragged data
|
||||
id destWindow; // NSWindow in this application that is the current target
|
||||
NSPoint dragPoint; // in base coordinates, only valid when destWindow != nil
|
||||
int dragSequence;
|
||||
id dragSource; // the NSObject source of the dragging
|
||||
unsigned int dragMask; // Operations supported by the source
|
||||
unsigned int operationMask; // user specified operation mask (key modifiers).
|
||||
// this is either a mask of type _NSDragOperation,
|
||||
// or NSDragOperationIgnoresModifiers, which
|
||||
// is defined as 0xffff
|
||||
BOOL slideBack; // slide the image back when drag fails?
|
||||
// the graphics that is dragged
|
||||
NSCell *dragCell;
|
||||
|
||||
/* information used in the drag and drop event loop */
|
||||
NSPoint offset; // offset of image w.r.t. cursor
|
||||
NSPoint dragPosition; // current drag position in screen coordinates
|
||||
NSPoint newPosition; // drag position, not yet processed
|
||||
// the pasteboard with the dragged data
|
||||
NSPasteboard *dragPasteboard;
|
||||
|
||||
int targetWindowRef; // OS specific current window target of the drag operation
|
||||
unsigned int targetMask; // Operations supported by the target, only valid if
|
||||
// targetWindowRef isn't 0
|
||||
// NSWindow in this application that is the current target
|
||||
NSWindow *destWindow;
|
||||
|
||||
BOOL destExternal; // YES if target and source are in a different application
|
||||
BOOL isDragging; // YES if we are currently dragging
|
||||
// Screen coordinates of mouse pointer, only valid when destWindow != nil
|
||||
NSPoint dragPoint;
|
||||
|
||||
NSMutableDictionary *cursors; // Cache for cursors
|
||||
int dragSequence;
|
||||
|
||||
// the source of the dragging operation
|
||||
id dragSource;
|
||||
|
||||
// Operations supported by the source
|
||||
unsigned int dragMask;
|
||||
|
||||
/* User specified operation mask (key modifiers).
|
||||
* This is either a mask of type _NSDragOperation,
|
||||
* or NSDragOperationIgnoresModifiers, which
|
||||
* is defined as 0xffff
|
||||
*/
|
||||
unsigned int operationMask;
|
||||
|
||||
// slide the image back when drag fails?
|
||||
BOOL slideBack;
|
||||
|
||||
/* The following information used in the drag and drop event loop
|
||||
*/
|
||||
|
||||
// offset of image w.r.t. cursor
|
||||
NSSize offset;
|
||||
|
||||
// current drag (mouse cursor) position in screen coordinates
|
||||
NSPoint dragPosition;
|
||||
|
||||
// drag (mouse cursor) position, not yet processed
|
||||
NSPoint newPosition;
|
||||
|
||||
// OS specific current window target of the drag operation
|
||||
int targetWindowRef;
|
||||
|
||||
// Operations supported by the target, only valid if targetWindowRef isn't 0
|
||||
unsigned int targetMask;
|
||||
|
||||
// YES if target and source are in a different application
|
||||
BOOL destExternal;
|
||||
|
||||
// YES if we are currently dragging
|
||||
BOOL isDragging;
|
||||
|
||||
// Cache for cursors
|
||||
NSMutableDictionary *cursors;
|
||||
}
|
||||
|
||||
+ (GSDragView*) sharedDragView;
|
||||
|
|
|
@ -58,27 +58,29 @@
|
|||
@end
|
||||
|
||||
@interface GSDragView (Private)
|
||||
- (void) _setupWindowAt: (NSPoint) dragStart image: (NSImage*)anImage;
|
||||
- (void) _setupWindowFor: (NSImage*)anImage
|
||||
mousePosition: (NSPoint)mPoint
|
||||
imagePosition: (NSPoint)iPoint;
|
||||
- (void) _clearupWindow;
|
||||
- (BOOL) _updateOperationMask: (NSEvent*) theEvent;
|
||||
- (void) _setCursor;
|
||||
- (void) _sendLocalEvent: (GSAppKitSubtype)subtype
|
||||
action: (NSDragOperation)action
|
||||
position: (NSPoint)eventLocation
|
||||
timestamp: (NSTimeInterval)time
|
||||
toWindow: (NSWindow*)dWindow;
|
||||
action: (NSDragOperation)action
|
||||
position: (NSPoint)eventLocation
|
||||
timestamp: (NSTimeInterval)time
|
||||
toWindow: (NSWindow*)dWindow;
|
||||
- (void) _sendExternalEvent: (GSAppKitSubtype)subtype
|
||||
action: (NSDragOperation)action
|
||||
position: (NSPoint)eventLocation
|
||||
timestamp: (NSTimeInterval)time
|
||||
toWindow: (int)dWindowNumber;
|
||||
action: (NSDragOperation)action
|
||||
position: (NSPoint)eventLocation
|
||||
timestamp: (NSTimeInterval)time
|
||||
toWindow: (int)dWindowNumber;
|
||||
- (void) _handleDrag: (NSEvent*)theEvent;
|
||||
- (void) _handleEventDuringDragging: (NSEvent *)theEvent;
|
||||
- (void) _updateAndMoveImageToCorrectPosition;
|
||||
- (void) _moveDraggedImageToNewPosition;
|
||||
- (void) _slideDraggedImageTo: (NSPoint)screenPoint
|
||||
numberOfSteps: (int) steps
|
||||
delay: (float) delay
|
||||
numberOfSteps: (int) steps
|
||||
delay: (float) delay
|
||||
waitAfterSlide: (BOOL) waitFlag;
|
||||
- (NSWindow*) _windowAcceptingDnDunder: (NSPoint) mouseLocation
|
||||
windowRef: (int*)mouseWindowRef;
|
||||
|
@ -201,15 +203,12 @@ static GSDragView *sharedDragView = nil;
|
|||
|
||||
- (NSPoint) draggedImageLocation
|
||||
{
|
||||
NSPoint loc;
|
||||
NSPoint loc = dragPoint;
|
||||
|
||||
if (dragSource)
|
||||
{
|
||||
loc = NSMakePoint(dragPoint.x - offset.x, dragPoint.y - offset.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = dragPoint;
|
||||
loc.x -= offset.width;
|
||||
loc.y -= offset.height;
|
||||
}
|
||||
|
||||
return loc;
|
||||
|
@ -226,10 +225,6 @@ static GSDragView *sharedDragView = nil;
|
|||
[dragCell drawWithFrame: [self frame] inView: self];
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - use initialOffset
|
||||
*/
|
||||
- (void) dragImage: (NSImage*)anImage
|
||||
at: (NSPoint)screenLocation
|
||||
offset: (NSSize)initialOffset
|
||||
|
@ -238,6 +233,7 @@ static GSDragView *sharedDragView = nil;
|
|||
source: (id)sourceObject
|
||||
slideBack: (BOOL)slideFlag
|
||||
{
|
||||
NSPoint eventPoint;
|
||||
ASSIGN(dragPasteboard, pboard);
|
||||
ASSIGN(dragSource, sourceObject);
|
||||
dragSequence = [event timestamp];
|
||||
|
@ -249,7 +245,22 @@ static GSDragView *sharedDragView = nil;
|
|||
destExternal = NO;
|
||||
|
||||
NSDebugLLog(@"NSDragging", @"Start drag with %@", [pboard types]);
|
||||
[self _setupWindowAt: screenLocation image: anImage];
|
||||
|
||||
/*
|
||||
* The position of the mouse is the event location plus any offset
|
||||
* provided. We convert this from window coordinates to screen
|
||||
* coordinates, then determine the screen offset between the mouse
|
||||
* pointer and the dragged image.
|
||||
*/
|
||||
eventPoint = [event locationInWindow];
|
||||
eventPoint.x += initialOffset.width;
|
||||
eventPoint.y += initialOffset.height;
|
||||
eventPoint = [[event window] convertBaseToScreen: eventPoint];
|
||||
|
||||
[self _setupWindowFor: anImage
|
||||
mousePosition: eventPoint
|
||||
imagePosition: screenLocation];
|
||||
|
||||
isDragging = YES;
|
||||
[self _handleDrag: event];
|
||||
isDragging = NO;
|
||||
|
@ -257,8 +268,14 @@ static GSDragView *sharedDragView = nil;
|
|||
DESTROY(dragPasteboard);
|
||||
}
|
||||
|
||||
- (void) slideDraggedImageTo: (NSPoint) point
|
||||
- (void) slideDraggedImageTo: (NSPoint)point
|
||||
{
|
||||
/*
|
||||
* Convert point from coordinates of image to coordinates of mouse
|
||||
* cursor for internal use.
|
||||
*/
|
||||
point.y += offset.height;
|
||||
point.y += offset.height;
|
||||
[self _slideDraggedImageTo: point
|
||||
numberOfSteps: SLIDE_NR_OF_STEPS
|
||||
delay: SLIDE_TIME_STEP
|
||||
|
@ -305,27 +322,28 @@ static GSDragView *sharedDragView = nil;
|
|||
- dragCell is initialized with the image to drag.
|
||||
- all instance variables pertaining to moving the window are initialized
|
||||
*/
|
||||
- (void) _setupWindowAt: (NSPoint) dragStart image: (NSImage*)anImage
|
||||
- (void) _setupWindowFor: (NSImage*)anImage
|
||||
mousePosition: (NSPoint)mPoint
|
||||
imagePosition: (NSPoint)iPoint
|
||||
{
|
||||
NSSize imageSize;
|
||||
NSSize imageSize;
|
||||
|
||||
if (anImage == nil)
|
||||
{
|
||||
anImage = [NSImage imageNamed: @"common_Close"];
|
||||
}
|
||||
|
||||
[dragCell setImage: anImage];
|
||||
imageSize = [anImage size];
|
||||
offset = NSMakePoint (imageSize.width / 2.0, imageSize.height / 2.0);
|
||||
[dragCell setImage: anImage];
|
||||
|
||||
[_window setFrame: NSMakeRect (dragStart.x - offset.x,
|
||||
dragStart.y - offset.y,
|
||||
imageSize.width, imageSize.height)
|
||||
display: NO];
|
||||
|
||||
/* setup the coordinates, used for moving the view around */
|
||||
dragPosition = dragStart;
|
||||
newPosition = dragStart;
|
||||
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];
|
||||
|
||||
// Only display the image
|
||||
[GSServerForWindow(_window) restrictWindow: [_window windowNumber]
|
||||
|
@ -558,6 +576,8 @@ static GSDragView *sharedDragView = nil;
|
|||
BOOL deposited;
|
||||
|
||||
startPoint = [eWindow convertBaseToScreen: [theEvent locationInWindow]];
|
||||
startPoint.x -= offset.width;
|
||||
startPoint.y -= offset.height;
|
||||
NSDebugLLog(@"NSDragging", @"Drag window origin %d %d\n", startPoint.x, startPoint.y);
|
||||
|
||||
// Notify the source that dragging has started
|
||||
|
@ -565,7 +585,7 @@ static GSDragView *sharedDragView = nil;
|
|||
@selector(draggedImage:beganAt:)])
|
||||
{
|
||||
[dragSource draggedImage: [self draggedImage]
|
||||
beganAt: startPoint];
|
||||
beganAt: startPoint];
|
||||
}
|
||||
|
||||
// --- Setup up the masks for the drag operation ---------------------
|
||||
|
@ -608,19 +628,20 @@ static GSDragView *sharedDragView = nil;
|
|||
if ((targetWindowRef != 0)
|
||||
&& ((targetMask & dragMask & operationMask) != NSDragOperationNone))
|
||||
{
|
||||
// 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.
|
||||
/* 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.
|
||||
*/
|
||||
[self _clearupWindow];
|
||||
[cursorBeforeDrag set];
|
||||
NSDebugLLog(@"NSDragging", @"sending dnd drop\n");
|
||||
|
@ -659,6 +680,9 @@ static GSDragView *sharedDragView = nil;
|
|||
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
|
||||
|
@ -680,6 +704,7 @@ static GSDragView *sharedDragView = nil;
|
|||
switch (sub)
|
||||
{
|
||||
case GSAppKitWindowMoved:
|
||||
case GSAppKitWindowResized:
|
||||
/*
|
||||
* Keep window up-to-date with its current position.
|
||||
*/
|
||||
|
@ -733,7 +758,7 @@ static GSDragView *sharedDragView = nil;
|
|||
{
|
||||
[self _sendLocalEvent: GSAppKitDraggingUpdate
|
||||
action: dragMask & operationMask
|
||||
position: NSMakePoint(newPosition.x + offset.x, newPosition.y + offset.y)
|
||||
position: newPosition
|
||||
timestamp: [theEvent timestamp]
|
||||
toWindow: destWindow];
|
||||
}
|
||||
|
@ -741,7 +766,7 @@ static GSDragView *sharedDragView = nil;
|
|||
{
|
||||
[self _sendExternalEvent: GSAppKitDraggingUpdate
|
||||
action: dragMask & operationMask
|
||||
position: NSMakePoint(newPosition.x + offset.x, newPosition.y + offset.y)
|
||||
position: newPosition
|
||||
timestamp: [theEvent timestamp]
|
||||
toWindow: targetWindowRef];
|
||||
}
|
||||
|
@ -770,14 +795,13 @@ static GSDragView *sharedDragView = nil;
|
|||
BOOL oldDestExternal = destExternal;
|
||||
int mouseWindowRef;
|
||||
BOOL changeCursor = NO;
|
||||
NSPoint mouseLocation = NSMakePoint(dragPosition.x + offset.x, dragPosition.y + offset.y);
|
||||
|
||||
//--- Move drag image to the new position -----------------------------------
|
||||
[self _moveDraggedImageToNewPosition];
|
||||
|
||||
//--- Determine target window ---------------------------------------------
|
||||
destWindow = [self _windowAcceptingDnDunder: mouseLocation
|
||||
windowRef: &mouseWindowRef];
|
||||
destWindow = [self _windowAcceptingDnDunder: dragPosition
|
||||
windowRef: &mouseWindowRef];
|
||||
|
||||
// If we have are not hovering above a window that we own
|
||||
// we are dragging to an external application.
|
||||
|
@ -788,7 +812,8 @@ static GSDragView *sharedDragView = nil;
|
|||
dragPoint = [destWindow convertScreenToBase: dragPosition];
|
||||
}
|
||||
|
||||
NSDebugLLog(@"NSDragging", @"mouse window %d\n", mouseWindowRef);
|
||||
NSDebugLLog(@"NSDragging", @"mouse window %d (%x) at %@\n",
|
||||
mouseWindowRef, destWindow, NSStringFromPoint(dragPosition));
|
||||
|
||||
//--- send exit message if necessary -------------------------------------
|
||||
if ((mouseWindowRef != targetWindowRef) && targetWindowRef)
|
||||
|
@ -837,7 +862,7 @@ static GSDragView *sharedDragView = nil;
|
|||
{
|
||||
[self _sendLocalEvent: GSAppKitDraggingUpdate
|
||||
action: dragMask & operationMask
|
||||
position: mouseLocation
|
||||
position: dragPosition
|
||||
timestamp: dragSequence
|
||||
toWindow: destWindow];
|
||||
}
|
||||
|
@ -845,7 +870,7 @@ static GSDragView *sharedDragView = nil;
|
|||
{
|
||||
[self _sendExternalEvent: GSAppKitDraggingUpdate
|
||||
action: dragMask & operationMask
|
||||
position: mouseLocation
|
||||
position: dragPosition
|
||||
timestamp: dragSequence
|
||||
toWindow: targetWindowRef];
|
||||
}
|
||||
|
@ -859,16 +884,16 @@ static GSDragView *sharedDragView = nil;
|
|||
if (destWindow != nil)
|
||||
{
|
||||
[self _sendLocalEvent: GSAppKitDraggingEnter
|
||||
action: dragMask
|
||||
position: mouseLocation
|
||||
timestamp: dragSequence
|
||||
toWindow: destWindow];
|
||||
action: dragMask
|
||||
position: dragPosition
|
||||
timestamp: dragSequence
|
||||
toWindow: destWindow];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self _sendExternalEvent: GSAppKitDraggingEnter
|
||||
action: dragMask
|
||||
position: mouseLocation
|
||||
position: dragPosition
|
||||
timestamp: dragSequence
|
||||
toWindow: mouseWindowRef];
|
||||
}
|
||||
|
@ -895,19 +920,23 @@ static GSDragView *sharedDragView = nil;
|
|||
- (void) _moveDraggedImageToNewPosition
|
||||
{
|
||||
dragPosition = newPosition;
|
||||
[GSServerForWindow(_window) movewindow: NSMakePoint(newPosition.x - offset.x,
|
||||
newPosition.y - offset.y)
|
||||
: [_window windowNumber]];
|
||||
[GSServerForWindow(_window) movewindow:
|
||||
NSMakePoint(newPosition.x - offset.width, newPosition.y - offset.height)
|
||||
: [_window windowNumber]];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NB. screenPoint here is the position of the mouse cursor.
|
||||
*/
|
||||
- (void) _slideDraggedImageTo: (NSPoint)screenPoint
|
||||
numberOfSteps: (int) steps
|
||||
delay: (float) delay
|
||||
waitAfterSlide: (BOOL) waitFlag
|
||||
numberOfSteps: (int)steps
|
||||
delay: (float)delay
|
||||
waitAfterSlide: (BOOL)waitFlag
|
||||
{
|
||||
// --- If we do not need multiple redrawing, just move the image immediately
|
||||
// to its desired spot.
|
||||
/* If we do not need multiple redrawing, just move the image immediately
|
||||
* to its desired spot.
|
||||
*/
|
||||
if (steps < 2)
|
||||
{
|
||||
newPosition = screenPoint;
|
||||
|
@ -963,8 +992,8 @@ static GSDragView *sharedDragView = nil;
|
|||
|
||||
*mouseWindowRef = 0;
|
||||
win = [GSServerForWindow(_window) findWindowAt: mouseLocation
|
||||
windowRef: mouseWindowRef
|
||||
excluding: [_window windowNumber]];
|
||||
windowRef: mouseWindowRef
|
||||
excluding: [_window windowNumber]];
|
||||
|
||||
return GSWindowWithNumber(win);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue