Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGDNDManager.cxx
Go to the documentation of this file.
1// @(#)root/gui:$Id$
2// Author: Bertrand Bellenot 19/04/07
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TGFrame.h"
13#include "TTimer.h"
14#include "TGDNDManager.h"
15#include "TRootCanvas.h"
16#include "TVirtualX.h"
17
18
19#define ROOTDND_PROTOCOL_VERSION 4
20#define XA_ATOM ((Atom_t) 4)
21#define XA_WINDOW ((Atom_t) 33)
22
26
34
40
44
47
49
50// TODO:
51// - add an TGFrame::HandleDNDStatus event handler?
52// - implement INCR protocol
53// - cache several requests?
54
56
58
59
60/** \class TGDragWindow
61 \ingroup guiwidgets
62
63Window used as drag icon during drag and drop operations.
64
65*/
66
67
68
69////////////////////////////////////////////////////////////////////////////////
70/// TGDragWindow constructor.
71
73 UInt_t options, Pixel_t back) :
74 TGFrame(p, 32, 32, options, back)
75{
76 if (fgDefaultCursor == kNone) {
77 fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
78 }
79
80 fPic = pic;
81 fMask = mask;
82
84
86 wattr.fSaveUnder = kTRUE;
87 wattr.fOverrideRedirect = kTRUE;
88
89 gVirtualX->ChangeWindowAttributes(fId, &wattr);
90
91 int x, y;
92
93 gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
94
96 wattr.fOverrideRedirect = kTRUE;
97
98 // This input window is used to make the dragging smoother when using
99 // highly complicated shaped windows (like labels and semitransparent
100 // icons), for some obscure reason most of the motion events get lost
101 // while the pointer is over the shaped window.
102
103 //fInput = gVirtualX->CreateWindow(fParent->GetId(), 0, 0, fWidth,
104 // fHeight, 0, 0, 0, 0, &wattr, 0);
105 fInput = fId;
106
108
109 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
110
111 gVirtualX->SetCursor(fId, fgDefaultCursor);
112}
113
114////////////////////////////////////////////////////////////////////////////////
115/// TGDragWindow destructor.
116
118{
119 //gVirtualX->DestroyWindow(fInput);
120}
121
122////////////////////////////////////////////////////////////////////////////////
123/// Map TGDragWindow.
124
126{
128 //gVirtualX->MapWindow(fInput);
129}
130
131////////////////////////////////////////////////////////////////////////////////
132/// Unmap TGDragWindow.
133
135{
137 //gVirtualX->UnmapWindow(fInput);
138}
139
140////////////////////////////////////////////////////////////////////////////////
141/// Raise TGDragWindow.
142
144{
146 //gVirtualX->RaiseWindow(fInput);
147}
148
149////////////////////////////////////////////////////////////////////////////////
150/// Lower TGDragWindow.
151
153{
154 //gVirtualX->LowerWindow(fInput);
156}
157
158////////////////////////////////////////////////////////////////////////////////
159/// Map and Raise TGDragWindow.
160
162{
164 //gVirtualX->MapRaised(fInput);
165}
166
167////////////////////////////////////////////////////////////////////////////////
168/// Layout TGDragWindow.
169
171{
172 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Redraw TGDragWindow.
177
179{
180 gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
181}
182
183//_____________________________________________________________________________
184//
185// TGDNDManager
186//
187// Central Drag and Drop manager for ROOT.
188//_____________________________________________________________________________
189
190
191////////////////////////////////////////////////////////////////////////////////
192/// TGDNDManager constructor.
193
195{
196 if (gDNDManager)
197 // coverity[uninit_member]: already done
198 return;
199
200 fMain = toplevel;
203 //fTypelist = typelist;
204 fTypelist = new Atom_t[3];
205 fTypelist[0] = gVirtualX->InternAtom("application/root", kFALSE);
206 fTypelist[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
207 fTypelist[2] = 0;
208
209 if (!fgInit) {
210 InitAtoms();
211 fgInit = kTRUE;
212 }
213
214 //Reset();
215 fDropTimeout = 0;
216
217 fSource = kNone;
218 fTarget = kNone;
221 fDropAccepted = kFALSE; // this would become obsoleted by _acceptedAction
222 fAcceptedAction = kNone; // target's accepted action
223 fLocalAction = kNone; // our last specified action when we act as source
225 fDragWin = 0;
226 fLocalSource = 0;
227 fLocalTarget = 0;
228 fPic = fMask = kNone;
229 fDraggerTypes = 0;
231 fHotx = fHoty = 0;
232
234
235 fDNDNoDropCursor = gVirtualX->CreateCursor(kNoDrop); // kNoDrop
236
237 // set the aware prop
238
240 gDNDManager = this;
241}
242
243////////////////////////////////////////////////////////////////////////////////
244/// TGDNDManager destructor.
245
247{
248 // remove the proxy prop if we own it
249 if (fProxyOurs)
251
252 // remove the aware prop ant the types list, if any
253 if (fMain) {
254 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDAware);
255 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDTypeList);
256 }
257 if (fDropTimeout) delete fDropTimeout;
258
259 // delete the drag pixmap, if any
260 if (fDragWin) {
262 fDragWin = 0;
263 }
264 if (fPic != kNone) gVirtualX->DeletePixmap(fPic);
265 if (fMask != kNone) gVirtualX->DeletePixmap(fMask);
266
267 if (fDraggerTypes) delete[] fDraggerTypes;
268 if (fTypelist) delete[] fTypelist;
269}
270
290
291////////////////////////////////////////////////////////////////////////////////
292/// Initialize drag and drop atoms.
293
295{
296 // awareness
297 fgDNDAware = gVirtualX->InternAtom("XdndAware", kFALSE);
298
299 // selection
300 fgDNDSelection = gVirtualX->InternAtom("XdndSelection", kFALSE);
301
302 // proxy window
303 fgDNDProxy = gVirtualX->InternAtom("XdndProxy", kFALSE);
304
305 // messages
306 fgDNDEnter = gVirtualX->InternAtom("XdndEnter", kFALSE);
307 fgDNDLeave = gVirtualX->InternAtom("XdndLeave", kFALSE);
308 fgDNDPosition = gVirtualX->InternAtom("XdndPosition", kFALSE);
309 fgDNDStatus = gVirtualX->InternAtom("XdndStatus", kFALSE);
310 fgDNDDrop = gVirtualX->InternAtom("XdndDrop", kFALSE);
311 fgDNDFinished = gVirtualX->InternAtom("XdndFinished", kFALSE);
312
313 // actions
314 fgDNDActionCopy = gVirtualX->InternAtom("XdndActionCopy", kFALSE);
315 fgDNDActionMove = gVirtualX->InternAtom("XdndActionMove", kFALSE);
316 fgDNDActionLink = gVirtualX->InternAtom("XdndActionLink", kFALSE);
317 fgDNDActionAsk = gVirtualX->InternAtom("XdndActionAsk", kFALSE);
318 fgDNDActionPrivate = gVirtualX->InternAtom("XdndActionPrivate", kFALSE);
319
320 // types list
321 fgDNDTypeList = gVirtualX->InternAtom("XdndTypeList", kFALSE);
322 fgDNDActionList = gVirtualX->InternAtom("XdndActionList", kFALSE);
323 fgDNDActionDescrip = gVirtualX->InternAtom("XdndActionDescription", kFALSE);
324
325 // misc
326 fgXAWMState = gVirtualX->InternAtom("WM_STATE", kFALSE);
327 fgXCDNDData = gVirtualX->InternAtom("_XC_DND_DATA", kFALSE);
328}
329
330static int ArrayLength(Atom_t *a)
331{
332 // Returns length of array a.
333
334 int n;
335
336 for (n = 0; a[n]; n++) { }
337 return n;
338}
339
340////////////////////////////////////////////////////////////////////////////////
341/// Check if window win is DND aware.
342
347
348////////////////////////////////////////////////////////////////////////////////
349/// Search for DND aware window at position x,y.
350
352{
353 if (maxd <= 0) return kNone;
354
355 if (fDragWin && fDragWin->HasWindow(root)) return kNone;
356
357 return gVirtualX->FindRWindow(root, fDragWin ? fDragWin->GetId() : 0,
359 x, y, maxd);
360}
361
362
363////////////////////////////////////////////////////////////////////////////////
364/// Get root window proxy.
365
367{
369 Int_t format = 32;
370 ULong_t count, remaining;
371 unsigned char *data = 0;
373
374 // search for XdndProxy property on the root window...
375
376 // XSync(_dpy, kFALSE); // get to known state...
377 gVirtualX->UpdateWindow(0);
378
379 //oldhandler = XSetErrorHandler(TGDNDManager::CatchXError);
380 //target_error = kFALSE;
381
382 gVirtualX->GetProperty(gVirtualX->GetDefaultRootWindow(),
384 &actual, &format, &count, &remaining, &data);
385
386 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
387
388 // found the XdndProxy property, now check for the proxy window...
389 win = *((Window_t *) data);
390 delete[] data;
391 data = 0;
392
393 gVirtualX->GetProperty(win, fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
394 &actual, &format, &count, &remaining, &data);
395
396 // XSync(_dpy, kFALSE); // force the error...
397 gVirtualX->UpdateWindow(0);
398
399 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
400 if (*((Window_t *) data) == win) {
401
402 // proxy window exists and is correct
403 proxy = win;
404 }
405 }
406 }
407 if (data) delete[] data;
408 //oldhandler = XSetErrorHandler(oldhandler);
409 return proxy;
410}
411
412////////////////////////////////////////////////////////////////////////////////
413/// Handle DND related client messages.
414
416{
417 if (event->fHandle == fgDNDEnter) {
418 HandleDNDEnter((Window_t) event->fUser[0], event->fUser[1],
419 (Atom_t *) &event->fUser[2]);
420
421 } else if (event->fHandle == fgDNDLeave) {
422 HandleDNDLeave((Window_t) event->fUser[0]);
423
424 } else if (event->fHandle == fgDNDPosition) {
425 Atom_t action = (Atom_t)event->fUser[4] ? event->fUser[4] : 1;
427 (Int_t)(event->fUser[2] >> 16) & 0xFFFF, // x_root
428 (Int_t)(event->fUser[2] & 0xFFFF), // y_root
429 (Atom_t)action, // action
430 (Time_t)event->fUser[3]); // timestamp
431
432 } else if (event->fHandle == fgDNDStatus) {
434 skip.fX = (event->fUser[2] >> 16) & 0xFFFF;
435 skip.fY = (event->fUser[2] & 0xFFFF);
436 skip.fWidth = (event->fUser[3] >> 16) & 0xFFFF;
437 skip.fHeight = (event->fUser[3] & 0xFFFF);
438
439 HandleDNDStatus((Window_t) event->fUser[0],
440 (int) (event->fUser[1] & 0x1),
441 skip, (Atom_t) event->fUser[4]);
442
443 } else if (event->fHandle == fgDNDDrop) {
444 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
445
446 } else if (event->fHandle == fgDNDFinished) {
447 HandleDNDFinished((Window_t) event->fUser[0]);
448
449 } else {
450 return kFALSE; // not for us...
451 }
452 return kTRUE;
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Handle Drop timeout.
457
459{
460 if (t == fDropTimeout) {
461 // The drop operation timed out without receiving
462 // status confirmation from the target. Send a
463 // leave message instead (and notify the user or widget).
464 delete fDropTimeout;
465 fDropTimeout = 0;
466
469
471 return kTRUE;
472 }
473 return kFALSE;
474}
475
476////////////////////////////////////////////////////////////////////////////////
477/// Send DND enter message to target window.
478
480{
481 Int_t i, n;
482 Event_t event;
483
484 event.fType = kClientMessage;
485 event.fWindow = target;
486 event.fHandle = fgDNDEnter;
487 event.fFormat = 32;
488
489 event.fUser[0] = fMain->GetId(); // from;
490
492
493 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
494
495 // set the first 1-3 data types
496
497 for (i = 0; i < 3; ++i)
498 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
499
500 if (fLocalSource) {
501 TDNDData *dnddata = 0;
503
504 // get the data type from the drag source widget
505 if (fLocalSource)
507 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
508 event.fUser[2] = dataType;
509 event.fUser[3] = kNone;
510 event.fUser[4] = kNone;
511 }
512
513 gVirtualX->SendEvent(target, &event);
514}
515
516////////////////////////////////////////////////////////////////////////////////
517/// Send DND leave message to target window.
518
520{
521 Event_t event;
522
523 event.fType = kClientMessage;
524 event.fWindow = target;
525 event.fHandle = fgDNDLeave;
526 event.fFormat = 32;
527
528 event.fUser[0] = fMain->GetId(); // from;
529 event.fUser[1] = 0L;
530
531 event.fUser[2] = 0L;
532 event.fUser[3] = 0L;
533 event.fUser[4] = 0L;
534
535 gVirtualX->SendEvent(target, &event);
536}
537
538////////////////////////////////////////////////////////////////////////////////
539/// Send DND position message to target window.
540
543{
544 Event_t event;
545
546 event.fType = kClientMessage;
547 event.fWindow = target;
548 event.fHandle = fgDNDPosition;
549 event.fFormat = 32;
550
551 event.fUser[0] = fMain->GetId(); // from;
552 event.fUser[1] = 0L;
553
554 event.fUser[2] = (x << 16) | y; // root coordinates
555 event.fUser[3] = timestamp; // timestamp for retrieving data
556 event.fUser[4] = action; // requested action
557
558 gVirtualX->SendEvent(target, &event);
559}
560
561////////////////////////////////////////////////////////////////////////////////
562/// Send DND status message to source window.
563
565{
566 Event_t event;
567
568 event.fType = kClientMessage;
569 event.fWindow = source;
570 event.fHandle = fgDNDStatus;
571 event.fFormat = 32;
572
573 event.fUser[0] = fMain->GetId(); // from;
574 event.fUser[1] = (action == kNone) ? 0L : 1L;
575
576 event.fUser[2] = 0L; // empty rectangle
577 event.fUser[3] = 0L;
578 event.fUser[4] = action; // accepted action
579
580 gVirtualX->SendEvent(source, &event);
581}
582
583////////////////////////////////////////////////////////////////////////////////
584/// Send DND drop message to target window.
585
587{
588 Event_t event;
589
590 event.fType = kClientMessage;
591 event.fWindow = target;
592 event.fHandle = fgDNDDrop;
593 event.fFormat = 32;
594
595 event.fUser[0] = fMain->GetId(); // from;
596 event.fUser[1] = 0L; // reserved
597 event.fUser[2] = 0L; //CurrentTime; // timestamp
598 event.fUser[3] = 0L;
599 event.fUser[4] = 0L;
600
601 gVirtualX->SendEvent(target, &event);
602}
603
604////////////////////////////////////////////////////////////////////////////////
605/// Send DND finished message to source window.
606
608{
609 Event_t event;
610
611 event.fType = kClientMessage;
612 event.fWindow = source;
613 event.fHandle = fgDNDFinished;
614 event.fFormat = 32;
615
616 event.fUser[0] = fMain->GetId(); // from;
617 event.fUser[1] = 0L; // reserved
618 event.fUser[2] = 0L;
619 event.fUser[3] = 0L;
620 event.fUser[4] = 0L;
621
622 gVirtualX->SendEvent(source, &event);
623}
624
625////////////////////////////////////////////////////////////////////////////////
626/// Handle DND enter event.
627
629{
630 fSource = src;
631
632 if (fDraggerTypes) delete[] fDraggerTypes;
633
634 if (vers & 1) { // more than 3 data types?
635 Atom_t type, *a;
636 Int_t format = 32;
637 ULong_t i, count, remaining;
638 unsigned char *data = 0;
639
640 gVirtualX->GetProperty(src, fgDNDTypeList,
641 0, 0x8000000L, kFALSE, XA_ATOM,
642 &type, &format, &count, &remaining, &data);
643
644 if (type != XA_ATOM || format != 32 || !data) {
645 count = 0;
646 }
647
648 fDraggerTypes = new Atom_t[count+4];
649
650 a = (Atom_t *) data;
651 for (i = 0; i < count; i++)
652 fDraggerTypes[i] = a[i];
653
654 fDraggerTypes[i] = kNone;
655
656 if (data) delete[] data;
657
658 } else {
659 fDraggerTypes = new Atom_t[4];
660
661 fDraggerTypes[0] = dataTypes[0];
662 fDraggerTypes[1] = dataTypes[1];
663 fDraggerTypes[2] = dataTypes[2];
664
665 fDraggerTypes[3] = kNone;
666 }
667
668 // the following is not strictly necessary, unless the previous
669 // dragging application crashed without sending XdndLeave
671 fLocalTarget = 0;
672
673 return kTRUE;
674}
675
676////////////////////////////////////////////////////////////////////////////////
677/// Handle DND leave event.
678
680{
681 fSource = kNone;
683 fLocalTarget = 0;
684
685 if (fDraggerTypes) delete[] fDraggerTypes;
686 fDraggerTypes = 0;
687
688 return kTRUE;
689}
690
691////////////////////////////////////////////////////////////////////////////////
692/// Handle DND position event.
693
695 Atom_t action, Time_t /*timestamp*/)
696{
697 Int_t x = 0, y = 0;
699 TGFrame *f = 0, *main = 0;
700 TGWindow *w = 0;
701 Window_t wtarget = 0;
702
703 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
704
705 if (wtarget) {
706 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
708 w = gClient->GetWindowById(wtarget);
709 if (w)
710 f = dynamic_cast<TGFrame *>(w);
711 }
712
713 if (f != fLocalTarget) {
715 fLocalTarget = f;
716 if (fLocalTarget) {
718 main->RaiseWindow();
719 if (fMain == 0)
720 fMain = main;
722 }
723 }
724 // query the target widget to determine whether it accepts the
725 // required action
726 if (fLocalTarget) {
727 action = (fDropType == kNone) ? kNone :
729 } else if (fProxyOurs) {
731 } else {
732 action = kNone;
733 }
735 return kTRUE;
736}
737
738////////////////////////////////////////////////////////////////////////////////
739/// Handle DND status event.
740
742 Rectangle_t /*area*/, Atom_t action)
743{
744 if (target) {
746 if (accepted) {
749 if (fDragWin)
750 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
752 } else {
755 if (fDragWin)
756 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
759 }
760 if (fDropTimeout) { // were we waiting for this to do the drop?
761 delete fDropTimeout;
762 fDropTimeout = 0;
764 }
765 }
766 return kTRUE;
767}
768
769////////////////////////////////////////////////////////////////////////////////
770/// Handle DND drop event.
771
773{
774 // to get the data, we must call XConvertSelection with
775 // the timestamp in XdndDrop, wait for SelectionNotify
776 // to arrive to retrieve the data, and when we are finished,
777 // send a XdndFinished message to the source.
778
779 if (fMain && fDropType != kNone) {
780 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
781 8, (unsigned char *) 0, 0);
782
783 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
785 }
786
787 fSource = source;
789
790 return kTRUE;
791}
792
793////////////////////////////////////////////////////////////////////////////////
794/// Handle DND finished event.
795
801
802////////////////////////////////////////////////////////////////////////////////
803/// Handle selection request event.
804
806{
807 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
808 TDNDData *dnddata = nullptr;
809 char *data;
810 int len;
811
812 // get the data from the drag source widget
813 if (fLocalSource)
814 dnddata = fLocalSource->GetDNDData(event->fUser[2]);
815
816 data = dnddata ? (char *) dnddata->fData : (char *) "";
817 len = dnddata ? dnddata->fDataLength : 0;
818
819 if ((Atom_t)event->fUser[3] == kNone) {
820 //printf("warning: kNone property specified in SelectionRequest\n");
821 event->fUser[3] = fgXCDNDData;
822 }
823
824 gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
825 event->fUser[2], 8,
826 (unsigned char *) data, len);
827#ifndef R__WIN32
829 xevent.fType = kSelectionNotify;
830 xevent.fTime = event->fTime;
831 xevent.fUser[0] = event->fUser[0]; // requestor
832 xevent.fUser[1] = event->fUser[1]; // selection
833 xevent.fUser[2] = event->fUser[2]; // target;
834 xevent.fUser[3] = event->fUser[3]; // property;
835 gVirtualX->SendEvent(event->fUser[0], &xevent);
836#endif
837 return kTRUE;
838 } else {
839 return kFALSE; // not for us...
840 }
841}
842
843////////////////////////////////////////////////////////////////////////////////
844/// Handle selection event.
845
847{
848 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
850 Int_t format = 8;
851 ULong_t count, remaining;
852 unsigned char *data = 0;
853
854
855 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
856 0, 0x8000000L, kTRUE, event->fUser[2],
857 &actual, &format, &count, &remaining, &data);
858
859 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
860 if (data) delete[] data;
861
862 return kFALSE;
863 }
864
866
867 // send the data to the target widget
868
869 if (fLocalTarget) {
872 if (fDraggerTypes) delete[] fDraggerTypes;
873 fDraggerTypes = 0;
874 }
875
876 fSource = kNone;
878
879// delete[] data;
880
881 return kTRUE;
882
883 } else {
884 return kFALSE; // not for us...
885 }
886}
887
888////////////////////////////////////////////////////////////////////////////////
889/// Set drag window pixmaps and hotpoint.
890
892 int hot_x, int hot_y)
893{
894 fPic = pic;
895 fMask = mask;
896 fHotx = hot_x;
897 fHoty = hot_y;
898}
899
900////////////////////////////////////////////////////////////////////////////////
901/// Start dragging.
902
905{
906 if (fDragging) return kTRUE;
907
909
910 if ((TGWindow *)fMain != src->GetMainFrame()) {
911 fMain = (TGFrame *)src->GetMainFrame();
912 }
913
914 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
915 // hmmm... failed to acquire ownership of XdndSelection!
916 return kFALSE;
917 }
918
919 if (grabWin == kNone) grabWin = fMain->GetId();
920
922
923 fLocalTarget = 0;
925 fTarget = kNone;
928 if (fDropTimeout) delete fDropTimeout;
929 fDropTimeout = 0;
933
934 if (!fDragWin && fPic != kNone && fMask != kNone) {
935 fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
939 }
940 return kTRUE;
941}
942
943////////////////////////////////////////////////////////////////////////////////
944/// Drop.
945
947{
948 if (!fDragging) return kFALSE;
949
950 if (fTargetIsDNDAware) {
951 if (fDropAccepted) {
952 if (fStatusPending) {
953 if (fDropTimeout) delete fDropTimeout;
954 fDropTimeout = new TTimer(this, 5000);
955 } else {
957 }
958 } else {
961 }
962 }
963 EndDrag();
964 return kTRUE;
965}
966
967////////////////////////////////////////////////////////////////////////////////
968/// End dragging.
969
971{
972 if (!fDragging) return kFALSE;
973
974 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
975
976 if (fSource)
978 if (fLocalSource)
980
982 if (fDragWin) {
984 fDragWin = 0;
985 }
986 return kTRUE;
987}
988
989////////////////////////////////////////////////////////////////////////////////
990/// Process drag event.
991
993{
994 if (!fDragging) return kFALSE;
995
996 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
997 x_root, y_root, 15);
998
999 if (newTarget == kNone) {
1000 Window_t t = GetRootProxy();
1001 if (t != kNone) newTarget = t;
1002 }
1003
1004 if (fTarget != newTarget) {
1005
1007
1013
1015
1016 if (fDragWin)
1017 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
1019 }
1020
1023
1024 // this is to avoid sending XdndPosition messages over and over
1025 // if the target is not responding
1027 }
1028
1029 if (fDragWin) {
1031 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
1032 }
1033 return kTRUE;
1034}
1035
1036////////////////////////////////////////////////////////////////////////////////
1037/// Set root window proxy.
1038
1040{
1042 int result = kFALSE;
1043
1044 if (GetRootProxy() == kNone) {
1045 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
1046 fgDNDProxy, XA_WINDOW, 32,
1047 (unsigned char *) &mainw, 1);
1048 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
1049 (unsigned char *) &mainw, 1);
1050
1051 fProxyOurs = kTRUE;
1052 result = kTRUE;
1053 }
1054 // XSync(_dpy, kFALSE);
1055 gVirtualX->UpdateWindow(0);
1056 return result;
1057}
1058
1059////////////////////////////////////////////////////////////////////////////////
1060/// Remove root window proxy.
1061
1063{
1064 if (!fProxyOurs) return kFALSE;
1065
1066 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
1067 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
1068 // the following is to ensure that the properties
1069 // (specially the one on the root window) are deleted
1070 // in case the application is exiting...
1071
1072 // XSync(_dpy, kFALSE);
1073 gVirtualX->UpdateWindow(0);
1074
1076
1077 return kTRUE;
1078}
Handle_t Atom_t
WM token.
Definition GuiTypes.h:37
@ kSelectionNotify
Definition GuiTypes.h:63
@ kClientMessage
Definition GuiTypes.h:63
const Mask_t kWAOverrideRedirect
Definition GuiTypes.h:149
@ kTopLeft
Definition GuiTypes.h:372
@ kNoDrop
Definition GuiTypes.h:375
Handle_t Pixmap_t
Pixmap handle.
Definition GuiTypes.h:30
const Mask_t kButtonMotionMask
Definition GuiTypes.h:164
const Mask_t kButtonPressMask
Definition GuiTypes.h:161
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
const Mask_t kWASaveUnder
Definition GuiTypes.h:150
ULong_t Time_t
Event time.
Definition GuiTypes.h:42
Handle_t Cursor_t
Cursor handle.
Definition GuiTypes.h:34
const Handle_t kNone
Definition GuiTypes.h:88
const Mask_t kButtonReleaseMask
Definition GuiTypes.h:162
ULong_t Pixel_t
Pixel value.
Definition GuiTypes.h:40
int main()
Definition Prototype.cxx:12
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:68
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define gClient
Definition TGClient.h:157
TGDNDManager * gDNDManager
#define ROOTDND_PROTOCOL_VERSION
static int ArrayLength(Atom_t *a)
R__EXTERN TGDNDManager * gDNDManager
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t mask
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t child
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t win
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t Atom_t typelist
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
#define gVirtualX
Definition TVirtualX.h:337
Drag and drop data container.
static Atom_t fgDNDAware
static Atom_t fgDNDVersion
Bool_t HandleDNDEnter(Window_t src, long vers, Atom_t dataTypes[3])
Handle DND enter event.
static Atom_t fgDNDActionPrivate
Window_t fSource
static Atom_t fgDNDActionAsk
static Atom_t GetDNDDrop()
static Atom_t GetDNDActionAsk()
TGFrame * fMain
pointer on TGMainFrame
static Atom_t fgDNDActionMove
Pixmap_t fMask
pixmap used for the drag window
Bool_t HandleSelectionRequest(Event_t *event)
Handle selection request event.
static Atom_t fgDNDActionLink
Int_t fHoty
hot point coordinates
Bool_t HandleClientMessage(Event_t *event)
Handle DND related client messages.
TTimer * fDropTimeout
drop timeout
static Atom_t fgDNDActionDescrip
void SendDNDEnter(Window_t target)
Send DND enter message to target window.
static Atom_t fgDNDSelection
Bool_t fTargetIsDNDAware
kTRUE if target is DND aware
Bool_t fStatusPending
kTRUE if status is pending
TGDNDManager(const TGDNDManager &)=delete
void InitAtoms()
Initialize drag and drop atoms.
static Atom_t fgDNDFinished
Atom_t fDropType
drop type
static Atom_t fgDNDDrop
static Atom_t GetXCDNDData()
static Atom_t GetDNDVersion()
Bool_t fProxyOurs
kTRUE if root proxy is ours
static Atom_t GetDNDActionLink()
static Atom_t fgDNDEnter
Bool_t HandleDNDDrop(Window_t src, Time_t timestamp)
Handle DND drop event.
static Atom_t GetDNDStatus()
Atom_t * fDraggerTypes
lists of DND types
static Atom_t fgXCDNDData
Bool_t HandleDNDFinished(Window_t target)
Handle DND finished event.
static Atom_t fgDNDPosition
static Atom_t fgDNDLeave
Bool_t HandleSelection(Event_t *event)
Handle selection event.
Atom_t fLocalAction
accepted and local actions
TGFrame * fLocalSource
static Atom_t GetDNDTypeList()
static Bool_t fgInit
~TGDNDManager() override
TGDNDManager destructor.
Window_t GetRootProxy()
Get root window proxy.
Bool_t HandleDNDStatus(Window_t from, int accepted, Rectangle_t skip, Atom_t action)
Handle DND status event.
static Atom_t fgDNDActionCopy
static Atom_t GetDNDProxy()
static Atom_t fgDNDProxy
static Atom_t GetDNDActionDescrip()
Bool_t StartDrag(TGFrame *src, Int_t x_root, Int_t y_root, Window_t grabWin=kNone)
Start dragging.
Bool_t fUseVersion
kTRUE if DND version is used
void SendDNDStatus(Window_t target, Atom_t action)
Send DND status message to source window.
Bool_t IsDNDAware(Window_t win, Atom_t *typelist=nullptr)
Check if window win is DND aware.
Bool_t fDragging
kTRUE while dragging
static Atom_t GetDNDAware()
void SetDragPixmap(Pixmap_t pic, Pixmap_t mask, Int_t hot_x, Int_t hot_y)
Set drag window pixmaps and hotpoint.
static Atom_t GetDNDFinished()
static Atom_t GetDNDSelection()
static Atom_t fgDNDActionList
UInt_t fGrabEventMask
pointer grab event mask
Bool_t fDropAccepted
kTRUE if drop accepted
static Atom_t GetDNDActionList()
Window_t FindWindow(Window_t root, Int_t x, Int_t y, Int_t maxd)
Search for DND aware window at position x,y.
static Atom_t fgDNDTypeList
Atom_t fVersion
not really an Atom, but a long
Bool_t RemoveRootProxy()
Remove root window proxy.
static Atom_t GetDNDEnter()
Bool_t HandleDNDPosition(Window_t src, int x_root, int y_root, Atom_t action, Time_t timestamp)
Handle DND position event.
static Atom_t fgXAWMState
Pixmap_t fPic
void SendDNDPosition(Window_t target, int x, int y, Atom_t action, Time_t timestamp)
Send DND position message to target window.
void SendDNDFinished(Window_t src)
Send DND finished message to source window.
Cursor_t fDNDNoDropCursor
no drop cursor type
Bool_t Drag(Int_t x_root, Int_t y_root, Atom_t action, Time_t timestamp)
Process drag event.
TGFrame * fLocalTarget
local source and target
void SendDNDDrop(Window_t target)
Send DND drop message to target window.
static Atom_t GetDNDPosition()
static Atom_t GetDNDActionPrivate()
static Atom_t fgDNDStatus
Window_t fTarget
source and target windows
Bool_t HandleDNDLeave(Window_t src)
Handle DND leave event.
Atom_t fAcceptedAction
void SendDNDLeave(Window_t target)
Send DND leave message to target window.
TGDragWindow * fDragWin
drag window
Atom_t * fTypelist
Bool_t Drop()
Drop.
Bool_t SetRootProxy()
Set root window proxy.
static Atom_t GetDNDActionCopy()
Bool_t HandleTimer(TTimer *t) override
Handle Drop timeout.
Bool_t EndDrag()
End dragging.
static Atom_t GetDNDActionMove()
static Atom_t GetDNDLeave()
Window used as drag icon during drag and drop operations.
void MapWindow() override
Map TGDragWindow.
TGDimension GetDefaultSize() const override
std::cout << fWidth << "x" << fHeight << std::endl;
Bool_t HasWindow(Window_t w) const
void LowerWindow() override
Lower TGDragWindow.
TGDragWindow(const TGWindow *p, Pixmap_t pic, Pixmap_t mask, UInt_t options=kChildFrame, Pixel_t back=GetWhitePixel())
TGDragWindow constructor.
~TGDragWindow() override
TGDragWindow destructor.
void UnmapWindow() override
Unmap TGDragWindow.
void DoRedraw() override
Redraw TGDragWindow.
Window_t GetInputId() const
void RaiseWindow() override
Raise TGDragWindow.
void Layout() override
Layout TGDragWindow.
Window_t fInput
Input Window.
void MapRaised() override
Map and Raise TGDragWindow.
Pixmap_t fMask
Pixmaps used as Window shape.
Pixmap_t fPic
UInt_t fPh
Hot point coordinates (x and y)
static Cursor_t fgDefaultCursor
A subclasses of TGWindow, and is used as base class for some simple widgets (buttons,...
Definition TGFrame.h:80
virtual Atom_t HandleDNDEnter(Atom_t *)
Definition TGFrame.h:281
void Resize(UInt_t w=0, UInt_t h=0) override
Resize the frame.
Definition TGFrame.cxx:597
virtual Atom_t HandleDNDPosition(Int_t, Int_t, Atom_t, Int_t, Int_t)
Definition TGFrame.h:279
virtual Bool_t HandleDNDDrop(TDNDData *)
Definition TGFrame.h:278
UInt_t fHeight
frame height
Definition TGFrame.h:88
void MapWindow() override
map window
Definition TGFrame.h:206
virtual Bool_t HandleDNDFinished()
Definition TGFrame.h:283
void Move(Int_t x, Int_t y) override
Move frame.
Definition TGFrame.cxx:585
virtual void DeleteWindow()
Delete window.
Definition TGFrame.cxx:268
void UnmapWindow() override
unmap window
Definition TGFrame.h:208
virtual Bool_t HandleDNDLeave()
Definition TGFrame.h:282
virtual TDNDData * GetDNDData(Atom_t)
Definition TGFrame.h:277
UInt_t fWidth
frame width
Definition TGFrame.h:87
void MapSubwindows() override
map sub windows
Definition TGFrame.h:202
static const TGGC & GetBckgndGC()
Get background color graphics context.
Definition TGFrame.cxx:767
void MapRaised() override
map raised
Definition TGFrame.h:207
Handle_t GetId() const
Definition TGObject.h:41
Handle_t fId
X11/Win32 Window identifier.
Definition TGObject.h:24
ROOT GUI Window base class.
Definition TGWindow.h:23
virtual const TGWindow * GetMainFrame() const
Returns top level main frame.
Definition TGWindow.cxx:150
virtual void LowerWindow()
lower window
Definition TGWindow.cxx:214
virtual void RaiseWindow()
raise window
Definition TGWindow.cxx:206
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Event structure.
Definition GuiTypes.h:174
EGEventType fType
of event (see EGEventType)
Definition GuiTypes.h:175
Handle_t fHandle
general resource handle (used for atoms or windows)
Definition GuiTypes.h:185
Longptr_t fUser[5]
5 longs can be used by client message events NOTE: only [0], [1] and [2] may be used.
Definition GuiTypes.h:187
Rectangle structure (maps to the X11 XRectangle structure)
Definition GuiTypes.h:361
Attributes that can be used when creating or changing a window.
Definition GuiTypes.h:93
#define XA_ATOM
Definition xatom.h:13
#define XA_WINDOW
Definition xatom.h:42