@@ -1691,6 +1691,158 @@ - (void)keyUp:(NSEvent *)event {
1691
1691
}
1692
1692
1693
1693
1694
+ #pragma mark - Drag and Drop Events
1695
+
1696
+ enum DragEventType {
1697
+ DragEnter,
1698
+ DragLeave,
1699
+ Drop,
1700
+ };
1701
+
1702
+ - (void )buildDataTransferItems:(std::vector<DataTransferItem> &)dataTransferItems forPasteboard:(NSPasteboard *)pasteboard {
1703
+ NSArray *fileNames = [pasteboard propertyListForType: NSFilenamesPboardType ] ?: @[];
1704
+ for (NSString *file in fileNames) {
1705
+ NSURL *fileURL = [NSURL fileURLWithPath: file];
1706
+ BOOL isDir = NO ;
1707
+ BOOL isValid = (![[NSFileManager defaultManager ] fileExistsAtPath: fileURL.path isDirectory: &isDir] || isDir) ? NO : YES ;
1708
+ if (isValid) {
1709
+
1710
+ NSString *MIMETypeString = nil ;
1711
+ if (fileURL.pathExtension ) {
1712
+ CFStringRef fileExtension = (__bridge CFStringRef)fileURL.pathExtension ;
1713
+ CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag (kUTTagClassFilenameExtension , fileExtension, NULL );
1714
+ if (UTI != NULL ) {
1715
+ CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType );
1716
+ CFRelease (UTI);
1717
+ MIMETypeString = (__bridge_transfer NSString *)MIMEType;
1718
+ }
1719
+ }
1720
+
1721
+ NSNumber *fileSizeValue = nil ;
1722
+ NSError *fileSizeError = nil ;
1723
+ BOOL success = [fileURL getResourceValue: &fileSizeValue
1724
+ forKey: NSURLFileSizeKey
1725
+ error: &fileSizeError];
1726
+
1727
+ NSNumber *width = nil ;
1728
+ NSNumber *height = nil ;
1729
+ if ([MIMETypeString hasPrefix: @" image/" ]) {
1730
+ NSImage *image = [[NSImage alloc ] initWithContentsOfURL: fileURL];
1731
+ width = @(image.size .width );
1732
+ height = @(image.size .height );
1733
+ }
1734
+
1735
+ DataTransferItem transferItem = {
1736
+ .name = fileURL.lastPathComponent .UTF8String ,
1737
+ .kind = " file" ,
1738
+ .type = MIMETypeString.UTF8String ,
1739
+ .uri = fileURL.path .UTF8String ,
1740
+ };
1741
+
1742
+ if (success) {
1743
+ transferItem.size = fileSizeValue.intValue ;
1744
+ }
1745
+
1746
+ if (width != nil ) {
1747
+ transferItem.width = width.intValue ;
1748
+ }
1749
+
1750
+ if (height != nil ) {
1751
+ transferItem.height = height.intValue ;
1752
+ }
1753
+
1754
+ dataTransferItems.push_back (transferItem);
1755
+ }
1756
+ }
1757
+
1758
+ NSPasteboardType imageType = [pasteboard availableTypeFromArray: @[NSPasteboardTypePNG , NSPasteboardTypeTIFF ]];
1759
+ if (imageType && fileNames.count == 0 ) {
1760
+ NSString *MIMETypeString = imageType == NSPasteboardTypePNG ? @" image/png" : @" image/tiff" ;
1761
+ NSData *imageData = [pasteboard dataForType: imageType];
1762
+ NSImage *image = [[NSImage alloc ] initWithData: imageData];
1763
+
1764
+ DataTransferItem transferItem = {
1765
+ .kind = " image" ,
1766
+ .type = MIMETypeString.UTF8String ,
1767
+ .uri = RCTDataURL (MIMETypeString, imageData).absoluteString .UTF8String ,
1768
+ .size = imageData.length ,
1769
+ .width = image.size .width ,
1770
+ .height = image.size .height ,
1771
+ };
1772
+
1773
+ dataTransferItems.push_back (transferItem);
1774
+ }
1775
+ }
1776
+
1777
+ - (void )sendDragEvent:(DragEventType)eventType withLocation:(NSPoint )locationInWindow pasteboard:(NSPasteboard *)pasteboard {
1778
+ if (!_eventEmitter) {
1779
+ return ;
1780
+ }
1781
+
1782
+ std::vector<DataTransferItem> dataTransferItems{};
1783
+ [self buildDataTransferItems: dataTransferItems forPasteboard: pasteboard];
1784
+
1785
+ NSPoint locationInView = [self convertPoint: locationInWindow fromView: nil ];
1786
+ NSEventModifierFlags modifierFlags = self.window .currentEvent .modifierFlags ;
1787
+
1788
+ DragEvent dragEvent = {
1789
+ {
1790
+ .clientX = locationInView.x ,
1791
+ .clientY = locationInView.y ,
1792
+ .screenX = locationInWindow.x ,
1793
+ .screenY = locationInWindow.y ,
1794
+ .altKey = static_cast <bool >(modifierFlags & NSEventModifierFlagOption),
1795
+ .ctrlKey = static_cast <bool >(modifierFlags & NSEventModifierFlagControl),
1796
+ .shiftKey = static_cast <bool >(modifierFlags & NSEventModifierFlagShift),
1797
+ .metaKey = static_cast <bool >(modifierFlags & NSEventModifierFlagCommand),
1798
+ },
1799
+ .dataTransferItems = dataTransferItems,
1800
+ };
1801
+
1802
+ switch (eventType) {
1803
+ case DragEnter:
1804
+ _eventEmitter->onDragEnter (dragEvent);
1805
+ break ;
1806
+
1807
+ case DragLeave:
1808
+ _eventEmitter->onDragLeave (dragEvent);
1809
+ break ;
1810
+
1811
+ case Drop:
1812
+ _eventEmitter->onDrop (dragEvent);
1813
+ break ;
1814
+ }
1815
+ }
1816
+
1817
+ - (NSDragOperation )draggingEntered:(id <NSDraggingInfo >)sender
1818
+ {
1819
+ NSPasteboard *pboard = sender.draggingPasteboard ;
1820
+ NSDragOperation sourceDragMask = sender.draggingSourceOperationMask ;
1821
+
1822
+ [self sendDragEvent: DragEnter withLocation: sender.draggingLocation pasteboard: pboard];
1823
+
1824
+ if ([pboard availableTypeFromArray: self .registeredDraggedTypes]) {
1825
+ if (sourceDragMask & NSDragOperationLink) {
1826
+ return NSDragOperationLink;
1827
+ } else if (sourceDragMask & NSDragOperationCopy) {
1828
+ return NSDragOperationCopy;
1829
+ }
1830
+ }
1831
+ return NSDragOperationNone;
1832
+ }
1833
+
1834
+ - (void )draggingExited:(id <NSDraggingInfo >)sender
1835
+ {
1836
+ [self sendDragEvent: DragLeave withLocation: sender.draggingLocation pasteboard: sender.draggingPasteboard];
1837
+ }
1838
+
1839
+ - (BOOL )performDragOperation:(id <NSDraggingInfo >)sender
1840
+ {
1841
+ [self sendDragEvent: Drop withLocation: sender.draggingLocation pasteboard: sender.draggingPasteboard];
1842
+ return YES ;
1843
+ }
1844
+
1845
+
1694
1846
#pragma mark - Mouse Events
1695
1847
1696
1848
- (void )emitMouseEvent {
0 commit comments