Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11/XDnDDragSourceProtocol.java
41159 views
1
/*
2
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.awt.X11;
27
28
import java.awt.datatransfer.Transferable;
29
import java.awt.datatransfer.DataFlavor;
30
31
import java.awt.dnd.DnDConstants;
32
import java.awt.dnd.InvalidDnDOperationException;
33
34
import java.util.Map;
35
36
import sun.util.logging.PlatformLogger;
37
38
import jdk.internal.misc.Unsafe;
39
40
/**
41
* XDragSourceProtocol implementation for XDnD protocol.
42
*
43
* @since 1.5
44
*/
45
class XDnDDragSourceProtocol extends XDragSourceProtocol {
46
private static final PlatformLogger logger =
47
PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDragSourceProtocol");
48
49
private static final Unsafe unsafe = XlibWrapper.unsafe;
50
51
protected XDnDDragSourceProtocol(XDragSourceProtocolListener listener) {
52
super(listener);
53
}
54
55
/**
56
* Creates an instance associated with the specified listener.
57
*
58
* @throws NullPointerException if listener is {@code null}.
59
*/
60
static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) {
61
return new XDnDDragSourceProtocol(listener);
62
}
63
64
public String getProtocolName() {
65
return XDragAndDropProtocols.XDnD;
66
}
67
68
/**
69
* Performs protocol-specific drag initialization.
70
*
71
* @return true if the initialized successfully.
72
*/
73
protected void initializeDragImpl(int actions, Transferable contents,
74
Map<Long, DataFlavor> formatMap, long[] formats)
75
throws InvalidDnDOperationException,
76
IllegalArgumentException, XException {
77
assert XToolkit.isAWTLockHeldByCurrentThread();
78
79
long window = XDragSourceProtocol.getDragSourceWindow();
80
81
long data = Native.allocateLongArray(3);
82
int action_count = 0;
83
try {
84
if ((actions & DnDConstants.ACTION_COPY) != 0) {
85
Native.putLong(data, action_count,
86
XDnDConstants.XA_XdndActionCopy.getAtom());
87
action_count++;
88
}
89
if ((actions & DnDConstants.ACTION_MOVE) != 0) {
90
Native.putLong(data, action_count,
91
XDnDConstants.XA_XdndActionMove.getAtom());
92
action_count++;
93
}
94
if ((actions & DnDConstants.ACTION_LINK) != 0) {
95
Native.putLong(data, action_count,
96
XDnDConstants.XA_XdndActionLink.getAtom());
97
action_count++;
98
}
99
100
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
101
XDnDConstants.XA_XdndActionList.setAtomData(window,
102
XAtom.XA_ATOM,
103
data, action_count);
104
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
105
106
if ((XErrorHandlerUtil.saved_error) != null &&
107
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
108
cleanup();
109
throw new XException("Cannot write XdndActionList property");
110
}
111
} finally {
112
unsafe.freeMemory(data);
113
data = 0;
114
}
115
116
data = Native.allocateLongArray(formats.length);
117
118
try {
119
Native.put(data, formats);
120
121
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
122
XDnDConstants.XA_XdndTypeList.setAtomData(window,
123
XAtom.XA_ATOM,
124
data, formats.length);
125
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
126
127
if ((XErrorHandlerUtil.saved_error != null) &&
128
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
129
cleanup();
130
throw new XException("Cannot write XdndActionList property");
131
}
132
} finally {
133
unsafe.freeMemory(data);
134
data = 0;
135
}
136
137
if (!XDnDConstants.XDnDSelection.setOwner(contents, formatMap, formats,
138
XConstants.CurrentTime)) {
139
cleanup();
140
throw new InvalidDnDOperationException("Cannot acquire selection ownership");
141
}
142
}
143
144
private boolean processXdndStatus(XClientMessageEvent xclient) {
145
int action = DnDConstants.ACTION_NONE;
146
147
/* Ignore XDnD messages from all other windows. */
148
if (xclient.get_data(0) != getTargetWindow()) {
149
return true;
150
}
151
152
if ((xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0) {
153
/* This feature is new in XDnD version 2, but we can use it as XDnD
154
compliance only requires supporting version 3 and up. */
155
action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(4));
156
}
157
158
getProtocolListener().handleDragReply(action);
159
160
return true;
161
}
162
163
private boolean processXdndFinished(XClientMessageEvent xclient) {
164
/* Ignore XDnD messages from all other windows. */
165
if (xclient.get_data(0) != getTargetWindow()) {
166
return true;
167
}
168
169
if (getTargetProtocolVersion() >= 5) {
170
boolean success = (xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0;
171
int action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(2));
172
getProtocolListener().handleDragFinished(success, action);
173
} else {
174
getProtocolListener().handleDragFinished();
175
}
176
177
finalizeDrop();
178
179
return true;
180
}
181
182
public boolean processClientMessage(XClientMessageEvent xclient) {
183
if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom()) {
184
return processXdndStatus(xclient);
185
} else if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {
186
return processXdndFinished(xclient);
187
} else {
188
return false;
189
}
190
}
191
192
public TargetWindowInfo getTargetWindowInfo(long window) {
193
assert XToolkit.isAWTLockHeldByCurrentThread();
194
195
WindowPropertyGetter wpg1 =
196
new WindowPropertyGetter(window, XDnDConstants.XA_XdndAware, 0, 1,
197
false, XConstants.AnyPropertyType);
198
199
int status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
200
201
if (status == XConstants.Success &&
202
wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {
203
204
int targetVersion = (int)Native.getLong(wpg1.getData());
205
206
wpg1.dispose();
207
208
if (targetVersion >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {
209
long proxy = 0;
210
int protocolVersion =
211
targetVersion < XDnDConstants.XDND_PROTOCOL_VERSION ?
212
targetVersion : XDnDConstants.XDND_PROTOCOL_VERSION;
213
214
WindowPropertyGetter wpg2 =
215
new WindowPropertyGetter(window, XDnDConstants.XA_XdndProxy,
216
0, 1, false, XAtom.XA_WINDOW);
217
218
try {
219
status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
220
221
if (status == XConstants.Success &&
222
wpg2.getData() != 0 &&
223
wpg2.getActualType() == XAtom.XA_WINDOW) {
224
225
proxy = Native.getLong(wpg2.getData());
226
}
227
} finally {
228
wpg2.dispose();
229
}
230
231
if (proxy != 0) {
232
WindowPropertyGetter wpg3 =
233
new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,
234
0, 1, false, XAtom.XA_WINDOW);
235
236
try {
237
status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
238
239
if (status != XConstants.Success ||
240
wpg3.getData() == 0 ||
241
wpg3.getActualType() != XAtom.XA_WINDOW ||
242
Native.getLong(wpg3.getData()) != proxy) {
243
244
proxy = 0;
245
} else {
246
WindowPropertyGetter wpg4 =
247
new WindowPropertyGetter(proxy,
248
XDnDConstants.XA_XdndAware,
249
0, 1, false,
250
XConstants.AnyPropertyType);
251
252
try {
253
status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
254
255
if (status != XConstants.Success ||
256
wpg4.getData() == 0 ||
257
wpg4.getActualType() != XAtom.XA_ATOM) {
258
259
proxy = 0;
260
}
261
} finally {
262
wpg4.dispose();
263
}
264
}
265
} finally {
266
wpg3.dispose();
267
}
268
}
269
270
return new TargetWindowInfo(proxy, protocolVersion);
271
}
272
} else {
273
wpg1.dispose();
274
}
275
276
return null;
277
}
278
279
public void sendEnterMessage(long[] formats,
280
int sourceAction, int sourceActions, long time) {
281
assert XToolkit.isAWTLockHeldByCurrentThread();
282
assert getTargetWindow() != 0;
283
assert formats != null;
284
285
XClientMessageEvent msg = new XClientMessageEvent();
286
try {
287
msg.set_type(XConstants.ClientMessage);
288
msg.set_window(getTargetWindow());
289
msg.set_format(32);
290
msg.set_message_type(XDnDConstants.XA_XdndEnter.getAtom());
291
msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
292
long data1 =
293
getTargetProtocolVersion() << XDnDConstants.XDND_PROTOCOL_SHIFT;
294
data1 |= formats.length > 3 ? XDnDConstants.XDND_DATA_TYPES_BIT : 0;
295
msg.set_data(1, data1);
296
msg.set_data(2, formats.length > 0 ? formats[0] : 0);
297
msg.set_data(3, formats.length > 1 ? formats[1] : 0);
298
msg.set_data(4, formats.length > 2 ? formats[2] : 0);
299
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
300
getTargetProxyWindow(),
301
false, XConstants.NoEventMask,
302
msg.pData);
303
} finally {
304
msg.dispose();
305
}
306
}
307
308
public void sendMoveMessage(int xRoot, int yRoot,
309
int sourceAction, int sourceActions, long time) {
310
assert XToolkit.isAWTLockHeldByCurrentThread();
311
assert getTargetWindow() != 0;
312
313
XClientMessageEvent msg = new XClientMessageEvent();
314
try {
315
msg.set_type(XConstants.ClientMessage);
316
msg.set_window(getTargetWindow());
317
msg.set_format(32);
318
msg.set_message_type(XDnDConstants.XA_XdndPosition.getAtom());
319
msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
320
msg.set_data(1, 0); /* flags */
321
msg.set_data(2, xRoot << 16 | yRoot);
322
msg.set_data(3, time);
323
msg.set_data(4, XDnDConstants.getXDnDActionForJavaAction(sourceAction));
324
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
325
getTargetProxyWindow(),
326
false, XConstants.NoEventMask,
327
msg.pData);
328
} finally {
329
msg.dispose();
330
}
331
}
332
333
public void sendLeaveMessage(long time) {
334
assert XToolkit.isAWTLockHeldByCurrentThread();
335
assert getTargetWindow() != 0;
336
337
XClientMessageEvent msg = new XClientMessageEvent();
338
try {
339
msg.set_type(XConstants.ClientMessage);
340
msg.set_window(getTargetWindow());
341
msg.set_format(32);
342
msg.set_message_type(XDnDConstants.XA_XdndLeave.getAtom());
343
msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
344
msg.set_data(1, 0);
345
msg.set_data(2, 0);
346
msg.set_data(3, 0);
347
msg.set_data(4, 0);
348
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
349
getTargetProxyWindow(),
350
false, XConstants.NoEventMask,
351
msg.pData);
352
} finally {
353
msg.dispose();
354
}
355
}
356
357
public void sendDropMessage(int xRoot, int yRoot,
358
int sourceAction, int sourceActions,
359
long time) {
360
assert XToolkit.isAWTLockHeldByCurrentThread();
361
assert getTargetWindow() != 0;
362
363
XClientMessageEvent msg = new XClientMessageEvent();
364
try {
365
msg.set_type(XConstants.ClientMessage);
366
msg.set_window(getTargetWindow());
367
msg.set_format(32);
368
msg.set_message_type(XDnDConstants.XA_XdndDrop.getAtom());
369
msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
370
msg.set_data(1, 0); /* flags */
371
msg.set_data(2, time);
372
msg.set_data(3, 0);
373
msg.set_data(4, 0);
374
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
375
getTargetProxyWindow(),
376
false, XConstants.NoEventMask,
377
msg.pData);
378
} finally {
379
msg.dispose();
380
}
381
}
382
383
public boolean processProxyModeEvent(XClientMessageEvent xclient,
384
long sourceWindow) {
385
if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom() ||
386
xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {
387
388
if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {
389
XDragSourceContextPeer.setProxyModeSourceWindow(0);
390
}
391
392
// This can happen if the drag operation started in the XEmbed server.
393
// In this case there is no need to forward it elsewhere, we should
394
// process it here.
395
if (xclient.get_window() == sourceWindow) {
396
return false;
397
}
398
399
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
400
logger.finest(" sourceWindow=" + sourceWindow +
401
" get_window=" + xclient.get_window() +
402
" xclient=" + xclient);
403
}
404
xclient.set_data(0, xclient.get_window());
405
xclient.set_window(sourceWindow);
406
407
assert XToolkit.isAWTLockHeldByCurrentThread();
408
409
XlibWrapper.XSendEvent(XToolkit.getDisplay(), sourceWindow,
410
false, XConstants.NoEventMask,
411
xclient.pData);
412
413
return true;
414
}
415
416
return false;
417
}
418
419
// TODO: register this runnable with XDnDSelection.
420
public void run() {
421
// XdndSelection ownership lost.
422
cleanup();
423
}
424
}
425
426