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