diff --git a/AppKit/CPCompatibility.j b/AppKit/CPCompatibility.j index e5e30c41fe..b381cd3593 100644 --- a/AppKit/CPCompatibility.j +++ b/AppKit/CPCompatibility.j @@ -35,17 +35,18 @@ CPCSSRGBAFeature = 1 << 5; CPHTMLCanvasFeature = 1 << 6; CPHTMLContentEditableFeature = 1 << 7; +CPHTMLDragAndDropFeature = 1 << 8; -CPJavascriptInnerTextFeature = 1 << 8; -CPJavascriptTextContentFeature = 1 << 9; -CPJavascriptClipboardEventsFeature = 1 << 10; -CPJavascriptClipboardAccessFeature = 1 << 11; -CPJavaScriptCanvasDrawFeature = 1 << 12; -CPJavaScriptCanvasTransformFeature = 1 << 13; +CPJavascriptInnerTextFeature = 1 << 9; +CPJavascriptTextContentFeature = 1 << 10; +CPJavascriptClipboardEventsFeature = 1 << 11; +CPJavascriptClipboardAccessFeature = 1 << 12; +CPJavaScriptCanvasDrawFeature = 1 << 13; +CPJavaScriptCanvasTransformFeature = 1 << 14; -CPVMLFeature = 1 << 14; +CPVMLFeature = 1 << 15; -CPJavascriptRemedialKeySupport = 1 << 15; +CPJavascriptRemedialKeySupport = 1 << 16; CPJavaScriptShadowFeature = 1 << 20; CPJavaScriptNegativeMouseWheelValues = 1 << 22; @@ -54,7 +55,8 @@ CPJavaScriptMouseWheelValues_8_15 = 1 << 23 CPOpacityRequiresFilterFeature = 1 << 24; //Internet explorer does not allow dynamically changing the type of an input element -CPInputTypeCanBeChangedFeature = 1 << 25; +CPInputTypeCanBeChangedFeature = 1 << 25; + @@ -100,6 +102,7 @@ else if (USER_AGENT.indexOf("AppleWebKit/") != -1) // Features we can only be sure of with WebKit (no known independent tests) PLATFORM_FEATURES |= CPCSSRGBAFeature; PLATFORM_FEATURES |= CPHTMLContentEditableFeature; + PLATFORM_FEATURES |= CPHTMLDragAndDropFeature; PLATFORM_FEATURES |= CPJavascriptClipboardEventsFeature; PLATFORM_FEATURES |= CPJavascriptClipboardAccessFeature; PLATFORM_FEATURES |= CPJavaScriptShadowFeature; diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index 5716dc0617..9697a18d27 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -29,73 +29,25 @@ #import "Platform/Platform.h" -#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window]) +CPDragOperationNone = 0, +CPDragOperationCopy = 1 << 1, +CPDragOperationLink = 1 << 1, +CPDragOperationGeneric = 1 << 2, +CPDragOperationPrivate = 1 << 3, +CPDragOperationMove = 1 << 4, +CPDragOperationDelete = 1 << 5, +CPDragOperationEvery = -1; -var CPSharedDragServer = nil; - -var CPDragServerView = nil, - CPDragServerSource = nil, - CPDragServerWindow = nil, - CPDragServerOffset = nil, - CPDragServerLocation = nil, - CPDragServerPasteboard = nil, - CPDragServerDestination = nil, - CPDragServerDraggingInfo = nil, - CPDragServerPreviousEvent = nil, - CPDragServerAutoscrollInterval = nil; - -var CPDragServerIsDraggingImage = NO, - - CPDragServerShouldSendDraggedViewMovedTo = NO, - CPDragServerShouldSendDraggedImageMovedTo = NO, - - CPDragServerShouldSendDraggedViewEndedAtOperation = NO, - CPDragServerShouldSendDraggedImageEndedAtOperation = NO; +#define DRAGGING_WINDOW(anObject) ([anObject isKindOfClass:[CPWindow class]] ? anObject : [anObject window]) +var CPDragServerPreviousEvent = nil, +CPDragServerAutoscrollInterval = nil; +/* var CPDragServerAutoscroll = function() { [CPDragServerSource autoscroll:CPDragServerPreviousEvent]; } -var CPDragServerStartDragging = function(anEvent) -{ - CPDragServerUpdateDragging(anEvent); -} - -var CPDragServerUpdateDragging = function(anEvent) -{ - var globalLocation = [[anEvent window] convertBaseToGlobal:[anEvent locationInWindow]]; - - // If this is a mouse up, then complete the drag. - if([anEvent type] == CPLeftMouseUp) - { - if (CPDragServerAutoscrollInterval !== nil) - clearInterval(CPDragServerAutoscrollInterval); - - CPDragServerAutoscrollInterval = nil; - - CPDragServerLocation = [DRAGGING_WINDOW(CPDragServerDestination) convertGlobalToBase:globalLocation]; - - [CPDragServerView removeFromSuperview]; - [CPSharedDragServer._dragWindow orderOut:nil]; - - if (CPDragServerDestination && - (![CPDragServerDestination respondsToSelector:@selector(prepareForDragOperation:)] || [CPDragServerDestination prepareForDragOperation:CPDragServerDraggingInfo]) && - (![CPDragServerDestination respondsToSelector:@selector(performDragOperation:)] || [CPDragServerDestination performDragOperation:CPDragServerDraggingInfo]) && - [CPDragServerDestination respondsToSelector:@selector(concludeDragOperation:)]) - [CPDragServerDestination concludeDragOperation:CPDragServerDraggingInfo]; - - if (CPDragServerShouldSendDraggedImageEndedAtOperation) - [CPDragServerSource draggedImage:[CPDragServerView image] endedAt:CPDragServerLocation operation:NO]; - else if (CPDragServerShouldSendDraggedViewEndedAtOperation) - [CPDragServerSource draggedView:CPDragServerView endedAt:CPDragServerLocation operation:NO]; - - CPDragServerIsDraggingImage = NO; - CPDragServerDestination = nil; - - return; - } - if (CPDragServerAutoscrollInterval === nil) { if ([CPDragServerSource respondsToSelector:@selector(autoscroll:)]) @@ -104,39 +56,16 @@ var CPDragServerUpdateDragging = function(anEvent) CPDragServerPreviousEvent = anEvent; - // If we're not a mouse up, then we're going to want to grab the next event. - [CPApp setCallback:CPDragServerUpdateDragging - forNextEventMatchingMask:CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask - untilDate:nil inMode:0 dequeue:NO]; - - // We have to convert base to bridge since the drag event comes from the source window, not the drag window. - var draggingDestination = [[CPPlatformWindow primaryPlatformWindow] _dragHitTest:globalLocation pasteboard:CPDragServerPasteboard]; - - CPDragServerLocation = [DRAGGING_WINDOW(draggingDestination) convertGlobalToBase:globalLocation]; - - if(draggingDestination !== CPDragServerDestination) - { - if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingExited:)]) - [CPDragServerDestination draggingExited:CPDragServerDraggingInfo]; - - CPDragServerDestination = draggingDestination; - - if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingEntered:)]) - [CPDragServerDestination draggingEntered:CPDragServerDraggingInfo]; - } - else if (CPDragServerDestination && [CPDragServerDestination respondsToSelector:@selector(draggingUpdated:)]) - [CPDragServerDestination draggingUpdated:CPDragServerDraggingInfo]; + if (CPDragServerAutoscrollInterval !== nil) + clearInterval(CPDragServerAutoscrollInterval); - globalLocation.x -= CPDragServerOffset.x; - globalLocation.y -= CPDragServerOffset.y; + CPDragServerAutoscrollInterval = nil; +*/ - [[CPDragServerView window] setFrameOrigin:globalLocation]; +var CPSharedDragServer = nil; - if (CPDragServerShouldSendDraggedImageMovedTo) - [CPDragServerSource draggedImage:[CPDragServerView image] movedTo:globalLocation]; - else if (CPDragServerShouldSendDraggedViewMovedTo) - [CPDragServerSource draggedView:CPDragServerView movedTo:globalLocation]; -} +var CPDragServerSource = nil; +var CPDragServerDraggingInfo = nil; /* CPDraggingInfo is a container of information about a specific dragging session. @@ -146,24 +75,36 @@ var CPDragServerUpdateDragging = function(anEvent) { } +- (CPPasteboard)draggingPasteboard +{ + if ([CPPlatform supportsDragAndDrop]) + return [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard]; + + return [[CPDragServer sharedDragServer] draggingPasteboard]; +} + - (id)draggingSource { - return CPDragServerSource; + return [[CPDragServer sharedDragServer] draggingSource]; } +/* +- (unsigned)draggingSourceOperationMask +*/ + - (CPPoint)draggingLocation { - return CPDragServerLocation; + return [[CPDragServer sharedDragServer] draggingLocation]; } -- (CPPasteboard)draggingPasteboard +- (CPWindow)draggingDestinationWindow { - return CPDragServerPasteboard; + return DRAGGING_WINDOW([[CPDragServer sharedDragServer] draggingDestination]); } - (CPImage)draggedImage { - return [CPDragServerView image]; + return [[self draggedView] image]; } - (CGPoint)draggedImageLocation @@ -171,22 +112,44 @@ var CPDragServerUpdateDragging = function(anEvent) return [self draggedViewLocation]; } -- (CGPoint)draggedViewLocation +- (CPView)draggedView { - return [DRAGGING_WINDOW(CPDragServerDestination) convertBridgeToBase:[CPDragServerView frame].origin]; + return [[CPDragServer sharedDragServer] draggedView]; } -- (CPView)draggedView +- (CGPoint)draggedViewLocation { - return CPDragServerView; + var dragServer = [CPDragServer sharedDragServer]; + + return [DRAGGING_WINDOW([dragServer draggingDestination]) convertPlatformWindowToBase:[[dragServer draggedView] frame].origin]; } @end +var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, + CPDraggingSource_draggedImage_endAt_operation_ = 1 << 1, + CPDraggingSource_draggedView_movedTo_ = 1 << 2, + CPDraggingSource_draggedView_endedAt_operation_ = 1 << 3; + @implementation CPDragServer : CPObject { - CPWindow _dragWindow; - CPImageView _imageView; + BOOL _isDragging @accessors(readonly, getter=isDragging); + + CPWindow _draggedWindow @accessors(readonly, getter=draggedWindow); + CPView _draggedView @accessors(readonly, getter=draggedView); + CPImageView _imageView; + + BOOL _isDraggingImage; + + CGSize _draggingOffset @accessors(readonly, getter=draggingOffset); + + CPPasteboard _draggingPasteboard @accessors(readonly, getter=draggingPasteboard); + + id _draggingSource @accessors(readonly, getter=draggingSource); + unsigned _implementedDraggingSourceMethods; + + CGPoint _draggingLocation; + id _draggingDestination; } /* @@ -197,7 +160,7 @@ var CPDragServerUpdateDragging = function(anEvent) { if (self !== [CPDragServer class]) return; - + CPDragServerDraggingInfo = [[CPDraggingInfo alloc] init]; } @@ -205,7 +168,7 @@ var CPDragServerUpdateDragging = function(anEvent) { if (!CPSharedDragServer) CPSharedDragServer = [[CPDragServer alloc] init]; - + return CPSharedDragServer; } @@ -215,17 +178,104 @@ var CPDragServerUpdateDragging = function(anEvent) - (id)init { self = [super init]; - + if (self) { - _dragWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask]; + _draggedWindow = [[CPWindow alloc] initWithContentRect:_CGRectMakeZero() styleMask:CPBorderlessWindowMask]; - [_dragWindow setLevel:CPDraggingWindowLevel]; + [_draggedWindow setLevel:CPDraggingWindowLevel]; } - + return self; } +- (CGPoint)draggingLocation +{ + return _draggingLocation +} + +- (void)draggingStartedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation +{ + if (_isDraggingImage) + { + if ([_draggingSource respondsToSelector:@selector(draggedImage:beganAt:)]) + [_draggingSource draggedImage:[_draggedView image] beganAt:aLocation]; + } + else + { + if ([_draggingSource respondsToSelector:@selector(draggedView:beganAt:)]) + [_draggingSource draggedView:_draggedView beganAt:aLocation]; + } + + if (![CPPlatform supportsDragAndDrop]) + [_draggedWindow orderFront:self]; +} + +- (void)draggingSourceUpdatedWithLocation:(CGPoint)aGlobalLocation +{ + if (![CPPlatform supportsDragAndDrop]) + [_draggedWindow setFrameOrigin:_CGPointMake(aGlobalLocation.x - _draggingOffset.width, aGlobalLocation.y - _draggingOffset.height)]; + + if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_movedTo_) + [_draggingSource draggedImage:[_draggedView image] movedTo:aGlobalLocation]; + + else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_movedTo_) + [_draggingSource draggedView:_draggedView movedTo:aGlobalLocation]; +} + +- (CPDragOperation)draggingUpdatedInPlatformWindow:(CPPlatformWindow)aPlatformWindow location:(CGPoint)aLocation +{ + var dragOperation = CPDragOperationCopy; + // We have to convert base to bridge since the drag event comes from the source window, not the drag window. + var draggingDestination = [aPlatformWindow _dragHitTest:aLocation pasteboard:[CPDragServerDraggingInfo draggingPasteboard]]; + + if (draggingDestination) + _draggingLocation = [DRAGGING_WINDOW(draggingDestination) convertPlatformWindowToBase:aLocation]; + + if(draggingDestination !== _draggingDestination) + { + if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingExited:)]) + [_draggingDestination draggingExited:CPDragServerDraggingInfo]; + + _draggingDestination = draggingDestination; + + if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingEntered:)]) + dragOperation = [_draggingDestination draggingEntered:CPDragServerDraggingInfo]; + } + else if (_draggingDestination && [_draggingDestination respondsToSelector:@selector(draggingUpdated:)]) + dragOperation = [_draggingDestination draggingUpdated:CPDragServerDraggingInfo]; + + if (!_draggingDestination) + dragOperation = CPDragOperationNone; + + return dragOperation; +} + +- (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow +{ + [_draggedView removeFromSuperview]; + + if (![CPPlatform supportsDragAndDrop]) + [_draggedWindow orderOut:self]; + + if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_) + [_draggingSource draggedImage:[_draggedView image] endedAt:_draggingLocation operation:NO]; + + else if (_implementedDraggingSourceMethods & CPDraggingSource_draggedView_endedAt_operation_) + [_draggingSource draggedView:_draggedView endedAt:_draggingLocation operation:NO]; + + _isDragging = NO; +} + +- (void)performDragOperationInPlatformWindow:(CPPlatformWindow)aPlatformWindow +{ + if (_draggingDestination && + (![_draggingDestination respondsToSelector:@selector(prepareForDragOperation:)] || [_draggingDestination prepareForDragOperation:CPDragServerDraggingInfo]) && + (![_draggingDestination respondsToSelector:@selector(performDragOperation:)] || [_draggingDestination performDragOperation:CPDragServerDraggingInfo]) && + [_draggingDestination respondsToSelector:@selector(concludeDragOperation:)]) + [_draggingDestination concludeDragOperation:CPDragServerDraggingInfo]; +} + /*! Initiates a drag session. @param aView the view being dragged @@ -240,10 +290,12 @@ var CPDragServerUpdateDragging = function(anEvent) */ - (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 { - CPDragServerView = aView; - CPDragServerSource = aSourceObject; - CPDragServerWindow = aWindow; - CPDragServerPasteboard = [CPPasteboard pasteboardWithName:CPDragPboard];//aPasteboard; + _isDragging = YES; + + _draggedView = aView; + _draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard]; + _draggingSource = aSourceObject; + _draggingDestination = nil; // The offset is based on the distance from where we want the view to be initially from where the mouse is initially // Hence the use of mouseDownEvent's location and view's location in global coordinates. @@ -255,58 +307,48 @@ var CPDragServerUpdateDragging = function(anEvent) if (mouseDownWindow) mouseDownEventLocation = [mouseDownWindow convertBaseToGlobal:mouseDownEventLocation]; - CPDragServerOffset = _CGPointMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y); + _draggingOffset = _CGSizeMake(mouseDownEventLocation.x - viewLocation.x, mouseDownEventLocation.y - viewLocation.y); } else - CPDragServerOffset = _CGPointMakeZero(); + _draggingOffset = _CGSizeMakerZero(); if ([CPPlatform isBrowser]) - [_dragWindow setPlatformWindow:[aWindow platformWindow]]; + [_draggedWindow setPlatformWindow:[aWindow platformWindow]]; [aView setFrameOrigin:_CGPointMakeZero()]; var mouseLocation = [CPEvent mouseLocation]; // Place it where the mouse pointer is. - [_dragWindow setFrameOrigin:_CGPointMake(mouseLocation.x - CPDragServerOffset.x, mouseLocation.y - CPDragServerOffset.y)]; - [_dragWindow setFrameSize:[aView frame].size]; + [_draggedWindow setFrameOrigin:_CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height)]; + [_draggedWindow setFrameSize:[aView frame].size]; - [[_dragWindow contentView] addSubview:aView]; + [[_draggedWindow contentView] addSubview:aView]; - [_dragWindow orderFront:self]; + _implementedDraggingSourceMethods = 0; - if (CPDragServerIsDraggingImage) + if (_draggedView === _imageView) { - if ([CPDragServerSource respondsToSelector:@selector(draggedImage:beganAt:)]) - [CPDragServerSource draggedImage:[aView image] beganAt:viewLocation]; - - CPDragServerShouldSendDraggedImageMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedImage:movedTo:)]; - CPDragServerShouldSendDraggedImageEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedImage:endAt:operation:)]; - - CPDragServerShouldSendDraggedViewMovedTo = NO; - CPDragServerShouldSendDraggedViewEndedAtOperation = NO; + if ([_draggingSource respondsToSelector:@selector(draggedImage:movedTo:)]) + _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_movedTo_; + + if ([_draggingSource respondsToSelector:@selector(draggedImage:endAt:operation:)]) + _implementedDraggingSourceMethods |= CPDraggingSource_draggedImage_endAt_operation_; } else { - if ([CPDragServerSource respondsToSelector:@selector(draggedView:beganAt:)]) - [CPDragServerSource draggedView:aView beganAt:viewLocation]; - - CPDragServerShouldSendDraggedViewMovedTo = [CPDragServerSource respondsToSelector:@selector(draggedView:movedTo:)]; - CPDragServerShouldSendDraggedViewEndedAtOperation = [CPDragServerSource respondsToSelector:@selector(draggedView:endedAt:operation:)]; - - - CPDragServerShouldSendDraggedImageMovedTo = NO; - CPDragServerShouldSendDraggedImageEndedAtOperation = NO; - } - - if (mouseDownWindow) - mouseLocation = [mouseDownWindow convertGlobalToBase:mouseLocation]; + if ([_draggingSource respondsToSelector:@selector(draggedView:movedTo:)]) + _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_movedTo_; - var updatedEvent = [CPEvent mouseEventWithType:CPLeftMouseDragged location:mouseLocation modifierFlags:[mouseDownEvent modifierFlags] - timestamp:[mouseDownEvent timestamp] windowNumber:[mouseDownEvent windowNumber] context:nil - eventNumber:0 clickCount:[mouseDownEvent clickCount] pressure:[mouseDownEvent pressure]]; + if ([_draggingSource respondsToSelector:@selector(draggedView:endedAt:operation:)]) + _implementedDraggingSourceMethods |= CPDraggingSource_draggedView_endedAt_operation_; + } - CPDragServerStartDragging(updatedEvent); + if (![CPPlatform supportsDragAndDrop]) + { + [self draggingStartedInPlatformWindow:[aWindow platformWindow] location:mouseLocation]; + [self trackDragging:mouseDownEvent]; + } } /*! @@ -323,17 +365,42 @@ var CPDragServerUpdateDragging = function(anEvent) */ - (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 { - CPDragServerIsDraggingImage = YES; - + _isDraggingImage = YES; + + var imageSize = [anImage size]; + if (!_imageView) - _imageView = [[CPImageView alloc] initWithFrame:CPRectMakeZero()]; - + _imageView = [[CPImageView alloc] initWithFrame:_CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)]; + [_imageView setImage:anImage]; - [_imageView setFrameSize:CGSizeMakeCopy([anImage size])]; - + [self dragView:_imageView fromWindow:aWindow at:imageLocation offset:mouseOffset event:anEvent pasteboard:aPasteboard source:aSourceObject slideBack:slideBack]; } +- (void)trackDragging:(CPEvent)anEvent +{ + var type = [anEvent type], + platformWindow = [_draggedWindow platformWindow], + platformWindowLocation = [[anEvent window] convertBaseToPlatformWindow:[anEvent locationInWindow]]; + + if (type === CPLeftMouseUp) + { + [self performDragOperationInPlatformWindow:platformWindow]; + [self draggingEndedInPlatformWindow:platformWindow]; + + // Stop tracking events. + return; + } + + [self draggingSourceUpdatedWithLocation:platformWindowLocation]; + [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation]; + + // 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 + untilDate:nil inMode:0 dequeue:NO]; +} + @end @implementation CPWindow (CPDraggingAdditions) @@ -351,18 +418,18 @@ var CPDragServerUpdateDragging = function(anEvent) // if (![self containsPoint:aPoint]) // return nil; - var adjustedPoint = _CGPointMake(aPoint.x - _CGRectGetMinX(_frame), aPoint.y - _CGRectGetMinY(_frame)), + var adjustedPoint = [self convertPlatformWindowToBase:aPoint], hitView = [_windowView hitTest:adjustedPoint]; while (hitView && ![aPasteboard availableTypeFromArray:[hitView registeredDraggedTypes]]) hitView = [hitView superview]; - + if (hitView) return hitView; - + if ([aPasteboard availableTypeFromArray:[self registeredDraggedTypes]]) return self; - + return nil; } diff --git a/AppKit/CPImageView.j b/AppKit/CPImageView.j index c751870736..ed6eeea427 100644 --- a/AppKit/CPImageView.j +++ b/AppKit/CPImageView.j @@ -87,7 +87,13 @@ var LEFT_SHADOW_INSET = 3.0, _DOMImageElement.style.position = "absolute"; _DOMImageElement.style.left = "0px"; _DOMImageElement.style.top = "0px"; - + + if ([CPPlatform supportsDragAndDrop]) + { + _DOMImageElement.setAttribute("draggable", "true"); + _DOMImageElement.style["-khtml-user-drag"] = "element"; + } + CPDOMDisplayServerAppendChild(_DOMElement, _DOMImageElement); _DOMImageElement.style.visibility = "hidden"; @@ -398,6 +404,11 @@ var CPImageViewImageKey = @"CPImageViewImageKey", _DOMImageElement.style.left = "0px"; _DOMImageElement.style.top = "0px"; _DOMImageElement.style.visibility = "hidden"; + if ([CPPlatform supportsDragAndDrop]) + { + _DOMImageElement.setAttribute("draggable", "true"); + _DOMImageElement.style["-khtml-user-drag"] = "element"; + } #endif self = [super initWithCoder:aCoder]; diff --git a/AppKit/CPPasteboard.j b/AppKit/CPPasteboard.j index f74711361e..4da0d92ec0 100644 --- a/AppKit/CPPasteboard.j +++ b/AppKit/CPPasteboard.j @@ -25,6 +25,8 @@ @import @import +#include "Platform/Platform.h" + CPGeneralPboard = @"CPGeneralPboard"; CPFontPboard = @"CPFontPboard"; @@ -213,7 +215,7 @@ var CPPasteboards = nil; */ - (CPString)availableTypeFromArray:(CPArray)anArray { - return [_types firstObjectCommonWithArray:anArray]; + return [[self types] firstObjectCommonWithArray:anArray]; } /*! @@ -304,3 +306,70 @@ var CPPasteboards = nil; } @end + +#if PLATFORM(DOM) + +var DOMDataTransferPasteboard = nil; + +@implementation _CPDOMDataTransferPasteboard : CPPasteboard +{ + DataTransfer _dataTransfer; +} + ++ (_CPDOMDataTransferPasteboard)DOMDataTransferPasteboard +{ + if (!DOMDataTransferPasteboard) + DOMDataTransferPasteboard = [[_CPDOMDataTransferPasteboard alloc] init]; + + return DOMDataTransferPasteboard; +} + +- (void)_setDataTransfer:(DataTransfer)aDataTransfer +{ + _dataTransfer = aDataTransfer; +} + +- (void)_setPasteboard:(CPPasteboard)aPasteboard +{ + _dataTransfer.clearData(); + + var types = [aPasteboard types], + count = types.length; + + while (count--) + { + var type = types[count]; + + if (type === CPStringPboardType) + _dataTransfer.setData(type, [aPasteboard stringForType:type]); + else + _dataTransfer.setData(type, [[aPasteboard dataForType:type] string]); + } +} + +- (CPArray)types +{ + return Array.prototype.slice.apply(_dataTransfer.types); +} + +- (CPData)dataForType:(CPString)aType +{ + var dataString = _dataTransfer.getData(aType); + + if (aType === CPStringPboardType) + return [CPData dataFromPropertyList:dataString format:kCFPropertyList280NorthFormat_v1_0 errorDescription:0]; + + return [CPData dataWithString:dataString]; +} + +- (id)propertyListForType:(CPString)aType +{ + if (aType === CPStringPboardType) + return _dataTransfer.getData(aType); + + return [CPPropertyListSerialization propertyListFromData:[self dataForType:aType] format:CPPropertyListUnknownFormat errorDescription:nil]; +} + +@end + +#endif diff --git a/AppKit/CPView.j b/AppKit/CPView.j index a1745f2d56..047e2ccc47 100644 --- a/AppKit/CPView.j +++ b/AppKit/CPView.j @@ -250,7 +250,7 @@ var DOMElementPrototype = nil, #if PLATFORM(DOM) _DOMElement = DOMElementPrototype.cloneNode(false); - + CPDOMDisplayServerSetStyleLeftTop(_DOMElement, NULL, _CGRectGetMinX(aFrame), _CGRectGetMinY(aFrame)); CPDOMDisplayServerSetStyleSize(_DOMElement, width, height); diff --git a/AppKit/CPWindow/_CPWindowView.j b/AppKit/CPWindow/_CPWindowView.j index a6d7c50e8b..890044daa1 100644 --- a/AppKit/CPWindow/_CPWindowView.j +++ b/AppKit/CPWindow/_CPWindowView.j @@ -142,6 +142,10 @@ var _CPWindowViewResizeIndicatorImage = nil; - (CGPoint)_pointWithinScreenFrame:(CGPoint)aPoint { + // FIXME: this is WRONG, all of this is WRONG + if (![CPPlatform isBrowser]) + return aPoint; + var visibleFrame = _cachedScreenFrame; if (!visibleFrame) diff --git a/AppKit/Platform/CPPlatform.j b/AppKit/Platform/CPPlatform.j index 9b031b0389..0e92269e91 100644 --- a/AppKit/Platform/CPPlatform.j +++ b/AppKit/Platform/CPPlatform.j @@ -26,7 +26,12 @@ + (BOOL)isBrowser { - return YES; + return typeof window.cpIsDesktop === "undefined"; +} + ++ (BOOL)supportsDragAndDrop +{ + return CPFeatureIsCompatible(CPHTMLDragAndDropFeature); } @end diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index dd719baf85..c632347310 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -164,6 +164,10 @@ var CTRL_KEY_CODE = 17; _DOMBodyElement = theDocument.getElementsByTagName("body")[0]; + // FIXME: Always do this? + if ([CPPlatform supportsDragAndDrop]) + _DOMBodyElement.style["-khtml-user-select"] = "none"; + _DOMBodyElement.webkitTouchCallout = "none"; _DOMFocusElement = theDocument.createElement("input"); @@ -189,6 +193,9 @@ var CTRL_KEY_CODE = 17; var theClass = [self class], + dragEventImplementation = class_getMethodImplementation(theClass, @selector(dragEvent:)), + dragEventCallback = function (anEvent) { dragEventImplementation(self, nil, anEvent); }, + resizeEventSelector = @selector(resizeEvent:), resizeEventImplementation = class_getMethodImplementation(theClass, resizeEventSelector), resizeEventCallback = function (anEvent) { resizeEventImplementation(self, nil, anEvent); }, @@ -211,6 +218,16 @@ var CTRL_KEY_CODE = 17; if (theDocument.addEventListener) { + if ([CPPlatform supportsDragAndDrop]) + { + theDocument.addEventListener("dragstart", dragEventCallback, NO); + theDocument.addEventListener("drag", dragEventCallback, NO); + theDocument.addEventListener("dragend", dragEventCallback, NO); + theDocument.addEventListener("dragover", dragEventCallback, NO); + theDocument.addEventListener("dragleave", dragEventCallback, NO); + theDocument.addEventListener("drop", dragEventCallback, NO); + } + theDocument.addEventListener("mouseup", mouseEventCallback, NO); theDocument.addEventListener("mousedown", mouseEventCallback, NO); theDocument.addEventListener("mousemove", mouseEventCallback, NO); @@ -331,6 +348,78 @@ var CTRL_KEY_CODE = 17; _DOMWindow.close(); } +- (void)dragEvent:(DOMEvent)aDOMEvent +{ + var type = aDOMEvent.type, + dragServer = [CPDragServer sharedDragServer], + location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY), + pasteboard = [_CPDOMDataTransferPasteboard DOMDataTransferPasteboard]; + + [pasteboard _setDataTransfer:aDOMEvent.dataTransfer]; + + if (aDOMEvent.type === "dragstart") + { + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; + + [pasteboard _setPasteboard:[dragServer draggingPasteboard]]; + + var draggedWindow = [dragServer draggedWindow], + draggedWindowFrame = [draggedWindow frame], + DOMDragElement = draggedWindow._DOMElement; + + DOMDragElement.style.left = -_CGRectGetWidth(draggedWindowFrame) + "px"; + DOMDragElement.style.top = -_CGRectGetHeight(draggedWindowFrame) + "px"; + + document.getElementsByTagName("body")[0].appendChild(DOMDragElement); + + var draggingOffset = [dragServer draggingOffset]; + + aDOMEvent.dataTransfer.setDragImage(DOMDragElement, draggingOffset.width, draggingOffset.height); + + [dragServer draggingStartedInPlatformWindow:self location:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY)]; + } + + else if (type === "drag") + [dragServer draggingSourceUpdatedWithLocation:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY)]; + + else if (type === "dragover" || type === "dragleave") + { + if (aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + + var dropEffect = "none", + dragOperation = [dragServer draggingUpdatedInPlatformWindow:self location:location]; + + if (dragOperation === CPDragOperationMove || dragOperation === CPDragOperationGeneric || dragOperation === CPDragOperationPrivate) + dropEffect = "move"; + + else if (dragOperation === CPDragOperationCopy) + dropEffect = "copy"; + + else if (dragOperation === CPDragOperationLink) + dropEffect = "link"; + + aDOMEvent.dataTransfer.dropEffect = dropEffect; + } + + else if (type === "dragend") + [dragServer draggingEndedInPlatformWindow:self]; + + else //if (type === "drop") + { + [dragServer performDragOperationInPlatformWindow:self]; + + // W3C Model + if (aDOMEvent.preventDefault) + aDOMEvent.preventDefault(); + + if (aDOMEvent.stopPropagation) + aDOMEvent.stopPropagation(); + } + + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; +} + - (void)keyEvent:(DOMEvent)aDOMEvent { var event, @@ -693,9 +782,15 @@ var CTRL_KEY_CODE = 17; } else if (type === "mousedown") - { + { if (ExcludedDOMElements[sourceElement.tagName] && sourceElement != _DOMFocusElement) { + if ([CPPlatform supportsDragAndDrop]) + { + _DOMBodyElement.setAttribute("draggable", "false"); + _DOMBodyElement.style["-khtml-user-drag"] = "none"; + } + _DOMEventMode = YES; _mouseIsDown = YES; @@ -710,6 +805,11 @@ var CTRL_KEY_CODE = 17; return; } + else if ([CPPlatform supportsDragAndDrop]) + { + _DOMBodyElement.setAttribute("draggable", "true"); + _DOMBodyElement.style["-khtml-user-drag"] = "element"; + } event = _CPEventFromNativeMouseEvent(aDOMEvent, CPLeftMouseDown, location, modifierFlags, timestamp, windowNumber, nil, -1, CPDOMEventGetClickCount(_lastMouseDown, timestamp, location), 0); @@ -717,7 +817,7 @@ var CTRL_KEY_CODE = 17; _lastMouseDown = event; } - else // if (type === "mousemove") + else // if (type === "mousemove" || type === "drag") { if (_DOMEventMode) return; @@ -732,7 +832,7 @@ var CTRL_KEY_CODE = 17; [CPApp sendEvent:event]; } - if (StopDOMEventPropagation) + if (StopDOMEventPropagation && (![CPPlatform supportsDragAndDrop] || type !== "mousedown" && ![[CPDragServer sharedDragServer] isDragging])) CPDOMEventStop(aDOMEvent, self); [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; diff --git a/AppKit/_CPImageAndTextView.j b/AppKit/_CPImageAndTextView.j index 8710d269fe..c80fed2e77 100644 --- a/AppKit/_CPImageAndTextView.j +++ b/AppKit/_CPImageAndTextView.j @@ -511,7 +511,13 @@ var HORIZONTAL_MARGIN = 3.0, else { _DOMImageElement = document.createElement("img"); - + + if ([CPPlatform supportsDragAndDrop]) + { + _DOMImageElement.setAttribute("draggable", "true"); + _DOMImageElement.style["-khtml-user-drag"] = "element"; + } + var imageStyle = _DOMImageElement.style; imageStyle.top = "0px"; diff --git a/Foundation/CPPropertyListSerialization.j b/Foundation/CPPropertyListSerialization.j index 19c71fa5ce..342a55257d 100644 --- a/Foundation/CPPropertyListSerialization.j +++ b/Foundation/CPPropertyListSerialization.j @@ -23,6 +23,7 @@ @import "CPObject.j" +CPPropertyListUnknownFormat = 0; CPPropertyListOpenStepFormat = kCFPropertyListOpenStepFormat; CPPropertyListXMLFormat_v1_0 = kCFPropertyListXMLFormat_v1_0; CPPropertyListBinaryFormat_v1_0 = kCFPropertyListBinaryFormat_v1_0;