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/MotifDnDDragSourceProtocol.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 jdk.internal.misc.Unsafe;
37
38
/**
39
* XDragSourceProtocol implementation for Motif DnD protocol.
40
*
41
* @since 1.5
42
*/
43
class MotifDnDDragSourceProtocol extends XDragSourceProtocol
44
implements XEventDispatcher {
45
46
private static final Unsafe unsafe = XlibWrapper.unsafe;
47
48
private long targetEnterServerTime = XConstants.CurrentTime;
49
50
protected MotifDnDDragSourceProtocol(XDragSourceProtocolListener listener) {
51
super(listener);
52
XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(), this);
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 MotifDnDDragSourceProtocol(listener);
62
}
63
64
public String getProtocolName() {
65
return XDragAndDropProtocols.MotifDnD;
66
}
67
68
protected void initializeDragImpl(int actions, Transferable contents,
69
Map<Long, DataFlavor> formatMap, long[] formats)
70
throws InvalidDnDOperationException,
71
IllegalArgumentException, XException {
72
73
long window = XDragSourceProtocol.getDragSourceWindow();
74
75
/* Write the Motif DnD initiator info on the root XWindow. */
76
try {
77
int index = MotifDnDConstants.getIndexForTargetList(formats);
78
79
MotifDnDConstants.writeDragInitiatorInfoStruct(window, index);
80
} catch (XException xe) {
81
cleanup();
82
throw xe;
83
} catch (InvalidDnDOperationException idoe) {
84
cleanup();
85
throw idoe;
86
}
87
88
if (!MotifDnDConstants.MotifDnDSelection.setOwner(contents, formatMap,
89
formats,
90
XConstants.CurrentTime)) {
91
cleanup();
92
throw new InvalidDnDOperationException("Cannot acquire selection ownership");
93
}
94
}
95
96
/**
97
* Processes the specified client message event.
98
*
99
* @return true if the event was successfully processed.
100
*/
101
public boolean processClientMessage(XClientMessageEvent xclient) {
102
if (xclient.get_message_type() !=
103
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
104
return false;
105
}
106
107
long data = xclient.get_data();
108
byte reason = (byte)(unsafe.getByte(data) &
109
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
110
byte origin = (byte)(unsafe.getByte(data) &
111
MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
112
byte byteOrder = unsafe.getByte(data + 1);
113
boolean swapNeeded = byteOrder != MotifDnDConstants.getByteOrderByte();
114
int action = DnDConstants.ACTION_NONE;
115
int x = 0;
116
int y = 0;
117
118
/* Only receiver messages should be handled. */
119
if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER) {
120
return false;
121
}
122
123
switch (reason) {
124
case MotifDnDConstants.DROP_SITE_ENTER:
125
case MotifDnDConstants.DROP_SITE_LEAVE:
126
case MotifDnDConstants.DRAG_MOTION:
127
case MotifDnDConstants.OPERATION_CHANGED:
128
break;
129
default:
130
// Unknown reason.
131
return false;
132
}
133
134
int t = unsafe.getInt(data + 4);
135
if (swapNeeded) {
136
t = MotifDnDConstants.Swapper.swap(t);
137
}
138
long time = t & 0xffffffffL;
139
// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.
140
141
/* Discard events from the previous receiver. */
142
if (targetEnterServerTime == XConstants.CurrentTime ||
143
time < targetEnterServerTime) {
144
return true;
145
}
146
147
if (reason != MotifDnDConstants.DROP_SITE_LEAVE) {
148
short flags = unsafe.getShort(data + 2);
149
if (swapNeeded) {
150
flags = MotifDnDConstants.Swapper.swap(flags);
151
}
152
153
byte status = (byte)((flags & MotifDnDConstants.MOTIF_DND_STATUS_MASK) >>
154
MotifDnDConstants.MOTIF_DND_STATUS_SHIFT);
155
byte motif_action = (byte)((flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
156
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT);
157
158
if (status == MotifDnDConstants.MOTIF_VALID_DROP_SITE) {
159
action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
160
} else {
161
action = DnDConstants.ACTION_NONE;
162
}
163
164
short tx = unsafe.getShort(data + 8);
165
short ty = unsafe.getShort(data + 10);
166
if (swapNeeded) {
167
tx = MotifDnDConstants.Swapper.swap(tx);
168
ty = MotifDnDConstants.Swapper.swap(ty);
169
}
170
x = tx;
171
y = ty;
172
}
173
174
getProtocolListener().handleDragReply(action, x, y);
175
176
return true;
177
}
178
179
public TargetWindowInfo getTargetWindowInfo(long window) {
180
assert XToolkit.isAWTLockHeldByCurrentThread();
181
182
WindowPropertyGetter wpg =
183
new WindowPropertyGetter(window,
184
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
185
0, 0xFFFF, false,
186
XConstants.AnyPropertyType);
187
188
try {
189
int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
190
191
/*
192
* DragICCI.h:
193
*
194
* typedef struct _xmDragReceiverInfoStruct{
195
* BYTE byte_order;
196
* BYTE protocol_version;
197
* BYTE drag_protocol_style;
198
* BYTE pad1;
199
* CARD32 proxy_window B32;
200
* CARD16 num_drop_sites B16;
201
* CARD16 pad2 B16;
202
* CARD32 heap_offset B32;
203
* } xmDragReceiverInfoStruct;
204
*/
205
if (status == XConstants.Success && wpg.getData() != 0 &&
206
wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
207
wpg.getNumberOfItems() >=
208
MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
209
210
long data = wpg.getData();
211
byte byteOrderByte = unsafe.getByte(data);
212
byte dragProtocolStyle = unsafe.getByte(data + 2);
213
switch (dragProtocolStyle) {
214
case MotifDnDConstants.MOTIF_PREFER_PREREGISTER_STYLE :
215
case MotifDnDConstants.MOTIF_PREFER_DYNAMIC_STYLE :
216
case MotifDnDConstants.MOTIF_DYNAMIC_STYLE :
217
case MotifDnDConstants.MOTIF_PREFER_RECEIVER_STYLE :
218
int proxy = unsafe.getInt(data + 4);
219
if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
220
proxy = MotifDnDConstants.Swapper.swap(proxy);
221
}
222
223
int protocolVersion = unsafe.getByte(data + 1);
224
225
return new TargetWindowInfo(proxy, protocolVersion);
226
default:
227
// Unsupported protocol style.
228
return null;
229
}
230
} else {
231
return null;
232
}
233
} finally {
234
wpg.dispose();
235
}
236
}
237
238
public void sendEnterMessage(long[] formats,
239
int sourceAction, int sourceActions, long time) {
240
assert XToolkit.isAWTLockHeldByCurrentThread();
241
assert getTargetWindow() != 0;
242
assert formats != null;
243
244
targetEnterServerTime = time;
245
246
XClientMessageEvent msg = new XClientMessageEvent();
247
try {
248
msg.set_type(XConstants.ClientMessage);
249
msg.set_window(getTargetWindow());
250
msg.set_format(8);
251
msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
252
253
long data = msg.get_data();
254
int flags =
255
(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
256
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
257
(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
258
MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
259
260
unsafe.putByte(data,
261
(byte)(MotifDnDConstants.TOP_LEVEL_ENTER |
262
MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
263
unsafe.putByte(data + 1,
264
MotifDnDConstants.getByteOrderByte());
265
unsafe.putShort(data + 2, (short)flags);
266
unsafe.putInt(data + 4, (int)time);
267
unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());
268
unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());
269
270
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
271
getTargetProxyWindow(),
272
false, XConstants.NoEventMask,
273
msg.pData);
274
} finally {
275
msg.dispose();
276
}
277
}
278
279
public void sendMoveMessage(int xRoot, int yRoot,
280
int sourceAction, int sourceActions, long time) {
281
assert XToolkit.isAWTLockHeldByCurrentThread();
282
assert getTargetWindow() != 0;
283
284
XClientMessageEvent msg = new XClientMessageEvent();
285
try {
286
msg.set_type(XConstants.ClientMessage);
287
msg.set_window(getTargetWindow());
288
msg.set_format(8);
289
msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
290
291
long data = msg.get_data();
292
int flags =
293
(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
294
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
295
(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
296
MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
297
298
unsafe.putByte(data,
299
(byte)(MotifDnDConstants.DRAG_MOTION |
300
MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
301
unsafe.putByte(data + 1,
302
MotifDnDConstants.getByteOrderByte());
303
unsafe.putShort(data + 2, (short)flags);
304
unsafe.putInt(data + 4, (int)time);
305
unsafe.putShort(data + 8, (short)xRoot);
306
unsafe.putShort(data + 10, (short)yRoot);
307
308
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
309
getTargetProxyWindow(),
310
false, XConstants.NoEventMask,
311
msg.pData);
312
} finally {
313
msg.dispose();
314
}
315
}
316
317
public void sendLeaveMessage(long time) {
318
assert XToolkit.isAWTLockHeldByCurrentThread();
319
assert getTargetWindow() != 0;
320
321
XClientMessageEvent msg = new XClientMessageEvent();
322
try {
323
msg.set_type(XConstants.ClientMessage);
324
msg.set_window(getTargetWindow());
325
msg.set_format(8);
326
msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
327
328
long data = msg.get_data();
329
330
unsafe.putByte(data,
331
(byte)(MotifDnDConstants.TOP_LEVEL_LEAVE |
332
MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
333
unsafe.putByte(data + 1,
334
MotifDnDConstants.getByteOrderByte());
335
unsafe.putShort(data + 2, (short)0);
336
unsafe.putInt(data + 4, (int)time);
337
unsafe.putInt(data + 8, (int)XDragSourceProtocol.getDragSourceWindow());
338
339
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
340
getTargetProxyWindow(),
341
false, XConstants.NoEventMask,
342
msg.pData);
343
} finally {
344
msg.dispose();
345
}
346
}
347
348
protected void sendDropMessage(int xRoot, int yRoot,
349
int sourceAction, int sourceActions,
350
long time) {
351
assert XToolkit.isAWTLockHeldByCurrentThread();
352
assert getTargetWindow() != 0;
353
354
/*
355
* Motif drop sites expect TOP_LEVEL_LEAVE before DROP_START.
356
*/
357
sendLeaveMessage(time);
358
359
XClientMessageEvent msg = new XClientMessageEvent();
360
try {
361
msg.set_type(XConstants.ClientMessage);
362
msg.set_window(getTargetWindow());
363
msg.set_format(8);
364
msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
365
366
long data = msg.get_data();
367
int flags =
368
(MotifDnDConstants.getMotifActionsForJavaActions(sourceAction) <<
369
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT) |
370
(MotifDnDConstants.getMotifActionsForJavaActions(sourceActions) <<
371
MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT);
372
373
unsafe.putByte(data,
374
(byte)(MotifDnDConstants.DROP_START |
375
MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR));
376
unsafe.putByte(data + 1,
377
MotifDnDConstants.getByteOrderByte());
378
unsafe.putShort(data + 2, (short)flags);
379
unsafe.putInt(data + 4, (int)time);
380
unsafe.putShort(data + 8, (short)xRoot);
381
unsafe.putShort(data + 10, (short)yRoot);
382
unsafe.putInt(data + 12, (int)MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom());
383
unsafe.putInt(data + 16, (int)XDragSourceProtocol.getDragSourceWindow());
384
385
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
386
getTargetProxyWindow(),
387
false, XConstants.NoEventMask,
388
msg.pData);
389
} finally {
390
msg.dispose();
391
}
392
}
393
394
public boolean processProxyModeEvent(XClientMessageEvent xclient,
395
long sourceWindow) {
396
// Motif DnD for XEmbed is not implemented.
397
return false;
398
}
399
400
public void cleanupTargetInfo() {
401
super.cleanupTargetInfo();
402
targetEnterServerTime = XConstants.CurrentTime;
403
}
404
405
public void dispatchEvent(XEvent ev) {
406
switch (ev.get_type()) {
407
case XConstants.SelectionRequest:
408
XSelectionRequestEvent xsre = ev.get_xselectionrequest();
409
long atom = xsre.get_selection();
410
411
if (atom == MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom()) {
412
long target = xsre.get_target();
413
if (target == MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom()) {
414
getProtocolListener().handleDragFinished(true);
415
} else if (target == MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom()) {
416
getProtocolListener().handleDragFinished(false);
417
}
418
}
419
break;
420
}
421
}
422
}
423
424