Skip to content

Commit 6b140ef

Browse files
committed
Linux: Add support for drag&drop of external files with off-screen rendering (fixes issue chromiumembedded#336)
1 parent d348788 commit 6b140ef

5 files changed

Lines changed: 177 additions & 34 deletions

File tree

java/org/cef/browser/CefBrowserOsr.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,23 @@
44

55
package org.cef.browser;
66

7+
import com.jogamp.nativewindow.NativeSurface;
8+
import com.jogamp.opengl.GLAutoDrawable;
9+
import com.jogamp.opengl.GLCapabilities;
10+
import com.jogamp.opengl.GLEventListener;
11+
import com.jogamp.opengl.GLProfile;
12+
import com.jogamp.opengl.awt.GLCanvas;
13+
14+
import org.cef.CefClient;
15+
import org.cef.callback.CefDragData;
16+
import org.cef.handler.CefRenderHandler;
17+
718
import java.awt.Component;
819
import java.awt.Cursor;
920
import java.awt.Graphics;
21+
import java.awt.Point;
22+
import java.awt.Rectangle;
23+
import java.awt.dnd.DropTarget;
1024
import java.awt.event.FocusEvent;
1125
import java.awt.event.FocusListener;
1226
import java.awt.event.KeyEvent;
@@ -16,24 +30,11 @@
1630
import java.awt.event.MouseMotionListener;
1731
import java.awt.event.MouseWheelEvent;
1832
import java.awt.event.MouseWheelListener;
19-
import java.awt.Point;
20-
import java.awt.Rectangle;
2133
import java.nio.ByteBuffer;
2234

23-
import com.jogamp.nativewindow.NativeSurface;
24-
import com.jogamp.opengl.awt.GLCanvas;
25-
import com.jogamp.opengl.GLAutoDrawable;
26-
import com.jogamp.opengl.GLEventListener;
27-
import com.jogamp.opengl.GLProfile;
28-
import com.jogamp.opengl.GLCapabilities;
29-
3035
import javax.swing.MenuSelectionManager;
3136
import javax.swing.SwingUtilities;
3237

33-
import org.cef.CefClient;
34-
import org.cef.callback.CefDragData;
35-
import org.cef.handler.CefRenderHandler;
36-
3738
/**
3839
* This class represents an off-screen rendered browser.
3940
* The visibility of this class is "package". To create a new
@@ -89,7 +90,7 @@ private synchronized long getWindowHandle() {
8990
surface.lockSurface();
9091
window_handle_ = getWindowHandle(surface.getSurfaceHandle());
9192
surface.unlockSurface();
92-
assert(window_handle_ != 0);
93+
assert (window_handle_ != 0);
9394
}
9495
}
9596
return window_handle_;
@@ -209,6 +210,9 @@ public void focusGained(FocusEvent e) {
209210
setFocus(true);
210211
}
211212
});
213+
214+
// Connect the Canvas with a drag and drop listener.
215+
new DropTarget(canvas_, new CefDropTargetListenerOsr(this));
212216
}
213217

214218
@Override
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
2+
// reserved. Use of this source code is governed by a BSD-style license that
3+
// can be found in the LICENSE file.
4+
5+
package org.cef.browser;
6+
7+
import org.cef.callback.CefDragData;
8+
import org.cef.misc.EventFlags;
9+
10+
import java.awt.datatransfer.DataFlavor;
11+
import java.awt.datatransfer.Transferable;
12+
import java.awt.dnd.DnDConstants;
13+
import java.awt.dnd.DropTarget;
14+
import java.awt.dnd.DropTargetDragEvent;
15+
import java.awt.dnd.DropTargetDropEvent;
16+
import java.awt.dnd.DropTargetEvent;
17+
import java.awt.dnd.DropTargetListener;
18+
import java.io.File;
19+
import java.util.List;
20+
21+
class CefDropTargetListenerOsr implements DropTargetListener {
22+
private CefBrowserOsr browser_;
23+
private CefDragData dragData_ = null;
24+
private int dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY;
25+
private int dragModifiers_ = EventFlags.EVENTFLAG_NONE;
26+
private int acceptOperations_ = DnDConstants.ACTION_COPY;
27+
28+
CefDropTargetListenerOsr(CefBrowserOsr browser) {
29+
browser_ = browser;
30+
}
31+
32+
@Override
33+
public void dragEnter(DropTargetDragEvent event) {
34+
CreateDragData(event);
35+
browser_.dragTargetDragEnter(
36+
dragData_, event.getLocation(), dragModifiers_, dragOperations_);
37+
}
38+
39+
@Override
40+
public void dragExit(DropTargetEvent event) {
41+
AssertDragData();
42+
browser_.dragTargetDragLeave();
43+
ClearDragData();
44+
}
45+
46+
@Override
47+
public void dragOver(DropTargetDragEvent event) {
48+
AssertDragData();
49+
browser_.dragTargetDragOver(event.getLocation(), dragModifiers_, dragOperations_);
50+
}
51+
52+
@Override
53+
public void dropActionChanged(DropTargetDragEvent event) {
54+
AssertDragData();
55+
acceptOperations_ = event.getDropAction();
56+
switch (acceptOperations_) {
57+
case DnDConstants.ACTION_LINK:
58+
dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_LINK;
59+
dragModifiers_ =
60+
EventFlags.EVENTFLAG_CONTROL_DOWN | EventFlags.EVENTFLAG_SHIFT_DOWN;
61+
break;
62+
case DnDConstants.ACTION_COPY:
63+
dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY;
64+
dragModifiers_ = EventFlags.EVENTFLAG_CONTROL_DOWN;
65+
break;
66+
case DnDConstants.ACTION_MOVE:
67+
dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_MOVE;
68+
dragModifiers_ = EventFlags.EVENTFLAG_SHIFT_DOWN;
69+
break;
70+
case DnDConstants.ACTION_NONE:
71+
// The user did not select an action, so use COPY as the default.
72+
dragOperations_ = CefDragData.DragOperations.DRAG_OPERATION_COPY;
73+
dragModifiers_ = EventFlags.EVENTFLAG_NONE;
74+
acceptOperations_ = DnDConstants.ACTION_COPY;
75+
break;
76+
}
77+
}
78+
79+
@Override
80+
public void drop(DropTargetDropEvent event) {
81+
AssertDragData();
82+
browser_.dragTargetDrop(event.getLocation(), dragModifiers_);
83+
event.acceptDrop(acceptOperations_);
84+
event.dropComplete(true);
85+
ClearDragData();
86+
}
87+
88+
private void CreateDragData(DropTargetDragEvent event) {
89+
assert dragData_ == null;
90+
dragData_ = createDragData(event);
91+
dropActionChanged(event);
92+
}
93+
94+
private void AssertDragData() {
95+
assert dragData_ != null;
96+
}
97+
98+
private void ClearDragData() {
99+
dragData_ = null;
100+
}
101+
102+
private static CefDragData createDragData(DropTargetDragEvent event) {
103+
CefDragData dragData = CefDragData.create();
104+
105+
Transferable transferable = event.getTransferable();
106+
DataFlavor[] flavors = transferable.getTransferDataFlavors();
107+
for (DataFlavor flavor : flavors) {
108+
try {
109+
// TODO(JCEF): Add support for other flavor types.
110+
if (flavor.isFlavorJavaFileListType()) {
111+
List<File> files = (List<File>) transferable.getTransferData(flavor);
112+
for (File file : files) {
113+
dragData.addFile(file.getPath(), file.getName());
114+
}
115+
}
116+
} catch (Exception e) {
117+
// Data is no longer available or of unsupported flavor.
118+
e.printStackTrace();
119+
}
120+
}
121+
122+
return dragData;
123+
}
124+
}

java/org/cef/callback/CefDragData.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@
1212
* on any thread.
1313
*/
1414
public abstract class CefDragData {
15+
/**
16+
* Supported drag operation bit flags.
17+
*/
18+
public static final class DragOperations {
19+
public final static int DRAG_OPERATION_NONE = 0;
20+
public final static int DRAG_OPERATION_COPY = 1;
21+
public final static int DRAG_OPERATION_LINK = 2;
22+
public final static int DRAG_OPERATION_GENERIC = 4;
23+
public final static int DRAG_OPERATION_PRIVATE = 8;
24+
public final static int DRAG_OPERATION_MOVE = 16;
25+
public final static int DRAG_OPERATION_DELETE = 32;
26+
public final static int DRAG_OPERATION_EVERY = Integer.MAX_VALUE;
27+
}
28+
1529
// This CTOR can't be called directly. Call method create() instead.
1630
CefDragData() {}
1731

java/org/cef/handler/CefContextMenuHandler.java

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,6 @@
1414
* class will be called on the UI thread.
1515
*/
1616
public interface CefContextMenuHandler {
17-
/**
18-
* Supported event bit flags.
19-
*/
20-
public static final class EventFlags {
21-
public final static int EVENTFLAG_NONE = 0;
22-
public final static int EVENTFLAG_CAPS_LOCK_ON = 1 << 0;
23-
public final static int EVENTFLAG_SHIFT_DOWN = 1 << 1;
24-
public final static int EVENTFLAG_CONTROL_DOWN = 1 << 2;
25-
public final static int EVENTFLAG_ALT_DOWN = 1 << 3;
26-
public final static int EVENTFLAG_LEFT_MOUSE_BUTTON = 1 << 4;
27-
public final static int EVENTFLAG_MIDDLE_MOUSE_BUTTON = 1 << 5;
28-
public final static int EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6;
29-
// Mac OS-X command key.
30-
public final static int EVENTFLAG_COMMAND_DOWN = 1 << 7;
31-
public final static int EVENTFLAG_NUM_LOCK_ON = 1 << 8;
32-
public final static int EVENTFLAG_IS_KEY_PAD = 1 << 9;
33-
public final static int EVENTFLAG_IS_LEFT = 1 << 10;
34-
public final static int EVENTFLAG_IS_RIGHT = 1 << 11;
35-
}
36-
3717
/**
3818
* Called before a context menu is displayed.
3919
*

java/org/cef/misc/EventFlags.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.cef.misc;
2+
3+
/**
4+
* Supported event bit flags.
5+
*/
6+
public final class EventFlags {
7+
public final static int EVENTFLAG_NONE = 0;
8+
public final static int EVENTFLAG_CAPS_LOCK_ON = 1 << 0;
9+
public final static int EVENTFLAG_SHIFT_DOWN = 1 << 1;
10+
public final static int EVENTFLAG_CONTROL_DOWN = 1 << 2;
11+
public final static int EVENTFLAG_ALT_DOWN = 1 << 3;
12+
public final static int EVENTFLAG_LEFT_MOUSE_BUTTON = 1 << 4;
13+
public final static int EVENTFLAG_MIDDLE_MOUSE_BUTTON = 1 << 5;
14+
public final static int EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6;
15+
// Mac OS-X command key.
16+
public final static int EVENTFLAG_COMMAND_DOWN = 1 << 7;
17+
public final static int EVENTFLAG_NUM_LOCK_ON = 1 << 8;
18+
public final static int EVENTFLAG_IS_KEY_PAD = 1 << 9;
19+
public final static int EVENTFLAG_IS_LEFT = 1 << 10;
20+
public final static int EVENTFLAG_IS_RIGHT = 1 << 11;
21+
}

0 commit comments

Comments
 (0)