25 @class _CPDOMDataTransferPasteboard
29 #define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window])
31 var CPDragServerPreviousEvent = nil,
32 CPDragServerPeriodicUpdateInterval = 0.05;
34 var CPSharedDragServer = nil;
36 var CPDragServerSource = nil,
37 CPDragServerDraggingInfo = nil;
51 return [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard];
53 return [[
CPDragServer sharedDragServer] draggingPasteboard];
65 - (CGPoint)draggingLocation
67 return [[
CPDragServer sharedDragServer] draggingLocation];
70 - (
CPWindow)draggingDestinationWindow
77 return [[
self draggedView] image];
80 - (CGPoint)draggedImageLocation
82 return [
self draggedViewLocation];
90 - (CGPoint)draggedViewLocation
94 return [DRAGGING_WINDOW([dragServer draggingDestination]) convertPlatformWindowToBase:[[dragServer draggedView] frame].origin];
99 var CPDraggingSource_draggedImage_movedTo_ = 1 << 0,
100 CPDraggingSource_draggedImage_endedAt_operation_ = 1 << 1,
101 CPDraggingSource_draggedView_movedTo_ = 1 << 2,
102 CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3;
112 BOOL _isDraggingImage;
114 CGSize _draggingOffset;
119 unsigned _implementedDraggingSourceMethods;
121 CGPoint _draggingLocation;
122 id _draggingDestination;
123 BOOL _draggingDestinationWantsPeriodicUpdates;
125 CGPoint _startDragLocation;
126 BOOL _shouldSlideBack;
127 unsigned _dragOperation;
146 if (!CPSharedDragServer)
149 return CPSharedDragServer;
161 _draggedWindow = [[
CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessWindowMask];
163 [_draggedWindow setLevel:CPDraggingWindowLevel];
169 - (id)draggingDestination
171 return _draggingDestination;
174 - (CGPoint)draggingLocation
176 return _draggingLocation
179 - (void)draggingStartedInPlatformWindow:(
CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation
181 if (_isDraggingImage)
183 if ([_draggingSource respondsToSelector:
@selector(draggedImage:beganAt:)])
184 [_draggingSource draggedImage:[_draggedView image] beganAt:aLocation];
188 if ([_draggingSource respondsToSelector:
@selector(draggedView:beganAt:)])
189 [_draggingSource draggedView:_draggedView beganAt:aLocation];
193 [_draggedWindow orderFront:self];
196 - (void)draggingSourceUpdatedWithGlobalLocation:(CGPoint)aGlobalLocation
200 var
frame = [_draggedWindow frame];
201 frame.origin.x = aGlobalLocation.x - _draggingOffset.
width;
202 frame.origin.y = aGlobalLocation.y - _draggingOffset.height;
203 [_draggedWindow _setFrame:frame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
206 if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_)
207 [_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation];
209 else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_movedTo_)
210 [_draggingSource draggedView:_draggedView movedTo:aGlobalLocation];
213 - (CPDragOperation)draggingUpdatedInPlatformWindow:(
CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation
215 [_draggingUpdateTimer invalidate];
216 _draggingUpdateTimer = nil;
220 draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]];
222 if (draggingDestination)
223 _draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation];
225 if (draggingDestination !== _draggingDestination)
227 if ([_draggingDestination respondsToSelector:
@selector(draggingExited:)])
228 [_draggingDestination draggingExited:CPDragServerDraggingInfo];
230 _draggingDestination = draggingDestination;
232 if ([_draggingDestination respondsToSelector:
@selector(wantsPeriodicDraggingUpdates)])
233 _draggingDestinationWantsPeriodicUpdates = [_draggingDestination wantsPeriodicDraggingUpdates];
235 _draggingDestinationWantsPeriodicUpdates = YES;
237 if ([_draggingDestination respondsToSelector:
@selector(draggingEntered:)])
238 dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo];
240 else if ([_draggingDestination respondsToSelector:
@selector(draggingUpdated:)])
241 dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo];
243 if (!_draggingDestination)
247 if (_draggingDestinationWantsPeriodicUpdates)
251 userInfo:@{ "platformWindow":aPlatformWindow, "location":aLocation }
254 var scrollView = [_draggingDestination isKindOfClass:[
CPView class]] ? [_draggingDestination enclosingScrollView] : nil;
257 var contentView = [scrollView contentView],
258 bounds = [contentView bounds],
259 insetBounds = CGRectInset(bounds, 30, 30),
260 eventLocation = [contentView convertPoint:_draggingLocation fromView:nil],
264 if (!CGRectContainsPoint(insetBounds, eventLocation))
266 if ([scrollView hasVerticalScroller])
268 if (eventLocation.y < CGRectGetMinY(insetBounds))
269 deltaY = CGRectGetMinY(insetBounds) - eventLocation.y;
270 else if (eventLocation.y > CGRectGetMaxY(insetBounds))
271 deltaY = CGRectGetMaxY(insetBounds) - eventLocation.y;
272 if (deltaY < -insetBounds.size.height)
273 deltaY = -insetBounds.size.height;
274 if (deltaY > insetBounds.size.height)
275 deltaY = insetBounds.size.height;
278 if ([scrollView hasHorizontalScroller])
280 if (eventLocation.x < CGRectGetMinX(insetBounds))
281 deltaX = CGRectGetMinX(insetBounds) - eventLocation.x;
282 else if (eventLocation.x > CGRectGetMaxX(insetBounds))
283 deltaX = CGRectGetMaxX(insetBounds) - eventLocation.x;
284 if (deltaX < -insetBounds.size.width)
285 deltaX = -insetBounds.size.
width;
286 if (deltaX > insetBounds.size.width)
287 deltaX = insetBounds.size.width;
290 var scrollPoint = CGPointMake(bounds.origin.x - deltaX, bounds.origin.y - deltaY);
292 [contentView scrollToPoint:scrollPoint];
293 [[scrollView _headerView] scrollPoint:scrollPoint];
299 return dragOperation;
302 - (void)_sendPeriodicDraggingUpdate:(
CPTimer)aTimer
305 _dragOperation = [
self draggingUpdatedInPlatformWindow:[userInfo objectForKey:@"platformWindow"]
306 location:[userInfo objectForKey:@"location"]];
309 - (void)draggingEndedInPlatformWindow:(
CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation
311 [_draggingUpdateTimer invalidate];
312 _draggingUpdateTimer = nil;
314 [_draggedView removeFromSuperview];
317 [_draggedWindow orderOut:self];
319 if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endedAt_operation_)
320 [_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation];
321 else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_)
322 [_draggingSource draggedView:_draggedView endedAt:aLocation operation:anOperation];
327 - (void)performDragOperationInPlatformWindow:(
CPPlatformWindow)aPlatformWindow
329 if (_draggingDestination &&
330 (![_draggingDestination respondsToSelector:
@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) &&
331 (![_draggingDestination respondsToSelector:
@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) &&
332 [_draggingDestination respondsToSelector:
@selector(concludeDragOperation:)])
333 [_draggingDestination concludeDragOperation:CPDragServerDraggingInfo];
348 - (void)dragView:(
CPView)aView fromWindow:(
CPWindow)aWindow at:(CGPoint)viewLocation offset:(CGSize)mouseOffset event:(
CPEvent)mouseDownEvent pasteboard:(
CPPasteboard)aPasteboard source:(
id)aSourceObject slideBack:(BOOL)slideBack
352 _draggedView = aView;
354 _draggingSource = aSourceObject;
355 _draggingDestination = nil;
356 _shouldSlideBack = slideBack;
360 var mouseDownWindow = [mouseDownEvent window],
361 mouseDownEventLocation = [mouseDownEvent locationInWindow];
363 if (mouseDownEventLocation)
366 mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation];
368 _draggingOffset = CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y);
371 _draggingOffset = CGSizeMakeZero();
374 [_draggedWindow setPlatformWindow:[aWindow platformWindow]];
376 [aView setFrameOrigin:CGPointMakeZero()];
378 var mouseLocation = [
CPEvent mouseLocation],
379 viewSize = [aView frameSize],
380 startDragLocationX = mouseLocation.x - _draggingOffset.
width,
381 startDragLocationY = mouseLocation.y - _draggingOffset.height,
382 draggedWindowFrame = CGRectMake(startDragLocationX, startDragLocationY, viewSize.
width, viewSize.height);
385 _startDragLocation = CGPointMake(startDragLocationX, startDragLocationY);
387 [_draggedWindow _setFrame:draggedWindowFrame display:YES animate:NO constrainWidth:NO constrainHeight:NO];
389 [[_draggedWindow contentView] addSubview:aView];
391 _implementedDraggingSourceMethods = 0;
393 if (_draggedView === _imageView)
395 if ([_draggingSource respondsToSelector:
@selector(draggedImage:movedTo:)])
396 _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_;
398 if ([_draggingSource respondsToSelector:
@selector(draggedImage:endedAt:operation:)])
399 _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endedAt_operation_;
403 if ([_draggingSource respondsToSelector:
@selector(draggedView:movedTo:)])
404 _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_movedTo_;
406 if ([_draggingSource respondsToSelector:
@selector(draggedView:endedAt:operation:)])
407 _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_endedAt_operation_;
412 [
self draggingStartedInPlatformWindow:[aWindow platformWindow] globalLocation:mouseLocation];
413 [
self trackDragging:mouseDownEvent];
429 - (void)dragImage:(
CPImage)anImage fromWindow:(
CPWindow)aWindow at:(CGPoint)imageLocation offset:(CGSize)mouseOffset event:(
CPEvent)anEvent pasteboard:(
CPPasteboard)aPasteboard source:(
id)aSourceObject slideBack:(BOOL)slideBack
431 _isDraggingImage = YES;
433 var imageSize = [anImage
size];
436 _imageView = [[
CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)];
438 [_imageView setImage:anImage];
440 [
self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack];
443 - (void)trackDragging:(
CPEvent)anEvent
445 var type = [anEvent type],
446 platformWindow = [_draggedWindow platformWindow],
447 platformWindowLocation = [[anEvent window] convertBaseToPlatformWindow:[anEvent locationInWindow]];
453 [
self performDragOperationInPlatformWindow:platformWindow];
455 [
self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:_dragOperation];
462 var characters = [anEvent characters];
467 [
self draggingEndedInPlatformWindow:platformWindow globalLocation:CGPointMakeZero() operation:_dragOperation];
473 [
self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation];
474 _dragOperation = [
self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation];
478 [CPApp setTarget:self selector:@selector(trackDragging:)
479 forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPKeyDownMask
480 untilDate:nil inMode:0 dequeue:YES];
485 @implementation CPDragServer (CPSynthesizedAccessors)
500 return _draggedWindow;
514 - (CGSize)draggingOffset
516 return _draggingOffset;
524 return _draggingPasteboard;
532 return _draggingSource;