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