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