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/XDnDDropTargetProtocol.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.util.logging.PlatformLogger;
37
38
import sun.misc.Unsafe;
39
40
/**
41
* XDropTargetProtocol implementation for XDnD protocol.
42
*
43
* @since 1.5
44
*/
45
class XDnDDropTargetProtocol extends XDropTargetProtocol {
46
private static final PlatformLogger logger =
47
PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDropTargetProtocol");
48
49
private static final Unsafe unsafe = XlibWrapper.unsafe;
50
51
private long sourceWindow = 0;
52
private long sourceWindowMask = 0;
53
private int sourceProtocolVersion = 0;
54
private int sourceActions = DnDConstants.ACTION_NONE;
55
private long[] sourceFormats = null;
56
private boolean trackSourceActions = false;
57
private int userAction = DnDConstants.ACTION_NONE;
58
private int sourceX = 0;
59
private int sourceY = 0;
60
private XWindow targetXWindow = null;
61
62
// XEmbed stuff.
63
private long prevCtxt = 0;
64
private boolean overXEmbedClient = false;
65
66
protected XDnDDropTargetProtocol(XDropTargetProtocolListener listener) {
67
super(listener);
68
}
69
70
/**
71
* Creates an instance associated with the specified listener.
72
*
73
* @throws NullPointerException if listener is <code>null</code>.
74
*/
75
static XDropTargetProtocol createInstance(XDropTargetProtocolListener listener) {
76
return new XDnDDropTargetProtocol(listener);
77
}
78
79
public String getProtocolName() {
80
return XDragAndDropProtocols.XDnD;
81
}
82
83
public void registerDropTarget(long window) {
84
assert XToolkit.isAWTLockHeldByCurrentThread();
85
86
long data = Native.allocateLongArray(1);
87
88
try {
89
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
90
91
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
92
XDnDConstants.XA_XdndAware.setAtomData(window, XAtom.XA_ATOM, data, 1);
93
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
94
95
if ((XErrorHandlerUtil.saved_error != null) &&
96
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
97
throw new XException("Cannot write XdndAware property");
98
}
99
} finally {
100
unsafe.freeMemory(data);
101
data = 0;
102
}
103
}
104
105
public void unregisterDropTarget(long window) {
106
assert XToolkit.isAWTLockHeldByCurrentThread();
107
108
XDnDConstants.XA_XdndAware.DeleteProperty(window);
109
}
110
111
public void registerEmbedderDropSite(long embedder) {
112
assert XToolkit.isAWTLockHeldByCurrentThread();
113
114
boolean overriden = false;
115
int version = 0;
116
long proxy = 0;
117
long newProxy = XDropTargetRegistry.getDnDProxyWindow();
118
int status = 0;
119
120
WindowPropertyGetter wpg1 =
121
new WindowPropertyGetter(embedder, XDnDConstants.XA_XdndAware, 0, 1,
122
false, XConstants.AnyPropertyType);
123
124
try {
125
status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
126
127
if (status == XConstants.Success &&
128
wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {
129
130
overriden = true;
131
version = (int)Native.getLong(wpg1.getData());
132
}
133
} finally {
134
wpg1.dispose();
135
}
136
137
/* XdndProxy is not supported for prior to XDnD version 4 */
138
if (overriden && version >= 4) {
139
WindowPropertyGetter wpg2 =
140
new WindowPropertyGetter(embedder, XDnDConstants.XA_XdndProxy,
141
0, 1, false, XAtom.XA_WINDOW);
142
143
try {
144
status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
145
146
if (status == XConstants.Success &&
147
wpg2.getData() != 0 &&
148
wpg2.getActualType() == XAtom.XA_WINDOW) {
149
150
proxy = Native.getLong(wpg2.getData());
151
}
152
} finally {
153
wpg2.dispose();
154
}
155
156
if (proxy != 0) {
157
WindowPropertyGetter wpg3 =
158
new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,
159
0, 1, false, XAtom.XA_WINDOW);
160
161
try {
162
status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
163
164
if (status != XConstants.Success ||
165
wpg3.getData() == 0 ||
166
wpg3.getActualType() != XAtom.XA_WINDOW ||
167
Native.getLong(wpg3.getData()) != proxy) {
168
169
proxy = 0;
170
} else {
171
WindowPropertyGetter wpg4 =
172
new WindowPropertyGetter(proxy,
173
XDnDConstants.XA_XdndAware,
174
0, 1, false,
175
XConstants.AnyPropertyType);
176
177
try {
178
status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
179
180
if (status != XConstants.Success ||
181
wpg4.getData() == 0 ||
182
wpg4.getActualType() != XAtom.XA_ATOM) {
183
184
proxy = 0;
185
}
186
} finally {
187
wpg4.dispose();
188
}
189
}
190
} finally {
191
wpg3.dispose();
192
}
193
}
194
}
195
196
if (proxy == newProxy) {
197
// Embedder already registered.
198
return;
199
}
200
201
long data = Native.allocateLongArray(1);
202
203
try {
204
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
205
206
/* The proxy window must have the XdndAware set, as XDnD protocol
207
prescribes to check the proxy window for XdndAware. */
208
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
209
XDnDConstants.XA_XdndAware.setAtomData(newProxy, XAtom.XA_ATOM,
210
data, 1);
211
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
212
213
if ((XErrorHandlerUtil.saved_error != null) &&
214
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
215
throw new XException("Cannot write XdndAware property");
216
}
217
218
Native.putLong(data, 0, newProxy);
219
220
/* The proxy window must have the XdndProxy set to point to itself.*/
221
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
222
XDnDConstants.XA_XdndProxy.setAtomData(newProxy, XAtom.XA_WINDOW,
223
data, 1);
224
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
225
226
if ((XErrorHandlerUtil.saved_error != null) &&
227
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
228
throw new XException("Cannot write XdndProxy property");
229
}
230
231
Native.putLong(data, 0, XDnDConstants.XDND_PROTOCOL_VERSION);
232
233
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
234
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
235
data, 1);
236
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
237
238
if ((XErrorHandlerUtil.saved_error != null) &&
239
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
240
throw new XException("Cannot write XdndAware property");
241
}
242
243
Native.putLong(data, 0, newProxy);
244
245
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
246
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
247
data, 1);
248
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
249
250
if ((XErrorHandlerUtil.saved_error != null) &&
251
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
252
throw new XException("Cannot write XdndProxy property");
253
}
254
} finally {
255
unsafe.freeMemory(data);
256
data = 0;
257
}
258
259
putEmbedderRegistryEntry(embedder, overriden, version, proxy);
260
}
261
262
public void unregisterEmbedderDropSite(long embedder) {
263
assert XToolkit.isAWTLockHeldByCurrentThread();
264
265
EmbedderRegistryEntry entry = getEmbedderRegistryEntry(embedder);
266
267
if (entry == null) {
268
return;
269
}
270
271
if (entry.isOverriden()) {
272
long data = Native.allocateLongArray(1);
273
274
try {
275
Native.putLong(data, 0, entry.getVersion());
276
277
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
278
XDnDConstants.XA_XdndAware.setAtomData(embedder, XAtom.XA_ATOM,
279
data, 1);
280
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
281
282
if ((XErrorHandlerUtil.saved_error != null) &&
283
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
284
throw new XException("Cannot write XdndAware property");
285
}
286
287
Native.putLong(data, 0, (int)entry.getProxy());
288
289
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
290
XDnDConstants.XA_XdndProxy.setAtomData(embedder, XAtom.XA_WINDOW,
291
data, 1);
292
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
293
294
if ((XErrorHandlerUtil.saved_error != null) &&
295
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
296
throw new XException("Cannot write XdndProxy property");
297
}
298
} finally {
299
unsafe.freeMemory(data);
300
data = 0;
301
}
302
} else {
303
XDnDConstants.XA_XdndAware.DeleteProperty(embedder);
304
XDnDConstants.XA_XdndProxy.DeleteProperty(embedder);
305
}
306
}
307
308
/*
309
* Gets and stores in the registry the embedder's XDnD drop site info
310
* from the embedded.
311
*/
312
public void registerEmbeddedDropSite(long embedded) {
313
assert XToolkit.isAWTLockHeldByCurrentThread();
314
315
boolean overriden = false;
316
int version = 0;
317
long proxy = 0;
318
long newProxy = XDropTargetRegistry.getDnDProxyWindow();
319
int status = 0;
320
321
WindowPropertyGetter wpg1 =
322
new WindowPropertyGetter(embedded, XDnDConstants.XA_XdndAware, 0, 1,
323
false, XConstants.AnyPropertyType);
324
325
try {
326
status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
327
328
if (status == XConstants.Success &&
329
wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {
330
331
overriden = true;
332
version = (int)Native.getLong(wpg1.getData());
333
}
334
} finally {
335
wpg1.dispose();
336
}
337
338
/* XdndProxy is not supported for prior to XDnD version 4 */
339
if (overriden && version >= 4) {
340
WindowPropertyGetter wpg2 =
341
new WindowPropertyGetter(embedded, XDnDConstants.XA_XdndProxy,
342
0, 1, false, XAtom.XA_WINDOW);
343
344
try {
345
status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
346
347
if (status == XConstants.Success &&
348
wpg2.getData() != 0 &&
349
wpg2.getActualType() == XAtom.XA_WINDOW) {
350
351
proxy = Native.getLong(wpg2.getData());
352
}
353
} finally {
354
wpg2.dispose();
355
}
356
357
if (proxy != 0) {
358
WindowPropertyGetter wpg3 =
359
new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,
360
0, 1, false, XAtom.XA_WINDOW);
361
362
try {
363
status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
364
365
if (status != XConstants.Success ||
366
wpg3.getData() == 0 ||
367
wpg3.getActualType() != XAtom.XA_WINDOW ||
368
Native.getLong(wpg3.getData()) != proxy) {
369
370
proxy = 0;
371
} else {
372
WindowPropertyGetter wpg4 =
373
new WindowPropertyGetter(proxy,
374
XDnDConstants.XA_XdndAware,
375
0, 1, false,
376
XConstants.AnyPropertyType);
377
378
try {
379
status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
380
381
if (status != XConstants.Success ||
382
wpg4.getData() == 0 ||
383
wpg4.getActualType() != XAtom.XA_ATOM) {
384
385
proxy = 0;
386
}
387
} finally {
388
wpg4.dispose();
389
}
390
}
391
} finally {
392
wpg3.dispose();
393
}
394
}
395
}
396
397
putEmbedderRegistryEntry(embedded, overriden, version, proxy);
398
}
399
400
public boolean isProtocolSupported(long window) {
401
assert XToolkit.isAWTLockHeldByCurrentThread();
402
403
WindowPropertyGetter wpg1 =
404
new WindowPropertyGetter(window, XDnDConstants.XA_XdndAware, 0, 1,
405
false, XConstants.AnyPropertyType);
406
407
try {
408
int status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
409
410
if (status == XConstants.Success &&
411
wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {
412
413
return true;
414
} else {
415
return false;
416
}
417
} finally {
418
wpg1.dispose();
419
}
420
}
421
422
private boolean processXdndEnter(XClientMessageEvent xclient) {
423
long source_win = 0;
424
long source_win_mask = 0;
425
int protocol_version = 0;
426
int actions = DnDConstants.ACTION_NONE;
427
boolean track = true;
428
long[] formats = null;
429
430
if (getSourceWindow() != 0) {
431
return false;
432
}
433
434
if (!(XToolkit.windowToXWindow(xclient.get_window()) instanceof XWindow)
435
&& getEmbedderRegistryEntry(xclient.get_window()) == null) {
436
return false;
437
}
438
439
if (xclient.get_message_type() != XDnDConstants.XA_XdndEnter.getAtom()){
440
return false;
441
}
442
443
protocol_version =
444
(int)((xclient.get_data(1) & XDnDConstants.XDND_PROTOCOL_MASK) >>
445
XDnDConstants.XDND_PROTOCOL_SHIFT);
446
447
/* XDnD compliance only requires supporting version 3 and up. */
448
if (protocol_version < XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {
449
return false;
450
}
451
452
/* Ignore the source if the protocol version is higher than we support. */
453
if (protocol_version > XDnDConstants.XDND_PROTOCOL_VERSION) {
454
return false;
455
}
456
457
source_win = xclient.get_data(0);
458
459
/* Extract the list of supported actions. */
460
if (protocol_version < 2) {
461
/* Prior to XDnD version 2 only COPY action was supported. */
462
actions = DnDConstants.ACTION_COPY;
463
} else {
464
WindowPropertyGetter wpg =
465
new WindowPropertyGetter(source_win,
466
XDnDConstants.XA_XdndActionList,
467
0, 0xFFFF, false,
468
XAtom.XA_ATOM);
469
try {
470
wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
471
472
if (wpg.getActualType() == XAtom.XA_ATOM &&
473
wpg.getActualFormat() == 32) {
474
long data = wpg.getData();
475
476
for (int i = 0; i < wpg.getNumberOfItems(); i++) {
477
actions |=
478
XDnDConstants.getJavaActionForXDnDAction(Native.getLong(data, i));
479
}
480
} else {
481
/*
482
* According to XDnD protocol, XdndActionList is optional.
483
* If XdndActionList is not set we try to guess which actions are
484
* supported.
485
*/
486
actions = DnDConstants.ACTION_COPY;
487
track = true;
488
}
489
} finally {
490
wpg.dispose();
491
}
492
}
493
494
/* Extract the available data types. */
495
if ((xclient.get_data(1) & XDnDConstants.XDND_DATA_TYPES_BIT) != 0) {
496
WindowPropertyGetter wpg =
497
new WindowPropertyGetter(source_win,
498
XDnDConstants.XA_XdndTypeList,
499
0, 0xFFFF, false,
500
XAtom.XA_ATOM);
501
try {
502
wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
503
504
if (wpg.getActualType() == XAtom.XA_ATOM &&
505
wpg.getActualFormat() == 32) {
506
formats = Native.toLongs(wpg.getData(),
507
wpg.getNumberOfItems());
508
} else {
509
formats = new long[0];
510
}
511
} finally {
512
wpg.dispose();
513
}
514
} else {
515
int countFormats = 0;
516
long[] formats3 = new long[3];
517
518
for (int i = 0; i < 3; i++) {
519
long j;
520
if ((j = xclient.get_data(2 + i)) != XConstants.None) {
521
formats3[countFormats++] = j;
522
}
523
}
524
525
formats = new long[countFormats];
526
527
System.arraycopy(formats3, 0, formats, 0, countFormats);
528
}
529
530
assert XToolkit.isAWTLockHeldByCurrentThread();
531
532
/*
533
* Select for StructureNotifyMask to receive DestroyNotify in case of source
534
* crash.
535
*/
536
XWindowAttributes wattr = new XWindowAttributes();
537
try {
538
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
539
int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
540
source_win, wattr.pData);
541
542
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
543
544
if ((status == 0) ||
545
((XErrorHandlerUtil.saved_error != null) &&
546
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
547
throw new XException("XGetWindowAttributes failed");
548
}
549
550
source_win_mask = wattr.get_your_event_mask();
551
} finally {
552
wattr.dispose();
553
}
554
555
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
556
XlibWrapper.XSelectInput(XToolkit.getDisplay(), source_win,
557
source_win_mask |
558
XConstants.StructureNotifyMask);
559
560
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
561
562
if ((XErrorHandlerUtil.saved_error != null) &&
563
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
564
throw new XException("XSelectInput failed");
565
}
566
567
sourceWindow = source_win;
568
sourceWindowMask = source_win_mask;
569
sourceProtocolVersion = protocol_version;
570
sourceActions = actions;
571
sourceFormats = formats;
572
trackSourceActions = track;
573
574
return true;
575
}
576
577
private boolean processXdndPosition(XClientMessageEvent xclient) {
578
long time_stamp = (int)XConstants.CurrentTime;
579
long xdnd_action = 0;
580
int java_action = DnDConstants.ACTION_NONE;
581
int x = 0;
582
int y = 0;
583
584
/* Ignore XDnD messages from all other windows. */
585
if (sourceWindow != xclient.get_data(0)) {
586
return false;
587
}
588
589
XWindow xwindow = null;
590
{
591
XBaseWindow xbasewindow = XToolkit.windowToXWindow(xclient.get_window());
592
if (xbasewindow instanceof XWindow) {
593
xwindow = (XWindow)xbasewindow;
594
}
595
}
596
597
x = (int)(xclient.get_data(2) >> 16);
598
y = (int)(xclient.get_data(2) & 0xFFFF);
599
600
if (xwindow == null) {
601
long receiver =
602
XDropTargetRegistry.getRegistry().getEmbeddedDropSite(
603
xclient.get_window(), x, y);
604
605
if (receiver != 0) {
606
XBaseWindow xbasewindow = XToolkit.windowToXWindow(receiver);
607
if (xbasewindow instanceof XWindow) {
608
xwindow = (XWindow)xbasewindow;
609
}
610
}
611
}
612
613
if (xwindow != null) {
614
/* Translate mouse position from root coordinates
615
to the target window coordinates. */
616
Point p = xwindow.toLocal(x, y);
617
x = p.x;
618
y = p.y;
619
}
620
621
/* Time stamp - new in XDnD version 1. */
622
if (sourceProtocolVersion > 0) {
623
time_stamp = xclient.get_data(3);
624
}
625
626
/* User action - new in XDnD version 2. */
627
if (sourceProtocolVersion > 1) {
628
xdnd_action = xclient.get_data(4);
629
} else {
630
/* The default action is XdndActionCopy */
631
xdnd_action = XDnDConstants.XA_XdndActionCopy.getAtom();
632
}
633
634
java_action = XDnDConstants.getJavaActionForXDnDAction(xdnd_action);
635
636
if (trackSourceActions) {
637
sourceActions |= java_action;
638
}
639
640
if (xwindow == null) {
641
if (targetXWindow != null) {
642
notifyProtocolListener(targetXWindow, x, y,
643
DnDConstants.ACTION_NONE, xclient,
644
MouseEvent.MOUSE_EXITED);
645
}
646
} else {
647
int java_event_id = 0;
648
649
if (targetXWindow == null) {
650
java_event_id = MouseEvent.MOUSE_ENTERED;
651
} else {
652
java_event_id = MouseEvent.MOUSE_DRAGGED;
653
}
654
655
notifyProtocolListener(xwindow, x, y, java_action, xclient,
656
java_event_id);
657
}
658
659
userAction = java_action;
660
sourceX = x;
661
sourceY = y;
662
targetXWindow = xwindow;
663
664
return true;
665
}
666
667
private boolean processXdndLeave(XClientMessageEvent xclient) {
668
/* Ignore XDnD messages from all other windows. */
669
if (sourceWindow != xclient.get_data(0)) {
670
return false;
671
}
672
673
cleanup();
674
675
return true;
676
}
677
678
private boolean processXdndDrop(XClientMessageEvent xclient) {
679
/* Ignore XDnD messages from all other windows. */
680
if (sourceWindow != xclient.get_data(0)) {
681
return false;
682
}
683
684
if (targetXWindow != null) {
685
notifyProtocolListener(targetXWindow, sourceX, sourceY, userAction,
686
xclient, MouseEvent.MOUSE_RELEASED);
687
}
688
689
return true;
690
}
691
692
public int getMessageType(XClientMessageEvent xclient) {
693
long messageType = xclient.get_message_type();
694
695
if (messageType == XDnDConstants.XA_XdndEnter.getAtom()) {
696
return ENTER_MESSAGE;
697
} else if (messageType == XDnDConstants.XA_XdndPosition.getAtom()) {
698
return MOTION_MESSAGE;
699
} else if (messageType == XDnDConstants.XA_XdndLeave.getAtom()) {
700
return LEAVE_MESSAGE;
701
} else if (messageType == XDnDConstants.XA_XdndDrop.getAtom()) {
702
return DROP_MESSAGE;
703
} else {
704
return UNKNOWN_MESSAGE;
705
}
706
}
707
708
protected boolean processClientMessageImpl(XClientMessageEvent xclient) {
709
long messageType = xclient.get_message_type();
710
711
if (messageType == XDnDConstants.XA_XdndEnter.getAtom()) {
712
return processXdndEnter(xclient);
713
} else if (messageType == XDnDConstants.XA_XdndPosition.getAtom()) {
714
return processXdndPosition(xclient);
715
} else if (messageType == XDnDConstants.XA_XdndLeave.getAtom()) {
716
return processXdndLeave(xclient);
717
} else if (messageType == XDnDConstants.XA_XdndDrop.getAtom()) {
718
return processXdndDrop(xclient);
719
} else {
720
return false;
721
}
722
}
723
724
protected void sendEnterMessageToToplevel(long toplevel,
725
XClientMessageEvent xclient) {
726
/* flags */
727
long data1 = sourceProtocolVersion << XDnDConstants.XDND_PROTOCOL_SHIFT;
728
if (sourceFormats != null && sourceFormats.length > 3) {
729
data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;
730
}
731
long data2 = sourceFormats.length > 0 ? sourceFormats[0] : 0;
732
long data3 = sourceFormats.length > 1 ? sourceFormats[1] : 0;
733
long data4 = sourceFormats.length > 2 ? sourceFormats[2] : 0;
734
sendEnterMessageToToplevelImpl(toplevel, xclient.get_data(0),
735
data1, data2, data3, data4);
736
737
}
738
739
private void sendEnterMessageToToplevelImpl(long toplevel,
740
long sourceWindow,
741
long data1, long data2,
742
long data3, long data4) {
743
XClientMessageEvent enter = new XClientMessageEvent();
744
try {
745
enter.set_type((int)XConstants.ClientMessage);
746
enter.set_window(toplevel);
747
enter.set_format(32);
748
enter.set_message_type(XDnDConstants.XA_XdndEnter.getAtom());
749
/* XID of the source window */
750
enter.set_data(0, sourceWindow);
751
enter.set_data(1, data1);
752
enter.set_data(2, data2);
753
enter.set_data(3, data3);
754
enter.set_data(4, data4);
755
756
forwardClientMessageToToplevel(toplevel, enter);
757
} finally {
758
enter.dispose();
759
}
760
}
761
762
protected void sendLeaveMessageToToplevel(long toplevel,
763
XClientMessageEvent xclient) {
764
sendLeaveMessageToToplevelImpl(toplevel, xclient.get_data(0));
765
}
766
767
protected void sendLeaveMessageToToplevelImpl(long toplevel,
768
long sourceWindow) {
769
XClientMessageEvent leave = new XClientMessageEvent();
770
try {
771
leave.set_type((int)XConstants.ClientMessage);
772
leave.set_window(toplevel);
773
leave.set_format(32);
774
leave.set_message_type(XDnDConstants.XA_XdndLeave.getAtom());
775
/* XID of the source window */
776
leave.set_data(0, sourceWindow);
777
/* flags */
778
leave.set_data(1, 0);
779
780
forwardClientMessageToToplevel(toplevel, leave);
781
} finally {
782
leave.dispose();
783
}
784
}
785
786
public boolean sendResponse(long ctxt, int eventID, int action) {
787
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
788
789
if (xclient.get_message_type() !=
790
XDnDConstants.XA_XdndPosition.getAtom()) {
791
792
return false;
793
}
794
795
if (eventID == MouseEvent.MOUSE_EXITED) {
796
action = DnDConstants.ACTION_NONE;
797
}
798
799
XClientMessageEvent msg = new XClientMessageEvent();
800
try {
801
msg.set_type((int)XConstants.ClientMessage);
802
msg.set_window(xclient.get_data(0));
803
msg.set_format(32);
804
msg.set_message_type(XDnDConstants.XA_XdndStatus.getAtom());
805
/* target window */
806
msg.set_data(0, xclient.get_window());
807
/* flags */
808
long flags = 0;
809
if (action != DnDConstants.ACTION_NONE) {
810
flags |= XDnDConstants.XDND_ACCEPT_DROP_FLAG;
811
}
812
msg.set_data(1, flags);
813
/* specify an empty rectangle */
814
msg.set_data(2, 0); /* x, y */
815
msg.set_data(3, 0); /* w, h */
816
/* action accepted by the target */
817
msg.set_data(4, XDnDConstants.getXDnDActionForJavaAction(action));
818
819
XToolkit.awtLock();
820
try {
821
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
822
xclient.get_data(0),
823
false, XConstants.NoEventMask,
824
msg.pData);
825
} finally {
826
XToolkit.awtUnlock();
827
}
828
} finally {
829
msg.dispose();
830
}
831
832
return true;
833
}
834
835
public Object getData(long ctxt, long format)
836
throws IllegalArgumentException, IOException {
837
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
838
long message_type = xclient.get_message_type();
839
long time_stamp = XConstants.CurrentTime;
840
841
// NOTE: we assume that the source supports at least version 1, so we
842
// can use the time stamp
843
if (message_type == XDnDConstants.XA_XdndPosition.getAtom()) {
844
// X server time is an unsigned 32-bit number!
845
time_stamp = xclient.get_data(3) & 0xFFFFFFFFL;
846
} else if (message_type == XDnDConstants.XA_XdndDrop.getAtom()) {
847
// X server time is an unsigned 32-bit number!
848
time_stamp = xclient.get_data(2) & 0xFFFFFFFFL;
849
} else {
850
throw new IllegalArgumentException();
851
}
852
853
return XDnDConstants.XDnDSelection.getData(format, time_stamp);
854
}
855
856
public boolean sendDropDone(long ctxt, boolean success, int dropAction) {
857
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
858
859
if (xclient.get_message_type() !=
860
XDnDConstants.XA_XdndDrop.getAtom()) {
861
return false;
862
}
863
864
/*
865
* The XDnD protocol recommends that the target requests the special
866
* target DELETE in case if the drop action is XdndActionMove.
867
*/
868
if (dropAction == DnDConstants.ACTION_MOVE && success) {
869
870
long time_stamp = xclient.get_data(2);
871
long xdndSelectionAtom =
872
XDnDConstants.XDnDSelection.getSelectionAtom().getAtom();
873
874
XToolkit.awtLock();
875
try {
876
XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
877
xdndSelectionAtom,
878
XAtom.get("DELETE").getAtom(),
879
XAtom.get("XAWT_SELECTION").getAtom(),
880
XWindow.getXAWTRootWindow().getWindow(),
881
time_stamp);
882
} finally {
883
XToolkit.awtUnlock();
884
}
885
}
886
887
XClientMessageEvent msg = new XClientMessageEvent();
888
try {
889
msg.set_type((int)XConstants.ClientMessage);
890
msg.set_window(xclient.get_data(0));
891
msg.set_format(32);
892
msg.set_message_type(XDnDConstants.XA_XdndFinished.getAtom());
893
msg.set_data(0, xclient.get_window()); /* target window */
894
msg.set_data(1, 0); /* flags */
895
/* specify an empty rectangle */
896
msg.set_data(2, 0);
897
if (sourceProtocolVersion >= 5) {
898
if (success) {
899
msg.set_data(1, XDnDConstants.XDND_ACCEPT_DROP_FLAG);
900
}
901
/* action performed by the target */
902
msg.set_data(2, XDnDConstants.getXDnDActionForJavaAction(dropAction));
903
}
904
msg.set_data(3, 0);
905
msg.set_data(4, 0);
906
907
XToolkit.awtLock();
908
try {
909
XlibWrapper.XSendEvent(XToolkit.getDisplay(),
910
xclient.get_data(0),
911
false, XConstants.NoEventMask,
912
msg.pData);
913
} finally {
914
XToolkit.awtUnlock();
915
}
916
} finally {
917
msg.dispose();
918
}
919
920
/*
921
* Flush the buffer to guarantee that the drop completion event is sent
922
* to the source before the method returns.
923
*/
924
XToolkit.awtLock();
925
try {
926
XlibWrapper.XFlush(XToolkit.getDisplay());
927
} finally {
928
XToolkit.awtUnlock();
929
}
930
931
/* Trick to prevent cleanup() from posting dragExit */
932
targetXWindow = null;
933
934
/* Cannot do cleanup before the drop finishes as we may need
935
source protocol version to send drop finished message. */
936
cleanup();
937
return true;
938
}
939
940
public final long getSourceWindow() {
941
return sourceWindow;
942
}
943
944
/**
945
* Reset the state of the object.
946
*/
947
public void cleanup() {
948
// Clear the reference to this protocol.
949
XDropTargetEventProcessor.reset();
950
951
if (targetXWindow != null) {
952
notifyProtocolListener(targetXWindow, 0, 0,
953
DnDConstants.ACTION_NONE, null,
954
MouseEvent.MOUSE_EXITED);
955
}
956
957
if (sourceWindow != 0) {
958
XToolkit.awtLock();
959
try {
960
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
961
XlibWrapper.XSelectInput(XToolkit.getDisplay(), sourceWindow,
962
sourceWindowMask);
963
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
964
} finally {
965
XToolkit.awtUnlock();
966
}
967
}
968
969
sourceWindow = 0;
970
sourceWindowMask = 0;
971
sourceProtocolVersion = 0;
972
sourceActions = DnDConstants.ACTION_NONE;
973
sourceFormats = null;
974
trackSourceActions = false;
975
userAction = DnDConstants.ACTION_NONE;
976
sourceX = 0;
977
sourceY = 0;
978
targetXWindow = null;
979
}
980
981
public boolean isDragOverComponent() {
982
return targetXWindow != null;
983
}
984
985
public void adjustEventForForwarding(XClientMessageEvent xclient,
986
EmbedderRegistryEntry entry) {
987
/* Adjust the event to match the XDnD protocol version. */
988
int version = entry.getVersion();
989
if (xclient.get_message_type() == XDnDConstants.XA_XdndEnter.getAtom()) {
990
int min_version = sourceProtocolVersion < version ?
991
sourceProtocolVersion : version;
992
long data1 = min_version << XDnDConstants.XDND_PROTOCOL_SHIFT;
993
if (sourceFormats != null && sourceFormats.length > 3) {
994
data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;
995
}
996
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
997
logger.finest(" "
998
+ " entryVersion=" + version
999
+ " sourceProtocolVersion=" +
1000
sourceProtocolVersion
1001
+ " sourceFormats.length=" +
1002
(sourceFormats != null ? sourceFormats.length : 0));
1003
}
1004
xclient.set_data(1, data1);
1005
}
1006
}
1007
1008
private void notifyProtocolListener(XWindow xwindow, int x, int y,
1009
int dropAction,
1010
XClientMessageEvent xclient,
1011
int eventID) {
1012
long nativeCtxt = 0;
1013
1014
// Make a copy of the passed XClientMessageEvent structure, since
1015
// the original structure can be freed before this
1016
// SunDropTargetEvent is dispatched.
1017
if (xclient != null) {
1018
int size = new XClientMessageEvent(nativeCtxt).getSize();
1019
1020
nativeCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());
1021
1022
unsafe.copyMemory(xclient.pData, nativeCtxt, size);
1023
1024
long data1 = sourceProtocolVersion << XDnDConstants.XDND_PROTOCOL_SHIFT;
1025
if (sourceFormats != null && sourceFormats.length > 3) {
1026
data1 |= XDnDConstants.XDND_DATA_TYPES_BIT;
1027
}
1028
// Append information from the latest XdndEnter event.
1029
Native.putLong(nativeCtxt + size, data1);
1030
Native.putLong(nativeCtxt + size + Native.getLongSize(),
1031
sourceFormats.length > 0 ? sourceFormats[0] : 0);
1032
Native.putLong(nativeCtxt + size + 2 * Native.getLongSize(),
1033
sourceFormats.length > 1 ? sourceFormats[1] : 0);
1034
Native.putLong(nativeCtxt + size + 3 * Native.getLongSize(),
1035
sourceFormats.length > 2 ? sourceFormats[2] : 0);
1036
}
1037
1038
getProtocolListener().handleDropTargetNotification(xwindow, x, y,
1039
dropAction,
1040
sourceActions,
1041
sourceFormats,
1042
nativeCtxt,
1043
eventID);
1044
}
1045
1046
/*
1047
* The methods/fields defined below are executed/accessed only on
1048
* the toolkit thread.
1049
* The methods/fields defined below are executed/accessed only on the event
1050
* dispatch thread.
1051
*/
1052
1053
public boolean forwardEventToEmbedded(long embedded, long ctxt,
1054
int eventID) {
1055
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1056
logger.finest(" ctxt=" + ctxt +
1057
" type=" + (ctxt != 0 ?
1058
getMessageType(new
1059
XClientMessageEvent(ctxt)) : 0) +
1060
" prevCtxt=" + prevCtxt +
1061
" prevType=" + (prevCtxt != 0 ?
1062
getMessageType(new
1063
XClientMessageEvent(prevCtxt)) : 0));
1064
}
1065
if ((ctxt == 0 ||
1066
getMessageType(new XClientMessageEvent(ctxt)) == UNKNOWN_MESSAGE) &&
1067
(prevCtxt == 0 ||
1068
getMessageType(new XClientMessageEvent(prevCtxt)) == UNKNOWN_MESSAGE)) {
1069
return false;
1070
}
1071
1072
// The size of XClientMessageEvent structure.
1073
int size = XClientMessageEvent.getSize();
1074
1075
if (ctxt != 0) {
1076
XClientMessageEvent xclient = new XClientMessageEvent(ctxt);
1077
if (!overXEmbedClient) {
1078
long data1 = Native.getLong(ctxt + size);
1079
long data2 = Native.getLong(ctxt + size + Native.getLongSize());
1080
long data3 = Native.getLong(ctxt + size + 2 * Native.getLongSize());
1081
long data4 = Native.getLong(ctxt + size + 3 * Native.getLongSize());
1082
1083
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1084
logger.finest(" 1 "
1085
+ " embedded=" + embedded
1086
+ " source=" + xclient.get_data(0)
1087
+ " data1=" + data1
1088
+ " data2=" + data2
1089
+ " data3=" + data3
1090
+ " data4=" + data4);
1091
}
1092
1093
// Copy XdndTypeList from source to proxy.
1094
if ((data1 & XDnDConstants.XDND_DATA_TYPES_BIT) != 0) {
1095
WindowPropertyGetter wpg =
1096
new WindowPropertyGetter(xclient.get_data(0),
1097
XDnDConstants.XA_XdndTypeList,
1098
0, 0xFFFF, false,
1099
XAtom.XA_ATOM);
1100
try {
1101
wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());
1102
1103
if (wpg.getActualType() == XAtom.XA_ATOM &&
1104
wpg.getActualFormat() == 32) {
1105
1106
XToolkit.awtLock();
1107
try {
1108
XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
1109
XDnDConstants.XA_XdndTypeList.setAtomData(xclient.get_window(),
1110
XAtom.XA_ATOM,
1111
wpg.getData(),
1112
wpg.getNumberOfItems());
1113
XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
1114
1115
if ((XErrorHandlerUtil.saved_error != null) &&
1116
(XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
1117
if (logger.isLoggable(PlatformLogger.Level.WARNING)) {
1118
logger.warning("Cannot set XdndTypeList on the proxy window");
1119
}
1120
}
1121
} finally {
1122
XToolkit.awtUnlock();
1123
}
1124
} else {
1125
if (logger.isLoggable(PlatformLogger.Level.WARNING)) {
1126
logger.warning("Cannot read XdndTypeList from the source window");
1127
}
1128
}
1129
} finally {
1130
wpg.dispose();
1131
}
1132
}
1133
XDragSourceContextPeer.setProxyModeSourceWindow(xclient.get_data(0));
1134
1135
sendEnterMessageToToplevelImpl(embedded, xclient.get_window(),
1136
data1, data2, data3, data4);
1137
overXEmbedClient = true;
1138
}
1139
1140
if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
1141
logger.finest(" 2 "
1142
+ " embedded=" + embedded
1143
+ " xclient=" + xclient);
1144
}
1145
1146
/* Make a copy of the original event, since we are going to modify the
1147
event while it still can be referenced from other Java events. */
1148
{
1149
XClientMessageEvent copy = new XClientMessageEvent();
1150
unsafe.copyMemory(xclient.pData, copy.pData, copy.getSize());
1151
1152
copy.set_data(0, xclient.get_window());
1153
1154
forwardClientMessageToToplevel(embedded, copy);
1155
}
1156
}
1157
1158
if (eventID == MouseEvent.MOUSE_EXITED) {
1159
if (overXEmbedClient) {
1160
if (ctxt != 0 || prevCtxt != 0) {
1161
// Last chance to send XdndLeave to the XEmbed client.
1162
XClientMessageEvent xclient = ctxt != 0 ?
1163
new XClientMessageEvent(ctxt) :
1164
new XClientMessageEvent(prevCtxt);
1165
sendLeaveMessageToToplevelImpl(embedded, xclient.get_window());
1166
}
1167
overXEmbedClient = false;
1168
// We have to clear the proxy mode source window here,
1169
// when the drag exits the XEmbedCanvasPeer.
1170
// NOTE: at this point the XEmbed client still might have some
1171
// drag notifications to process and it will send responses to
1172
// us. With the proxy mode source window cleared we won't be
1173
// able to forward these responses to the actual source. This is
1174
// not a problem if the drag operation was initiated in this
1175
// JVM. However, if it was initiated in another processes the
1176
// responses will be lost. We bear with it for now, as it seems
1177
// there is no other reliable point to clear.
1178
XDragSourceContextPeer.setProxyModeSourceWindow(0);
1179
}
1180
}
1181
1182
if (eventID == MouseEvent.MOUSE_RELEASED) {
1183
overXEmbedClient = false;
1184
cleanup();
1185
}
1186
1187
if (prevCtxt != 0) {
1188
unsafe.freeMemory(prevCtxt);
1189
prevCtxt = 0;
1190
}
1191
1192
if (ctxt != 0 && overXEmbedClient) {
1193
prevCtxt = unsafe.allocateMemory(size + 4 * Native.getLongSize());
1194
1195
unsafe.copyMemory(ctxt, prevCtxt, size + 4 * Native.getLongSize());
1196
}
1197
1198
return true;
1199
}
1200
1201
public boolean isXEmbedSupported() {
1202
return true;
1203
}
1204
}
1205
1206