Skip to content

Commit 450e1f3

Browse files
committed
darwin-external-dragndrop: implement external drag n' drop for darwin
1 parent 5f818bc commit 450e1f3

File tree

5 files changed

+65
-0
lines changed

5 files changed

+65
-0
lines changed

app/os_macos.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"gioui.org/internal/f32"
1717
"gioui.org/io/clipboard"
18+
"gioui.org/io/externalDragDrop"
1819
"gioui.org/io/key"
1920
"gioui.org/io/pointer"
2021
"gioui.org/io/system"
@@ -557,6 +558,13 @@ func gio_onMouse(view, evt C.CFTypeRef, cdir C.int, cbtn C.NSInteger, x, y, dx,
557558
})
558559
}
559560

561+
//export gio_onExternalDrop
562+
func gio_onExternalDrop(view C.CFTypeRef, pbrd *C.char) {
563+
fileUrl := C.GoString(pbrd)
564+
w := mustView(view)
565+
w.w.Event(externalDragDrop.Event{Text: fileUrl})
566+
}
567+
560568
//export gio_onDraw
561569
func gio_onDraw(view C.CFTypeRef) {
562570
w := mustView(view)

app/os_macos.m

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,27 @@ - (void)mouseMoved:(NSEvent *)event {
110110
- (void)mouseDragged:(NSEvent *)event {
111111
handleMouse(self, event, MOUSE_MOVE, 0, 0);
112112
}
113+
-(NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
114+
{
115+
return NSDragOperationCopy; // NSDragOperationGeneric
116+
}
117+
- (void)draggingEnded:(id <NSDraggingInfo>)sender
118+
{
119+
NSPasteboard* pbrd = [sender draggingPasteboard];
120+
121+
for (NSPasteboardItem *item in [pbrd pasteboardItems]) {
122+
for (NSString *type in [item types]) {
123+
if ([type isEqualToString:@"public.file-url"]) {
124+
NSData* data = [item dataForType:type];
125+
NSString *clipboard_url = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
126+
NSURL *url = [[NSURL alloc] initWithString:clipboard_url];
127+
NSString *real_path = url.path;
128+
char* content = (char*)[real_path UTF8String];
129+
gio_onExternalDrop((__bridge CFTypeRef)self, content);
130+
}
131+
}
132+
}
133+
}
113134
- (void)scrollWheel:(NSEvent *)event {
114135
CGFloat dx = -event.scrollingDeltaX;
115136
CGFloat dy = -event.scrollingDeltaY;
@@ -366,6 +387,7 @@ CFTypeRef gio_createView(void) {
366387
@autoreleasepool {
367388
NSRect frame = NSMakeRect(0, 0, 0, 0);
368389
GioView* view = [[GioView alloc] initWithFrame:frame];
390+
[view registerForDraggedTypes: [NSArray arrayWithObjects:NSTIFFPboardType,NSFilenamesPboardType,nil]];
369391
view.wantsLayer = YES;
370392
view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
371393
return CFBridgingRetain(view);

internal/ops/ops.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const (
7676
TypeSnippet
7777
TypeSelection
7878
TypeActionInput
79+
TypeExternalDragDrop
7980
)
8081

8182
type StackID struct {
@@ -160,6 +161,7 @@ const (
160161
TypeSnippetLen = 1 + 4 + 4
161162
TypeSelectionLen = 1 + 2*4 + 2*4 + 4 + 4
162163
TypeActionInputLen = 1 + 1
164+
TypeExternalDragDropLen = 1
163165
)
164166

165167
func (op *ClipOp) Decode(data []byte) {
@@ -417,6 +419,7 @@ var opProps = [0x100]opProp{
417419
TypeSnippet: {Size: TypeSnippetLen, NumRefs: 2},
418420
TypeSelection: {Size: TypeSelectionLen, NumRefs: 1},
419421
TypeActionInput: {Size: TypeActionInputLen, NumRefs: 0},
422+
TypeExternalDragDrop: {Size: TypeExternalDragDropLen, NumRefs: 1},
420423
}
421424

422425
func (t OpType) props() (size, numRefs int) {
@@ -498,6 +501,8 @@ func (t OpType) String() string {
498501
return "Stroke"
499502
case TypeSemanticLabel:
500503
return "SemanticDescription"
504+
case TypeExternalDragDrop:
505+
return "ExternalDragDrop"
501506
default:
502507
panic("unknown OpType")
503508
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: Unlicense OR MIT
2+
3+
package externalDragDrop
4+
5+
import (
6+
"gioui.org/internal/ops"
7+
"gioui.org/io/event"
8+
"gioui.org/op"
9+
)
10+
11+
// Event is generated when the clipboard content is requested.
12+
type Event struct {
13+
Text string
14+
}
15+
16+
// ReadOp requests the text of the clipboard, delivered to
17+
// the current handler through an Event.
18+
type ReadOp struct {
19+
Tag event.Tag
20+
}
21+
22+
func (h ReadOp) Add(o *op.Ops) {
23+
data := ops.Write1(&o.Internal, ops.TypeExternalDragDropLen, h.Tag)
24+
data[0] = byte(ops.TypeExternalDragDrop)
25+
}
26+
27+
func (Event) ImplementsEvent() {}

io/router/router.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"gioui.org/internal/ops"
2424
"gioui.org/io/clipboard"
2525
"gioui.org/io/event"
26+
"gioui.org/io/externalDragDrop"
2627
"gioui.org/io/key"
2728
"gioui.org/io/pointer"
2829
"gioui.org/io/profile"
@@ -182,6 +183,8 @@ func (q *Router) Queue(events ...event.Event) bool {
182183
}
183184
case clipboard.Event:
184185
q.cqueue.Push(e, &q.handlers)
186+
case externalDragDrop.Event:
187+
q.handlers.Add(nil, e)
185188
}
186189
}
187190
return q.handlers.HadEvents()

0 commit comments

Comments
 (0)