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/MotifDnDDropTargetProtocol.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.Point;
29
30
import java.awt.dnd.DnDConstants;
31
32
import java.awt.event.MouseEvent;
33
34
import java.io.IOException;
35
36
import sun.misc.Unsafe;
37
38
/**
39
* XDropTargetProtocol implementation for Motif DnD protocol.
40
*
41
* @since 1.5
42
*/
43
class MotifDnDDropTargetProtocol extends XDropTargetProtocol {
44
private static final Unsafe unsafe = XlibWrapper.unsafe;
45
46
private long sourceWindow = 0;
47
private long sourceWindowMask = 0;
48
private int sourceProtocolVersion = 0;
49
private int sourceActions = DnDConstants.ACTION_NONE;
50
private long[] sourceFormats = null;
51
private long sourceAtom = 0;
52
private int userAction = DnDConstants.ACTION_NONE;
53
private int sourceX = 0;
54
private int sourceY = 0;
55
private XWindow targetXWindow = null;
56
private boolean topLevelLeavePostponed = false;
57
58
protected MotifDnDDropTargetProtocol(XDropTargetProtocolListener listener) {
59
super(listener);
60
}
61
62
/**
63
* Creates an instance associated with the specified listener.
64
*
65
* @throws NullPointerException if listener is <code>null</code>.
66
*/
67
static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {
68
return new MotifDnDDropTargetProtocol(listener);
69
}
70
71
public String getProtocolName() {
72
return XDragAndDropProtocols.MotifDnD;
73
}
74
75
public void registerDropTarget(long window) {
76
assert XToolkit.isAWTLockHeldByCurrentThread();
77
78
MotifDnDConstants.writeDragReceiverInfoStruct(window);
79
}
80
81
public void unregisterDropTarget(long window) {
82
assert XToolkit.isAWTLockHeldByCurrentThread();
83
84
MotifDnDConstants.XA_MOTIF_ATOM_0.DeleteProperty(window);
85
}
86
87
public void registerEmbedderDropSite(long embedder) {
88
assert XToolkit.isAWTLockHeldByCurrentThread();
89
90
boolean overriden = false;
91
int version = 0;
92
long proxy = 0;
93
long newProxy = XDropTargetRegistry.getDnDProxyWindow();
94
int status = 0;
95
long data = 0;
96
int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
97
98
WindowPropertyGetter wpg =
99
new WindowPropertyGetter(embedder,
100
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
101
0, 0xFFFF, false,
102
XConstants.AnyPropertyType);
103
104
try {
105
status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
106
107
/*
108
* DragICCI.h:
109
*
110
* typedef struct _xmDragReceiverInfoStruct{
111
* BYTE byte_order;
112
* BYTE protocol_version;
113
* BYTE drag_protocol_style;
114
* BYTE pad1;
115
* CARD32 proxy_window B32;
116
* CARD16 num_drop_sites B16;
117
* CARD16 pad2 B16;
118
* CARD32 heap_offset B32;
119
* } xmDragReceiverInfoStruct;
120
*/
121
if (status == (int)XConstants.Success && wpg.getData() != 0 &&
122
wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
123
wpg.getNumberOfItems() >=
124
MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
125
126
overriden = true;
127
data = wpg.getData();
128
dataSize = wpg.getNumberOfItems();
129
130
byte byteOrderByte = unsafe.getByte(data);
131
132
{
133
int tproxy = unsafe.getInt(data + 4);
134
if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
135
tproxy = MotifDnDConstants.Swapper.swap(tproxy);
136
}
137
proxy = tproxy;
138
}
139
140
if (proxy == newProxy) {
141
// Embedder already registered.
142
return;
143
}
144
145
{
146
int tproxy = (int)newProxy;
147
if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
148
tproxy = MotifDnDConstants.Swapper.swap(tproxy);
149
}
150
unsafe.putInt(data + 4, tproxy);
151
}
152
} else {
153
data = unsafe.allocateMemory(dataSize);
154
155
unsafe.putByte(data, MotifDnDConstants.getByteOrderByte()); /* byte order */
156
unsafe.putByte(data + 1, MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION); /* protocol version */
157
unsafe.putByte(data + 2, (byte)MotifDnDConstants.MOTIF_DYNAMIC_STYLE); /* protocol style */
158
unsafe.putByte(data + 3, (byte)0); /* pad */
159
unsafe.putInt(data + 4, (int)newProxy); /* proxy window */
160
unsafe.putShort(data + 8, (short)0); /* num_drop_sites */
161
unsafe.putShort(data + 10, (short)0); /* pad */
162
unsafe.putInt(data + 12, dataSize);
163
}
164
165
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
166
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
167
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
168
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
169
8, XConstants.PropModeReplace,
170
data, dataSize);
171
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
172
173
if ((XErrorHandlerUtil.saved_error != null) &&
174
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
175
throw new XException("Cannot write Motif receiver info property");
176
}
177
} finally {
178
if (!overriden) {
179
unsafe.freeMemory(data);
180
data = 0;
181
}
182
wpg.dispose();
183
}
184
185
putEmbedderRegistryEntry(embedder, overriden, version, proxy);
186
}
187
188
public void unregisterEmbedderDropSite(long embedder) {
189
assert XToolkit.isAWTLockHeldByCurrentThread();
190
191
EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);
192
193
if (entry == null) {
194
return;
195
}
196
197
if (entry.isOverriden()) {
198
int status = 0;
199
200
WindowPropertyGetter wpg =
201
new WindowPropertyGetter(embedder,
202
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
203
0, 0xFFFF, false,
204
XConstants.AnyPropertyType);
205
206
try {
207
status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
208
209
/*
210
* DragICCI.h:
211
*
212
* typedef struct _xmDragReceiverInfoStruct{
213
* BYTE byte_order;
214
* BYTE protocol_version;
215
* BYTE drag_protocol_style;
216
* BYTE pad1;
217
* CARD32 proxy_window B32;
218
* CARD16 num_drop_sites B16;
219
* CARD16 pad2 B16;
220
* CARD32 heap_offset B32;
221
* } xmDragReceiverInfoStruct;
222
*/
223
if (status == (int)XConstants.Success && wpg.getData() != 0 &&
224
wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
225
wpg.getNumberOfItems() >=
226
MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
227
228
int dataSize = MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE;
229
long data = wpg.getData();
230
byte byteOrderByte = unsafe.getByte(data);
231
232
int tproxy = (int)entry.getProxy();
233
if (MotifDnDConstants.getByteOrderByte() != byteOrderByte) {
234
tproxy = MotifDnDConstants.Swapper.swap(tproxy);
235
}
236
237
unsafe.putInt(data + 4, tproxy);
238
239
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
240
XlibWrapper.XChangeProperty(XToolkit.getDisplay(), embedder,
241
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
242
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.getAtom(),
243
8, XConstants.PropModeReplace,
244
data, dataSize);
245
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
246
247
if ((XErrorHandlerUtil.saved_error != null) &&
248
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
249
throw new XException("Cannot write Motif receiver info property");
250
}
251
}
252
} finally {
253
wpg.dispose();
254
}
255
} else {
256
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO.DeleteProperty(embedder);
257
}
258
}
259
260
/*
261
* Gets and stores in the registry the embedder's Motif DnD drop site info
262
* from the embedded.
263
*/
264
public void registerEmbeddedDropSite(long embedded) {
265
assert XToolkit.isAWTLockHeldByCurrentThread();
266
267
boolean overriden = false;
268
int version = 0;
269
long proxy = 0;
270
int status = 0;
271
272
WindowPropertyGetter wpg =
273
new WindowPropertyGetter(embedded,
274
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
275
0, 0xFFFF, false,
276
XConstants.AnyPropertyType);
277
278
try {
279
status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
280
281
/*
282
* DragICCI.h:
283
*
284
* typedef struct _xmDragReceiverInfoStruct{
285
* BYTE byte_order;
286
* BYTE protocol_version;
287
* BYTE drag_protocol_style;
288
* BYTE pad1;
289
* CARD32 proxy_window B32;
290
* CARD16 num_drop_sites B16;
291
* CARD16 pad2 B16;
292
* CARD32 heap_offset B32;
293
* } xmDragReceiverInfoStruct;
294
*/
295
if (status == (int)XConstants.Success && wpg.getData() != 0 &&
296
wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
297
wpg.getNumberOfItems() >=
298
MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
299
300
overriden = true;
301
long data = wpg.getData();
302
303
byte byteOrderByte = unsafe.getByte(data);
304
305
{
306
int tproxy = unsafe.getInt(data + 4);
307
if (byteOrderByte != MotifDnDConstants.getByteOrderByte()) {
308
tproxy = MotifDnDConstants.Swapper.swap(tproxy);
309
}
310
proxy = tproxy;
311
}
312
}
313
} finally {
314
wpg.dispose();
315
}
316
317
putEmbedderRegistryEntry(embedded, overriden, version, proxy);
318
}
319
320
public boolean isProtocolSupported(long window) {
321
WindowPropertyGetter wpg =
322
new WindowPropertyGetter(window,
323
MotifDnDConstants.XA_MOTIF_DRAG_RECEIVER_INFO,
324
0, 0xFFFF, false,
325
XConstants.AnyPropertyType);
326
327
try {
328
int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
329
330
if (status == (int)XConstants.Success && wpg.getData() != 0 &&
331
wpg.getActualType() != 0 && wpg.getActualFormat() == 8 &&
332
wpg.getNumberOfItems() >=
333
MotifDnDConstants.MOTIF_RECEIVER_INFO_SIZE) {
334
return true;
335
} else {
336
return false;
337
}
338
} finally {
339
wpg.dispose();
340
}
341
}
342
343
private boolean processTopLevelEnter(XClientMessageEvent xclient) {
344
assert XToolkit.isAWTLockHeldByCurrentThread();
345
346
if (targetXWindow != null || sourceWindow != 0) {
347
return false;
348
}
349
350
if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)
351
&& getEmbedderRegistryEntry(xclient.get_window()) == null) {
352
return false;
353
}
354
355
long source_win = 0;
356
long source_win_mask = 0;
357
int protocol_version = 0;
358
long property_atom = 0;
359
long[] formats = null;
360
361
{
362
long data = xclient.get_data();
363
byte eventByteOrder = unsafe.getByte(data + 1);
364
source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);
365
property_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
366
}
367
368
/* Extract the available data types. */
369
{
370
WindowPropertyGetter wpg =
371
new WindowPropertyGetter(source_win,
372
XAtom.get(property_atom),
373
0, 0xFFFF,
374
false,
375
MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom());
376
377
try {
378
int status = wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
379
380
if (status == XConstants.Success && wpg.getData() != 0 &&
381
wpg.getActualType() ==
382
MotifDnDConstants.XA_MOTIF_DRAG_INITIATOR_INFO.getAtom() &&
383
wpg.getActualFormat() == 8 &&
384
wpg.getNumberOfItems() ==
385
MotifDnDConstants.MOTIF_INITIATOR_INFO_SIZE) {
386
387
long data = wpg.getData();
388
byte propertyByteOrder = unsafe.getByte(data);
389
390
protocol_version = unsafe.getByte(data + 1);
391
392
if (protocol_version !=
393
MotifDnDConstants.MOTIF_DND_PROTOCOL_VERSION) {
394
return false;
395
}
396
397
int index =
398
MotifDnDConstants.Swapper.getShort(data + 2, propertyByteOrder);
399
400
formats = MotifDnDConstants.getTargetListForIndex(index);
401
} else {
402
formats = new long[0];
403
}
404
} finally {
405
wpg.dispose();
406
}
407
}
408
409
/*
410
* Select for StructureNotifyMask to receive DestroyNotify in case of source
411
* crash.
412
*/
413
XWindowAttributes wattr = new XWindowAttributes();
414
try {
415
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
416
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
417
source_win, wattr.pData);
418
419
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
420
421
if ((status == 0) ||
422
((XErrorHandlerUtil.saved_error != null) &&
423
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
424
throw new XException("XGetWindowAttributes failed");
425
}
426
427
source_win_mask = wattr.get_your_event_mask();
428
} finally {
429
wattr.dispose();
430
}
431
432
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
433
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
434
source_win_mask |
435
XConstants.StructureNotifyMask);
436
437
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
438
439
if ((XErrorHandlerUtil.saved_error != null) &&
440
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
441
throw new XException("XSelectInput failed");
442
}
443
444
sourceWindow = source_win;
445
sourceWindowMask = source_win_mask;
446
sourceProtocolVersion = protocol_version;
447
/*
448
* TOP_LEVEL_ENTER doesn't communicate the list of supported actions
449
* They are provided in DRAG_MOTION.
450
*/
451
sourceActions = DnDConstants.ACTION_NONE;
452
sourceFormats = formats;
453
sourceAtom = property_atom;
454
455
return true;
456
}
457
458
private boolean processDragMotion(XClientMessageEvent xclient) {
459
long data = xclient.get_data();
460
byte eventByteOrder = unsafe.getByte(data + 1);
461
byte eventReason = (byte)(unsafe.getByte(data) &
462
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
463
int x = 0;
464
int y = 0;
465
466
short flags = MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);
467
468
int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
469
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
470
int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
471
MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;
472
473
int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
474
int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);
475
476
/* Append source window id to the event data, so that we can send the
477
response properly. */
478
{
479
int win = (int)sourceWindow;
480
if (eventByteOrder != MotifDnDConstants.getByteOrderByte()) {
481
win = MotifDnDConstants.Swapper.swap(win);
482
}
483
unsafe.putInt(data + 12, win);
484
}
485
486
XWindow xwindow = null;
487
{
488
XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
489
if (xbasewindow instanceof XWindow) {
490
xwindow = (XWindow)xbasewindow;
491
}
492
}
493
494
if (eventReason == MotifDnDConstants.OPERATION_CHANGED) {
495
/* OPERATION_CHANGED event doesn't provide coordinates, so we use
496
previously stored position and component ref. */
497
x = sourceX;
498
y = sourceY;
499
500
if (xwindow == null) {
501
xwindow = targetXWindow;
502
}
503
} else {
504
x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
505
y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);
506
507
if (xwindow == null) {
508
long receiver =
509
XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
510
xclient.get_window(), x, y);
511
512
if (receiver != 0) {
513
XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
514
if (xbasewindow instanceof XWindow) {
515
xwindow = (XWindow)xbasewindow;
516
}
517
}
518
}
519
520
if (xwindow != null) {
521
Point p = xwindow.toLocal(x, y);
522
x = p.x;
523
y = p.y;
524
}
525
}
526
527
if (xwindow == null) {
528
if (targetXWindow != null) {
529
notifyProtocolListener(targetXWindow, x, y,
530
DnDConstants.ACTION_NONE, java_actions,
531
xclient, MouseEvent.MOUSE_EXITED);
532
}
533
} else {
534
int java_event_id = 0;
535
536
if (targetXWindow == null) {
537
java_event_id = MouseEvent.MOUSE_ENTERED;
538
} else {
539
java_event_id = MouseEvent.MOUSE_DRAGGED;
540
}
541
542
notifyProtocolListener(xwindow, x, y, java_action, java_actions,
543
xclient, java_event_id);
544
}
545
546
sourceActions = java_actions;
547
userAction = java_action;
548
sourceX = x;
549
sourceY = y;
550
targetXWindow = xwindow;
551
552
return true;
553
}
554
555
private boolean processTopLevelLeave(XClientMessageEvent xclient) {
556
assert XToolkit.isAWTLockHeldByCurrentThread();
557
558
long data = xclient.get_data();
559
byte eventByteOrder = unsafe.getByte(data + 1);
560
561
long source_win = MotifDnDConstants.Swapper.getInt(data + 8, eventByteOrder);
562
563
/* Ignore Motif DnD messages from all other windows. */
564
if (source_win != sourceWindow) {
565
return false;
566
}
567
568
/*
569
* Postpone upcall to java, so that we can abort it in case
570
* if drop immediatelly follows (see BugTraq ID 4395290).
571
* Send a dummy ClientMessage event to guarantee that a postponed java
572
* upcall will be processed.
573
*/
574
topLevelLeavePostponed = true;
575
{
576
long proxy;
577
578
/*
579
* If this is an embedded drop site, the event should go to the
580
* awt_root_window as this is a proxy for all embedded drop sites.
581
* Otherwise the event should go to the event->window, as we don't use
582
* proxies for normal drop sites.
583
*/
584
if (getEmbedderRegistryEntry(xclient.get_window()) != null) {
585
proxy = XDropTargetRegistry.getDnDProxyWindow();
586
} else {
587
proxy = xclient.get_window();
588
}
589
590
XClientMessageEvent dummy = new XClientMessageEvent();
591
592
try {
593
dummy.set_type(XConstants.ClientMessage);
594
dummy.set_window(xclient.get_window());
595
dummy.set_format(32);
596
dummy.set_message_type(0);
597
dummy.set_data(0, 0);
598
dummy.set_data(1, 0);
599
dummy.set_data(2, 0);
600
dummy.set_data(3, 0);
601
dummy.set_data(4, 0);
602
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
603
proxy, false, XConstants.NoEventMask,
604
dummy.pData);
605
} finally {
606
dummy.dispose();
607
}
608
}
609
return true;
610
}
611
612
private boolean processDropStart(XClientMessageEvent xclient) {
613
long data = xclient.get_data();
614
byte eventByteOrder = unsafe.getByte(data + 1);
615
616
long source_win =
617
MotifDnDConstants.Swapper.getInt(data + 16, eventByteOrder);
618
619
/* Ignore Motif DnD messages from all other windows. */
620
if (source_win != sourceWindow) {
621
return false;
622
}
623
624
long property_atom =
625
MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
626
627
short flags =
628
MotifDnDConstants.Swapper.getShort(data + 2, eventByteOrder);
629
630
int motif_action = (flags & MotifDnDConstants.MOTIF_DND_ACTION_MASK) >>
631
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
632
int motif_actions = (flags & MotifDnDConstants.MOTIF_DND_ACTIONS_MASK) >>
633
MotifDnDConstants.MOTIF_DND_ACTIONS_SHIFT;
634
635
int java_action = MotifDnDConstants.getJavaActionsForMotifActions(motif_action);
636
int java_actions = MotifDnDConstants.getJavaActionsForMotifActions(motif_actions);
637
638
int x = MotifDnDConstants.Swapper.getShort(data + 8, eventByteOrder);
639
int y = MotifDnDConstants.Swapper.getShort(data + 10, eventByteOrder);
640
641
XWindow xwindow = null;
642
{
643
XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
644
if (xbasewindow instanceof XWindow) {
645
xwindow = (XWindow)xbasewindow;
646
}
647
}
648
649
if (xwindow == null) {
650
long receiver =
651
XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
652
xclient.get_window(), x, y);
653
654
if (receiver != 0) {
655
XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
656
if (xbasewindow instanceof XWindow) {
657
xwindow = (XWindow)xbasewindow;
658
}
659
}
660
}
661
662
if (xwindow != null) {
663
Point p = xwindow.toLocal(x, y);
664
x = p.x;
665
y = p.y;
666
}
667
668
if (xwindow != null) {
669
notifyProtocolListener(xwindow, x, y, java_action, java_actions,
670
xclient, MouseEvent.MOUSE_RELEASED);
671
} else if (targetXWindow != null) {
672
notifyProtocolListener(targetXWindow, x, y,
673
DnDConstants.ACTION_NONE, java_actions,
674
xclient, MouseEvent.MOUSE_EXITED);
675
}
676
677
return true;
678
}
679
680
public int getMessageType(XClientMessageEvent xclient) {
681
if (xclient.get_message_type() !=
682
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
683
684
return UNKNOWN_MESSAGE;
685
}
686
687
long data = xclient.get_data();
688
byte reason = (byte)(unsafe.getByte(data) &
689
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
690
691
switch (reason) {
692
case MotifDnDConstants.TOP_LEVEL_ENTER :
693
return ENTER_MESSAGE;
694
case MotifDnDConstants.DRAG_MOTION :
695
case MotifDnDConstants.OPERATION_CHANGED :
696
return MOTION_MESSAGE;
697
case MotifDnDConstants.TOP_LEVEL_LEAVE :
698
return LEAVE_MESSAGE;
699
case MotifDnDConstants.DROP_START :
700
return DROP_MESSAGE;
701
default:
702
return UNKNOWN_MESSAGE;
703
}
704
}
705
706
protected boolean processClientMessageImpl(XClientMessageEvent xclient) {
707
if (xclient.get_message_type() !=
708
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
709
if (topLevelLeavePostponed) {
710
topLevelLeavePostponed = false;
711
cleanup();
712
}
713
714
return false;
715
}
716
717
long data = xclient.get_data();
718
byte reason = (byte)(unsafe.getByte(data) &
719
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
720
byte origin = (byte)(unsafe.getByte(data) &
721
MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
722
723
if (topLevelLeavePostponed) {
724
topLevelLeavePostponed = false;
725
if (reason != MotifDnDConstants.DROP_START) {
726
cleanup();
727
}
728
}
729
730
/* Only initiator messages should be handled. */
731
if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
732
return false;
733
}
734
735
switch (reason) {
736
case MotifDnDConstants.TOP_LEVEL_ENTER :
737
return processTopLevelEnter(xclient);
738
case MotifDnDConstants.DRAG_MOTION :
739
case MotifDnDConstants.OPERATION_CHANGED :
740
return processDragMotion(xclient);
741
case MotifDnDConstants.TOP_LEVEL_LEAVE :
742
return processTopLevelLeave(xclient);
743
case MotifDnDConstants.DROP_START :
744
return processDropStart(xclient);
745
default:
746
return false;
747
}
748
}
749
750
/*
751
* Currently we don't synthesize enter/leave messages for Motif DnD
752
* protocol. See comments in XDropTargetProtocol.postProcessClientMessage.
753
*/
754
protected void sendEnterMessageToToplevel(long win,
755
XClientMessageEvent xclient) {
756
throw new Error("UNIMPLEMENTED");
757
}
758
759
protected void sendLeaveMessageToToplevel(long win,
760
XClientMessageEvent xclient) {
761
throw new Error("UNIMPLEMENTED");
762
}
763
764
public boolean forwardEventToEmbedded(long embedded, long ctxt,
765
int eventID) {
766
// UNIMPLEMENTED.
767
return false;
768
}
769
770
public boolean isXEmbedSupported() {
771
return false;
772
}
773
774
public boolean sendResponse(long ctxt, int eventID, int action) {
775
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
776
if (xclient.get_message_type() !=
777
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
778
return false;
779
}
780
781
long data = xclient.get_data();
782
byte reason = (byte)(unsafe.getByte(data) &
783
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
784
byte origin = (byte)(unsafe.getByte(data) &
785
MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
786
byte eventByteOrder = unsafe.getByte(data + 1);
787
byte response_reason = (byte)0;
788
789
/* Only initiator messages should be handled. */
790
if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
791
return false;
792
}
793
794
switch (reason) {
795
case MotifDnDConstants.TOP_LEVEL_ENTER:
796
case MotifDnDConstants.TOP_LEVEL_LEAVE:
797
/* Receiver shouldn't rely to these messages. */
798
return false;
799
case MotifDnDConstants.DRAG_MOTION:
800
switch (eventID) {
801
case MouseEvent.MOUSE_ENTERED:
802
response_reason = MotifDnDConstants.DROP_SITE_ENTER;
803
break;
804
case MouseEvent.MOUSE_DRAGGED:
805
response_reason = MotifDnDConstants.DRAG_MOTION;
806
break;
807
case MouseEvent.MOUSE_EXITED:
808
response_reason = MotifDnDConstants.DROP_SITE_LEAVE;
809
break;
810
}
811
break;
812
case MotifDnDConstants.OPERATION_CHANGED:
813
case MotifDnDConstants.DROP_START:
814
response_reason = reason;
815
break;
816
default:
817
// Unknown reason. Shouldn't get here.
818
assert false;
819
}
820
821
XClientMessageEvent msg = new XClientMessageEvent();
822
823
try {
824
msg.set_type(XConstants.ClientMessage);
825
msg.set_window(MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder));
826
msg.set_format(8);
827
msg.set_message_type(MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom());
828
829
long responseData = msg.get_data();
830
831
unsafe.putByte(responseData, (byte)(response_reason |
832
MotifDnDConstants.MOTIF_MESSAGE_FROM_RECEIVER));
833
unsafe.putByte(responseData + 1, MotifDnDConstants.getByteOrderByte());
834
835
int response_flags = 0;
836
837
if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
838
short flags = MotifDnDConstants.Swapper.getShort(data + 2,
839
eventByteOrder);
840
byte dropSiteStatus = (action == DnDConstants.ACTION_NONE) ?
841
MotifDnDConstants.MOTIF_INVALID_DROP_SITE :
842
MotifDnDConstants.MOTIF_VALID_DROP_SITE;
843
844
/* Clear action and drop site status bits. */
845
response_flags = flags &
846
~MotifDnDConstants.MOTIF_DND_ACTION_MASK &
847
~MotifDnDConstants.MOTIF_DND_STATUS_MASK;
848
/* Fill in new action and drop site status. */
849
response_flags |=
850
MotifDnDConstants.getMotifActionsForJavaActions(action) <<
851
MotifDnDConstants.MOTIF_DND_ACTION_SHIFT;
852
response_flags |=
853
dropSiteStatus << MotifDnDConstants.MOTIF_DND_STATUS_SHIFT;
854
} else {
855
response_flags = 0;
856
}
857
858
unsafe.putShort(responseData + 2, (short)response_flags);
859
860
/* Write time stamp. */
861
int time = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder);
862
unsafe.putInt(responseData + 4, time);
863
864
/* Write coordinates. */
865
if (response_reason != MotifDnDConstants.DROP_SITE_LEAVE) {
866
short x = MotifDnDConstants.Swapper.getShort(data + 8,
867
eventByteOrder);
868
short y = MotifDnDConstants.Swapper.getShort(data + 10,
869
eventByteOrder);
870
unsafe.putShort(responseData + 8, x); // x
871
unsafe.putShort(responseData + 10, y); // y
872
} else {
873
unsafe.putShort(responseData + 8, (short)0); // x
874
unsafe.putShort(responseData + 10, (short)0); // y
875
}
876
877
XToolkit.awtLock();
878
try {
879
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
880
msg.get_window(),
881
false, XConstants.NoEventMask,
882
msg.pData);
883
} finally {
884
XToolkit.awtUnlock();
885
}
886
} finally {
887
msg.dispose();
888
}
889
890
return true;
891
}
892
893
public Object getData(long ctxt, long format)
894
throws IllegalArgumentException, IOException {
895
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
896
897
if (xclient.get_message_type() !=
898
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
899
throw new IllegalArgumentException();
900
}
901
902
long data = xclient.get_data();
903
byte reason = (byte)(unsafe.getByte(data) &
904
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
905
byte origin = (byte)(unsafe.getByte(data) &
906
MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
907
byte eventByteOrder = unsafe.getByte(data + 1);
908
909
if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
910
throw new IOException("Cannot get data: corrupted context");
911
}
912
913
long selatom = 0;
914
915
switch (reason) {
916
case MotifDnDConstants.DRAG_MOTION :
917
case MotifDnDConstants.OPERATION_CHANGED :
918
selatom = sourceAtom;
919
break;
920
case MotifDnDConstants.DROP_START :
921
selatom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
922
break;
923
default:
924
throw new IOException("Cannot get data: invalid message reason");
925
}
926
927
if (selatom == 0) {
928
throw new IOException("Cannot get data: drag source property atom unavailable");
929
}
930
931
long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;
932
// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.
933
934
XAtom selectionAtom = XAtom.get(selatom);
935
936
XSelection selection = XSelection.getSelection(selectionAtom);
937
if (selection == null) {
938
selection = new XSelection(selectionAtom);
939
}
940
941
return selection.getData(format, time_stamp);
942
}
943
944
public boolean sendDropDone(long ctxt, boolean success, int dropAction) {
945
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
946
947
if (xclient.get_message_type() !=
948
MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom()) {
949
return false;
950
}
951
952
long data = xclient.get_data();
953
byte reason = (byte)(unsafe.getByte(data) &
954
MotifDnDConstants.MOTIF_MESSAGE_REASON_MASK);
955
byte origin = (byte)(unsafe.getByte(data) &
956
MotifDnDConstants.MOTIF_MESSAGE_SENDER_MASK);
957
byte eventByteOrder = unsafe.getByte(data + 1);
958
959
if (origin != MotifDnDConstants.MOTIF_MESSAGE_FROM_INITIATOR) {
960
return false;
961
}
962
963
if (reason != MotifDnDConstants.DROP_START) {
964
return false;
965
}
966
967
long time_stamp = MotifDnDConstants.Swapper.getInt(data + 4, eventByteOrder) & 0xffffffffL;
968
// with correction of (32-bit unsigned to 64-bit signed) implicit conversion.
969
970
long sel_atom = MotifDnDConstants.Swapper.getInt(data + 12, eventByteOrder);
971
972
long status_atom = 0;
973
974
if (success) {
975
status_atom = MotifDnDConstants.XA_XmTRANSFER_SUCCESS.getAtom();
976
} else {
977
status_atom = MotifDnDConstants.XA_XmTRANSFER_FAILURE.getAtom();
978
}
979
980
XToolkit.awtLock();
981
try {
982
XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
983
sel_atom,
984
status_atom,
985
MotifDnDConstants.XA_MOTIF_ATOM_0.getAtom(),
986
XWindow.getXAWTRootWindow().getWindow(),
987
time_stamp);
988
989
/*
990
* Flush the buffer to guarantee that the drop completion event is sent
991
* to the source before the method returns.
992
*/
993
XlibWrapper.XFlush(XToolkit.getDisplay());
994
} finally {
995
XToolkit.awtUnlock();
996
}
997
998
/* Trick to prevent cleanup() from posting dragExit */
999
targetXWindow = null;
1000
1001
/* Cannot do cleanup before the drop finishes as we may need
1002
source protocol version to send drop finished message. */
1003
cleanup();
1004
return true;
1005
}
1006
1007
public final long getSourceWindow() {
1008
return sourceWindow;
1009
}
1010
1011
/**
1012
* Reset the state of the object.
1013
*/
1014
public void cleanup() {
1015
// Clear the reference to this protocol.
1016
XDropTargetEventProcessor.reset();
1017
1018
if (targetXWindow != null) {
1019
notifyProtocolListener(targetXWindow, 0, 0,
1020
DnDConstants.ACTION_NONE, sourceActions,
1021
null, MouseEvent.MOUSE_EXITED);
1022
}
1023
1024
if (sourceWindow != 0) {
1025
XToolkit.awtLock();
1026
try {
1027
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
1028
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
1029
sourceWindowMask);
1030
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
1031
} finally {
1032
XToolkit.awtUnlock();
1033
}
1034
}
1035
1036
sourceWindow = 0;
1037
sourceWindowMask = 0;
1038
sourceProtocolVersion = 0;
1039
sourceActions = DnDConstants.ACTION_NONE;
1040
sourceFormats = null;
1041
sourceAtom = 0;
1042
userAction = DnDConstants.ACTION_NONE;
1043
sourceX = 0;
1044
sourceY = 0;
1045
targetXWindow = null;
1046
topLevelLeavePostponed = false;
1047
}
1048
1049
public boolean isDragOverComponent() {
1050
return targetXWindow != null;
1051
}
1052
1053
private void notifyProtocolListener(XWindow xwindow, int x, int y,
1054
int dropAction, int actions,
1055
XClientMessageEvent xclient,
1056
int eventID) {
1057
long nativeCtxt = 0;
1058
1059
// Make a copy of the passed XClientMessageEvent structure, since
1060
// the original structure can be freed before this
1061
// SunDropTargetEvent is dispatched.
1062
if (xclient != null) {
1063
int size = XClientMessageEvent.getSize();
1064
1065
nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());
1066
1067
unsafe.copyMemory(xclient.pData, nativeCtxt, size);
1068
}
1069
1070
getProtocolListener().handleDropTargetNotification(xwindow, x, y,
1071
dropAction,
1072
actions,
1073
sourceFormats,
1074
nativeCtxt,
1075
eventID);
1076
}
1077
}
1078
1079