Logo ROOT   6.16/01
Reference Guide
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
17#define ROOTDND_PROTOCOL_VERSION 4
18#define XA_ATOM ((Atom_t) 4)
19#define XA_WINDOW ((Atom_t) 33)
20
24
32
38
42
45
47
48// TODO:
49// - add an TGFrame::HandleDNDStatus event handler?
50// - implement INCR protocol
51// - cache several requests?
52
54
56
57//_____________________________________________________________________________
58//
59// TGDragWindow
60//
61// Window used as drag icon during drag and drop operations.
62//_____________________________________________________________________________
63
65
66////////////////////////////////////////////////////////////////////////////////
67/// TGDragWindow constructor.
68
70 UInt_t options, Pixel_t back) :
71 TGFrame(p, 32, 32, options, back)
72{
73 if (fgDefaultCursor == kNone) {
74 fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
75 }
76
77 fPic = pic;
78 fMask = mask;
79
81
83 wattr.fSaveUnder = kTRUE;
85
86 gVirtualX->ChangeWindowAttributes(fId, &wattr);
87
88 int x, y;
89
90 gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
91
94
95 // This input window is used to make the dragging smoother when using
96 // highly complicated shapped windows (like labels and semitransparent
97 // icons), for some obscure reason most of the motion events get lost
98 // while the pointer is over the shaped window.
99
100 //fInput = gVirtualX->CreateWindow(fParent->GetId(), 0, 0, fWidth,
101 // fHeight, 0, 0, 0, 0, &wattr, 0);
102 fInput = fId;
103
105
106 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
107
108 gVirtualX->SetCursor(fId, fgDefaultCursor);
109}
110
111////////////////////////////////////////////////////////////////////////////////
112/// TGDragWindow destructor.
113
115{
116 //gVirtualX->DestroyWindow(fInput);
117}
118
119////////////////////////////////////////////////////////////////////////////////
120/// Map TGDragWindow.
121
123{
125 //gVirtualX->MapWindow(fInput);
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Unmap TGDragWindow.
130
132{
134 //gVirtualX->UnmapWindow(fInput);
135}
136
137////////////////////////////////////////////////////////////////////////////////
138/// Raise TGDragWindow.
139
141{
143 //gVirtualX->RaiseWindow(fInput);
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// Lower TGDragWindow.
148
150{
151 //gVirtualX->LowerWindow(fInput);
153}
154
155////////////////////////////////////////////////////////////////////////////////
156/// Map and Raise TGDragWindow.
157
159{
161 //gVirtualX->MapRaised(fInput);
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// Layout TGDragWindow.
166
168{
169 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Redraw TGDragWindow.
174
176{
177 gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
178}
179
180//_____________________________________________________________________________
181//
182// TGDNDManager
183//
184// Central Drag and Drop manager for ROOT.
185//_____________________________________________________________________________
186
188
189////////////////////////////////////////////////////////////////////////////////
190/// TGDNDManager constructor.
191
192TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t * /*typelist*/)
193{
194 if (gDNDManager)
195 // coverity[uninit_member]: already done
196 return;
197
198 fMain = toplevel;
201 //fTypelist = typelist;
202 fTypelist = new Atom_t[3];
203 fTypelist[0] = gVirtualX->InternAtom("application/root", kFALSE);
204 fTypelist[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
205 fTypelist[2] = 0;
206
207 if (!fgInit) {
208 InitAtoms();
209 fgInit = kTRUE;
210 }
211
212 //Reset();
213 fDropTimeout = 0;
214
215 fSource = kNone;
216 fTarget = kNone;
219 fDropAccepted = kFALSE; // this would become obsoleted by _acceptedAction
220 fAcceptedAction = kNone; // target's accepted action
221 fLocalAction = kNone; // our last specified action when we act as source
223 fDragWin = 0;
224 fLocalSource = 0;
225 fLocalTarget = 0;
226 fPic = fMask = kNone;
227 fDraggerTypes = 0;
229 fHotx = fHoty = 0;
230
232
233 fDNDNoDropCursor = gVirtualX->CreateCursor(kNoDrop); // kNoDrop
234
235 // set the aware prop
236
238 gDNDManager = this;
239}
240
241////////////////////////////////////////////////////////////////////////////////
242/// TGDNDManager destructor.
243
245{
246 // remove the proxy prop if we own it
247 if (fProxyOurs)
249
250 // remove the aware prop ant the types list, if any
251 if (fMain) {
252 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDAware);
253 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDTypeList);
254 }
255 if (fDropTimeout) delete fDropTimeout;
256
257 // delete the drag pixmap, if any
258 if (fDragWin) {
260 fDragWin = 0;
261 }
262 if (fPic != kNone) gVirtualX->DeletePixmap(fPic);
263 if (fMask != kNone) gVirtualX->DeletePixmap(fMask);
264
265 if (fDraggerTypes) delete[] fDraggerTypes;
266 if (fTypelist) delete[] fTypelist;
267}
268
288
289////////////////////////////////////////////////////////////////////////////////
290/// Initialize drag and drop atoms.
291
293{
294 // awareness
295 fgDNDAware = gVirtualX->InternAtom("XdndAware", kFALSE);
296
297 // selection
298 fgDNDSelection = gVirtualX->InternAtom("XdndSelection", kFALSE);
299
300 // proxy window
301 fgDNDProxy = gVirtualX->InternAtom("XdndProxy", kFALSE);
302
303 // messages
304 fgDNDEnter = gVirtualX->InternAtom("XdndEnter", kFALSE);
305 fgDNDLeave = gVirtualX->InternAtom("XdndLeave", kFALSE);
306 fgDNDPosition = gVirtualX->InternAtom("XdndPosition", kFALSE);
307 fgDNDStatus = gVirtualX->InternAtom("XdndStatus", kFALSE);
308 fgDNDDrop = gVirtualX->InternAtom("XdndDrop", kFALSE);
309 fgDNDFinished = gVirtualX->InternAtom("XdndFinished", kFALSE);
310
311 // actions
312 fgDNDActionCopy = gVirtualX->InternAtom("XdndActionCopy", kFALSE);
313 fgDNDActionMove = gVirtualX->InternAtom("XdndActionMove", kFALSE);
314 fgDNDActionLink = gVirtualX->InternAtom("XdndActionLink", kFALSE);
315 fgDNDActionAsk = gVirtualX->InternAtom("XdndActionAsk", kFALSE);
316 fgDNDActionPrivate = gVirtualX->InternAtom("XdndActionPrivate", kFALSE);
317
318 // types list
319 fgDNDTypeList = gVirtualX->InternAtom("XdndTypeList", kFALSE);
320 fgDNDActionList = gVirtualX->InternAtom("XdndActionList", kFALSE);
321 fgDNDActionDescrip = gVirtualX->InternAtom("XdndActionDescription", kFALSE);
322
323 // misc
324 fgXAWMState = gVirtualX->InternAtom("WM_STATE", kFALSE);
325 fgXCDNDData = gVirtualX->InternAtom("_XC_DND_DATA", kFALSE);
326}
327
328static int ArrayLength(Atom_t *a)
329{
330 // Returns length of array a.
331
332 int n;
333
334 for (n = 0; a[n]; n++) { }
335 return n;
336}
337
338////////////////////////////////////////////////////////////////////////////////
339/// Check if window win is DND aware.
340
342{
343 return gVirtualX->IsDNDAware(win, typelist);
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Search for DND aware window at position x,y.
348
350{
351 if (maxd <= 0) return kNone;
352
353 if (fDragWin && fDragWin->HasWindow(root)) return kNone;
354
355 return gVirtualX->FindRWindow(root, fDragWin ? fDragWin->GetId() : 0,
357 x, y, maxd);
358}
359
360
361////////////////////////////////////////////////////////////////////////////////
362/// Get root window proxy.
363
365{
366 Atom_t actual;
367 Int_t format = 32;
368 ULong_t count, remaining;
369 unsigned char *data = 0;
370 Window_t win, proxy = kNone;
371
372 // search for XdndProxy property on the root window...
373
374 // XSync(_dpy, kFALSE); // get to known state...
375 gVirtualX->UpdateWindow(0);
376
377 //oldhandler = XSetErrorHandler(TGDNDManager::CatchXError);
378 //target_error = kFALSE;
379
380 gVirtualX->GetProperty(gVirtualX->GetDefaultRootWindow(),
382 &actual, &format, &count, &remaining, &data);
383
384 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
385
386 // found the XdndProxy property, now check for the proxy window...
387 win = *((Window_t *) data);
388 delete[] data;
389 data = 0;
390
391 gVirtualX->GetProperty(win, fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
392 &actual, &format, &count, &remaining, &data);
393
394 // XSync(_dpy, kFALSE); // force the error...
395 gVirtualX->UpdateWindow(0);
396
397 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
398 if (*((Window_t *) data) == win) {
399
400 // proxy window exists and is correct
401 proxy = win;
402 }
403 }
404 }
405 if (data) delete[] data;
406 //oldhandler = XSetErrorHandler(oldhandler);
407 return proxy;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// Handle DND related client messages.
412
414{
415 if (event->fHandle == fgDNDEnter) {
416 HandleDNDEnter((Window_t) event->fUser[0], event->fUser[1],
417 (Atom_t *) &event->fUser[2]);
418
419 } else if (event->fHandle == fgDNDLeave) {
420 HandleDNDLeave((Window_t) event->fUser[0]);
421
422 } else if (event->fHandle == fgDNDPosition) {
423 HandleDNDPosition((Window_t) event->fUser[0],
424 (Int_t) (event->fUser[2] >> 16) & 0xFFFF, // x_root
425 (Int_t) (event->fUser[2] & 0xFFFF), // y_root
426 (Atom_t) event->fUser[4], // action
427 (Time_t) event->fUser[3]); // timestamp
428
429 } else if (event->fHandle == fgDNDStatus) {
430 Rectangle_t skip;
431 skip.fX = (event->fUser[2] >> 16) & 0xFFFF;
432 skip.fY = (event->fUser[2] & 0xFFFF);
433 skip.fWidth = (event->fUser[3] >> 16) & 0xFFFF;
434 skip.fHeight = (event->fUser[3] & 0xFFFF);
435
436 HandleDNDStatus((Window_t) event->fUser[0],
437 (int) (event->fUser[1] & 0x1),
438 skip, (Atom_t) event->fUser[4]);
439
440 } else if (event->fHandle == fgDNDDrop) {
441 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
442
443 } else if (event->fHandle == fgDNDFinished) {
444 HandleDNDFinished((Window_t) event->fUser[0]);
445
446 } else {
447 return kFALSE; // not for us...
448 }
449 return kTRUE;
450}
451
452////////////////////////////////////////////////////////////////////////////////
453/// Handle Drop timeout.
454
456{
457 if (t == fDropTimeout) {
458 // The drop operation timed out without receiving
459 // status confirmation from the target. Send a
460 // leave message instead (and notify the user or widget).
461 delete fDropTimeout;
462 fDropTimeout = 0;
463
466
468 return kTRUE;
469 }
470 return kFALSE;
471}
472
473////////////////////////////////////////////////////////////////////////////////
474/// Send DND enter message to target window.
475
477{
478 Int_t i, n;
479 Event_t event;
480
481 event.fType = kClientMessage;
482 event.fWindow = target;
483 event.fHandle = fgDNDEnter;
484 event.fFormat = 32;
485
486 event.fUser[0] = fMain->GetId(); // from;
487
489
490 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
491
492 // set the first 1-3 data types
493
494 for (i = 0; i < 3; ++i)
495 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
496
497 if (fLocalSource) {
498 TDNDData *dnddata = 0;
499 Atom_t dataType;
500
501 // get the data type from the drag source widget
502 if (fLocalSource)
503 dnddata = fLocalSource->GetDNDData(0);
504 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
505 event.fUser[2] = dataType;
506 event.fUser[3] = kNone;
507 event.fUser[4] = kNone;
508 }
509
510 gVirtualX->SendEvent(target, &event);
511}
512
513////////////////////////////////////////////////////////////////////////////////
514/// Send DND leave message to target window.
515
517{
518 Event_t event;
519
520 event.fType = kClientMessage;
521 event.fWindow = target;
522 event.fHandle = fgDNDLeave;
523 event.fFormat = 32;
524
525 event.fUser[0] = fMain->GetId(); // from;
526 event.fUser[1] = 0L;
527
528 event.fUser[2] = 0L;
529 event.fUser[3] = 0L;
530 event.fUser[4] = 0L;
531
532 gVirtualX->SendEvent(target, &event);
533}
534
535////////////////////////////////////////////////////////////////////////////////
536/// Send DND position message to target window.
537
539 Atom_t action, Time_t timestamp)
540{
541 Event_t event;
542
543 event.fType = kClientMessage;
544 event.fWindow = target;
545 event.fHandle = fgDNDPosition;
546 event.fFormat = 32;
547
548 event.fUser[0] = fMain->GetId(); // from;
549 event.fUser[1] = 0L;
550
551 event.fUser[2] = (x << 16) | y; // root coodinates
552 event.fUser[3] = timestamp; // timestamp for retrieving data
553 event.fUser[4] = action; // requested action
554
555 gVirtualX->SendEvent(target, &event);
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Send DND status message to source window.
560
562{
563 Event_t event;
564
565 event.fType = kClientMessage;
566 event.fWindow = source;
567 event.fHandle = fgDNDStatus;
568 event.fFormat = 32;
569
570 event.fUser[0] = fMain->GetId(); // from;
571 event.fUser[1] = (action == kNone) ? 0L : 1L;
572
573 event.fUser[2] = 0L; // empty rectangle
574 event.fUser[3] = 0L;
575 event.fUser[4] = action; // accepted action
576
577 gVirtualX->SendEvent(source, &event);
578}
579
580////////////////////////////////////////////////////////////////////////////////
581/// Send DND drop message to target window.
582
584{
585 Event_t event;
586
587 event.fType = kClientMessage;
588 event.fWindow = target;
589 event.fHandle = fgDNDDrop;
590 event.fFormat = 32;
591
592 event.fUser[0] = fMain->GetId(); // from;
593 event.fUser[1] = 0L; // reserved
594 event.fUser[2] = 0L; //CurrentTime; // timestamp
595 event.fUser[3] = 0L;
596 event.fUser[4] = 0L;
597
598 gVirtualX->SendEvent(target, &event);
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// Send DND finished message to source window.
603
605{
606 Event_t event;
607
608 event.fType = kClientMessage;
609 event.fWindow = source;
610 event.fHandle = fgDNDFinished;
611 event.fFormat = 32;
612
613 event.fUser[0] = fMain->GetId(); // from;
614 event.fUser[1] = 0L; // reserved
615 event.fUser[2] = 0L;
616 event.fUser[3] = 0L;
617 event.fUser[4] = 0L;
618
619 gVirtualX->SendEvent(source, &event);
620}
621
622////////////////////////////////////////////////////////////////////////////////
623/// Handle DND enter event.
624
626{
627 fSource = src;
628
629 if (fDraggerTypes) delete[] fDraggerTypes;
630
631 if (vers & 1) { // more than 3 data types?
632 Atom_t type, *a;
633 Int_t format = 32;
634 ULong_t i, count, remaining;
635 unsigned char *data = 0;
636
637 gVirtualX->GetProperty(src, fgDNDTypeList,
638 0, 0x8000000L, kFALSE, XA_ATOM,
639 &type, &format, &count, &remaining, &data);
640
641 if (type != XA_ATOM || format != 32 || !data) {
642 count = 0;
643 }
644
645 fDraggerTypes = new Atom_t[count+4];
646
647 a = (Atom_t *) data;
648 for (i = 0; i < count; i++)
649 fDraggerTypes[i] = a[i];
650
651 fDraggerTypes[i] = kNone;
652
653 if (data) delete[] data;
654
655 } else {
656 fDraggerTypes = new Atom_t[4];
657
658 fDraggerTypes[0] = dataTypes[0];
659 fDraggerTypes[1] = dataTypes[1];
660 fDraggerTypes[2] = dataTypes[2];
661
662 fDraggerTypes[3] = kNone;
663 }
664
665 // the following is not strictly neccessary, unless the previous
666 // dragging application crashed without sending XdndLeave
668 fLocalTarget = 0;
669
670 return kTRUE;
671}
672
673////////////////////////////////////////////////////////////////////////////////
674/// Handle DND leave event.
675
677{
678 fSource = kNone;
680 fLocalTarget = 0;
681
682 if (fDraggerTypes) delete[] fDraggerTypes;
683 fDraggerTypes = 0;
684
685 return kTRUE;
686}
687
688////////////////////////////////////////////////////////////////////////////////
689/// Handle DND position event.
690
692 Atom_t action, Time_t /*timestamp*/)
693{
694 Int_t x = 0, y = 0;
695 Window_t child;
696 TGFrame *f = 0, *main = 0;
697 TGWindow *w = 0;
698 Window_t wtarget = 0;
699
700 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
701
702 if (wtarget) {
703 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
704 wtarget, x_root, y_root, x, y, child);
705 w = gClient->GetWindowById(wtarget);
706 if (w)
707 f = dynamic_cast<TGFrame *>(w);
708 }
709
710 if (f != fLocalTarget) {
712 fLocalTarget = f;
713 if (fLocalTarget) {
715 main->RaiseWindow();
716 if (fMain == 0)
717 fMain = main;
719 }
720 }
721 // query the target widget to determine whether it accepts the
722 // required action
723 if (fLocalTarget) {
724 action = (fDropType == kNone) ? kNone :
725 fLocalTarget->HandleDNDPosition(x, y, action, x_root, y_root);
726 } else if (fProxyOurs) {
727 action = fMain->HandleDNDPosition(x, y, action, x_root, y_root);
728 } else {
729 action = kNone;
730 }
731 SendDNDStatus(source, fLocalAction = action);
732 return kTRUE;
733}
734
735////////////////////////////////////////////////////////////////////////////////
736/// Handle DND status event.
737
739 Rectangle_t /*area*/, Atom_t action)
740{
741 if (target) {
743 if (accepted) {
745 fAcceptedAction = action;
746 if (fDragWin)
747 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
749 } else {
752 if (fDragWin)
753 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
756 }
757 if (fDropTimeout) { // were we waiting for this to do the drop?
758 delete fDropTimeout;
759 fDropTimeout = 0;
761 }
762 }
763 return kTRUE;
764}
765
766////////////////////////////////////////////////////////////////////////////////
767/// Handle DND drop event.
768
770{
771 // to get the data, we must call XConvertSelection with
772 // the timestamp in XdndDrop, wait for SelectionNotify
773 // to arrive to retrieve the data, and when we are finished,
774 // send a XdndFinished message to the source.
775
776 if (fMain && fDropType != kNone) {
777 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
778 8, (unsigned char *) 0, 0);
779
780 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
781 fgXCDNDData, timestamp);
782 }
783
784 fSource = source;
785 if (fMain) SendDNDFinished(source);
786
787 return kTRUE;
788}
789
790////////////////////////////////////////////////////////////////////////////////
791/// Handle DND finished event.
792
794{
796 return kTRUE;
797}
798
799////////////////////////////////////////////////////////////////////////////////
800/// Handle selection request event.
801
803{
804 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
805 Event_t xevent;
806 TDNDData *dnddata = 0;
807 char *data;
808 int len;
809
810 // get the data from the drag source widget
811 if (fLocalSource)
812 dnddata = fLocalSource->GetDNDData(event->fUser[2]);
813
814 data = dnddata ? (char *) dnddata->fData : (char *) "";
815 len = dnddata ? dnddata->fDataLength : 0;
816
817 if ((Atom_t)event->fUser[3] == kNone) {
818 //printf("warning: kNone property specified in SelectionRequest\n");
819 event->fUser[3] = fgXCDNDData;
820 }
821
822 gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
823 event->fUser[2], 8,
824 (unsigned char *) data, len);
825
826 xevent.fType = kSelectionNotify;
827 xevent.fTime = event->fTime;
828 xevent.fUser[0] = event->fUser[0]; // requestor
829 xevent.fUser[1] = event->fUser[1]; // selection
830 xevent.fUser[2] = event->fUser[2]; // target;
831 xevent.fUser[3] = event->fUser[3]; // property;
832 gVirtualX->SendEvent(event->fUser[0], &xevent);
833
834 return kTRUE;
835 } else {
836 return kFALSE; // not for us...
837 }
838}
839
840////////////////////////////////////////////////////////////////////////////////
841/// Handle selection event.
842
844{
845 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
846 Atom_t actual = fDropType;
847 Int_t format = 8;
848 ULong_t count, remaining;
849 unsigned char *data = 0;
850
851
852 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
853 0, 0x8000000L, kTRUE, event->fUser[2],
854 &actual, &format, &count, &remaining, &data);
855
856 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
857 if (data) delete[] data;
858
859 return kFALSE;
860 }
861
863
864 // send the data to the target widget
865
866 if (fLocalTarget) {
867 TDNDData dndData(actual, data, count, fLocalAction);
868 fLocalTarget->HandleDNDDrop(&dndData);
869 if (fDraggerTypes) delete[] fDraggerTypes;
870 fDraggerTypes = 0;
871 }
872
873 fSource = kNone;
875
876// delete[] data;
877
878 return kTRUE;
879
880 } else {
881 return kFALSE; // not for us...
882 }
883}
884
885////////////////////////////////////////////////////////////////////////////////
886/// Set drag window pixmaps and hotpoint.
887
889 int hot_x, int hot_y)
890{
891 fPic = pic;
892 fMask = mask;
893 fHotx = hot_x;
894 fHoty = hot_y;
895}
896
897////////////////////////////////////////////////////////////////////////////////
898/// Start dragging.
899
900Bool_t TGDNDManager::StartDrag(TGFrame *src, int x_root, int y_root,
901 Window_t grabWin)
902{
903 if (fDragging) return kTRUE;
904
905 fLocalSource = src;
906
907 if ((TGWindow *)fMain != src->GetMainFrame()) {
908 fMain = (TGFrame *)src->GetMainFrame();
909 }
910
911 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
912 // hmmm... failed to acquire ownership of XdndSelection!
913 return kFALSE;
914 }
915
916 if (grabWin == kNone) grabWin = fMain->GetId();
917
918 gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
919
920 fLocalTarget = 0;
922 fTarget = kNone;
925 if (fDropTimeout) delete fDropTimeout;
926 fDropTimeout = 0;
930
931 if (!fDragWin && fPic != kNone && fMask != kNone) {
932 fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
933 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
936 }
937 return kTRUE;
938}
939
940////////////////////////////////////////////////////////////////////////////////
941/// Drop.
942
944{
945 if (!fDragging) return kFALSE;
946
947 if (fTargetIsDNDAware) {
948 if (fDropAccepted) {
949 if (fStatusPending) {
950 if (fDropTimeout) delete fDropTimeout;
951 fDropTimeout = new TTimer(this, 5000);
952 } else {
954 }
955 } else {
958 }
959 }
960 EndDrag();
961 return kTRUE;
962}
963
964////////////////////////////////////////////////////////////////////////////////
965/// End dragging.
966
968{
969 if (!fDragging) return kFALSE;
970
971 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
972
973 if (fSource)
975 if (fLocalSource)
977
979 if (fDragWin) {
981 fDragWin = 0;
982 }
983 return kTRUE;
984}
985
986////////////////////////////////////////////////////////////////////////////////
987/// Process drag event.
988
989Bool_t TGDNDManager::Drag(int x_root, int y_root, Atom_t action, Time_t timestamp)
990{
991 if (!fDragging) return kFALSE;
992
993 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
994 x_root, y_root, 15);
995
996 if (newTarget == kNone) {
998 if (t != kNone) newTarget = t;
999 }
1000
1001 if (fTarget != newTarget) {
1002
1004
1005 fTarget = newTarget;
1010
1012
1013 if (fDragWin)
1014 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
1016 }
1017
1019 SendDNDPosition(fTarget, x_root, y_root, action, timestamp);
1020
1021 // this is to avoid sending XdndPosition messages over and over
1022 // if the target is not responding
1024 }
1025
1026 if (fDragWin) {
1028 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
1029 }
1030 return kTRUE;
1031}
1032
1033////////////////////////////////////////////////////////////////////////////////
1034/// Set root window proxy.
1035
1037{
1038 Window_t mainw = fMain->GetId();
1039 int result = kFALSE;
1040
1041 if (GetRootProxy() == kNone) {
1042 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
1043 fgDNDProxy, XA_WINDOW, 32,
1044 (unsigned char *) &mainw, 1);
1045 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
1046 (unsigned char *) &mainw, 1);
1047
1048 fProxyOurs = kTRUE;
1049 result = kTRUE;
1050 }
1051 // XSync(_dpy, kFALSE);
1052 gVirtualX->UpdateWindow(0);
1053 return result;
1054}
1055
1056////////////////////////////////////////////////////////////////////////////////
1057/// Remove root window proxy.
1058
1060{
1061 if (!fProxyOurs) return kFALSE;
1062
1063 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
1064 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
1065 // the following is to ensure that the properties
1066 // (specially the one on the root window) are deleted
1067 // in case the application is exiting...
1068
1069 // XSync(_dpy, kFALSE);
1070 gVirtualX->UpdateWindow(0);
1071
1073
1074 return kTRUE;
1075}
@ kSelectionNotify
Definition: GuiTypes.h:62
@ kClientMessage
Definition: GuiTypes.h:62
const Mask_t kWAOverrideRedirect
Definition: GuiTypes.h:148
Handle_t Cursor_t
Definition: GuiTypes.h:33
const Mask_t kButtonMotionMask
Definition: GuiTypes.h:163
const Mask_t kButtonPressMask
Definition: GuiTypes.h:160
const Mask_t kWASaveUnder
Definition: GuiTypes.h:149
Handle_t Pixmap_t
Definition: GuiTypes.h:29
ULong_t Time_t
Definition: GuiTypes.h:41
Handle_t Atom_t
Definition: GuiTypes.h:36
const Handle_t kNone
Definition: GuiTypes.h:87
const Mask_t kButtonReleaseMask
Definition: GuiTypes.h:161
ULong_t Pixel_t
Definition: GuiTypes.h:39
Handle_t Window_t
Definition: GuiTypes.h:28
#define f(i)
Definition: RSha256.hxx:104
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
#define gClient
Definition: TGClient.h:166
#define XA_ATOM
TGDNDManager * gDNDManager
#define ROOTDND_PROTOCOL_VERSION
static int ArrayLength(Atom_t *a)
#define XA_WINDOW
int type
Definition: TGX11.cxx:120
#define gVirtualX
Definition: TVirtualX.h:345
@ kTopLeft
Definition: TVirtualX.h:44
@ kNoDrop
Definition: TVirtualX.h:47
Atom_t fDataType
Definition: TGDNDManager.h:75
Int_t fDataLength
Definition: TGDNDManager.h:78
void * fData
Definition: TGDNDManager.h:77
static Atom_t fgDNDAware
Definition: TGDNDManager.h:116
static Atom_t fgDNDVersion
Definition: TGDNDManager.h:119
Bool_t HandleDNDEnter(Window_t src, long vers, Atom_t dataTypes[3])
Handle DND enter event.
virtual ~TGDNDManager()
TGDNDManager destructor.
static Atom_t fgDNDActionPrivate
Definition: TGDNDManager.h:121
Window_t fSource
Definition: TGDNDManager.h:103
static Atom_t fgDNDActionAsk
Definition: TGDNDManager.h:121
static Atom_t GetDNDDrop()
static Atom_t GetDNDActionAsk()
TGFrame * fMain
Definition: TGDNDManager.h:92
static Atom_t fgDNDActionMove
Definition: TGDNDManager.h:120
Pixmap_t fMask
Definition: TGDNDManager.h:111
Bool_t HandleSelectionRequest(Event_t *event)
Handle selection request event.
static Atom_t fgDNDActionLink
Definition: TGDNDManager.h:120
Bool_t HandleClientMessage(Event_t *event)
Handle DND related client messages.
TTimer * fDropTimeout
Definition: TGDNDManager.h:108
static Atom_t fgDNDActionDescrip
Definition: TGDNDManager.h:122
void SendDNDEnter(Window_t target)
Send DND enter message to target window.
static Atom_t fgDNDSelection
Definition: TGDNDManager.h:116
Bool_t fTargetIsDNDAware
Definition: TGDNDManager.h:104
Bool_t fStatusPending
Definition: TGDNDManager.h:100
void InitAtoms()
Initialize drag and drop atoms.
static Atom_t fgDNDFinished
Definition: TGDNDManager.h:118
Atom_t fDropType
Definition: TGDNDManager.h:95
static Atom_t fgDNDDrop
Definition: TGDNDManager.h:118
static Atom_t GetXCDNDData()
static Atom_t GetDNDVersion()
Bool_t fProxyOurs
Definition: TGDNDManager.h:102
static Atom_t GetDNDActionLink()
static Atom_t fgDNDEnter
Definition: TGDNDManager.h:117
Bool_t HandleTimer(TTimer *t)
Handle Drop timeout.
Bool_t HandleDNDDrop(Window_t src, Time_t timestamp)
Handle DND drop event.
static Atom_t GetDNDStatus()
Atom_t * fDraggerTypes
Definition: TGDNDManager.h:94
static Atom_t fgXCDNDData
Definition: TGDNDManager.h:123
Bool_t HandleDNDFinished(Window_t target)
Handle DND finished event.
static Atom_t fgDNDPosition
Definition: TGDNDManager.h:117
static Atom_t fgDNDLeave
Definition: TGDNDManager.h:117
Bool_t HandleSelection(Event_t *event)
Handle selection event.
Atom_t fLocalAction
Definition: TGDNDManager.h:96
TGFrame * fLocalSource
Definition: TGDNDManager.h:106
static Atom_t GetDNDTypeList()
static Bool_t fgInit
Definition: TGDNDManager.h:125
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
Definition: TGDNDManager.h:120
static Atom_t GetDNDProxy()
static Atom_t fgDNDProxy
Definition: TGDNDManager.h:116
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
Definition: TGDNDManager.h:101
void SendDNDStatus(Window_t target, Atom_t action)
Send DND status message to source window.
Bool_t fDragging
Definition: TGDNDManager.h:98
static Atom_t GetDNDAware()
Bool_t IsDNDAware(Window_t win, Atom_t *typelist=0)
Check if window win is DND aware.
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
Definition: TGDNDManager.h:122
UInt_t fGrabEventMask
Definition: TGDNDManager.h:105
Bool_t fDropAccepted
Definition: TGDNDManager.h:99
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
Definition: TGDNDManager.h:122
Atom_t fVersion
Definition: TGDNDManager.h:93
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
Definition: TGDNDManager.h:126
Pixmap_t fPic
Definition: TGDNDManager.h:111
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
Definition: TGDNDManager.h:113
Bool_t Drag(Int_t x_root, Int_t y_root, Atom_t action, Time_t timestamp)
Process drag event.
TGFrame * fLocalTarget
Definition: TGDNDManager.h:106
void SendDNDDrop(Window_t target)
Send DND drop message to target window.
static Atom_t GetDNDPosition()
static Atom_t GetDNDActionPrivate()
static Atom_t fgDNDStatus
Definition: TGDNDManager.h:117
TGDNDManager(const TGDNDManager &)
Window_t fTarget
Definition: TGDNDManager.h:103
Bool_t HandleDNDLeave(Window_t src)
Handle DND leave event.
Atom_t fAcceptedAction
Definition: TGDNDManager.h:96
void SendDNDLeave(Window_t target)
Send DND leave message to target window.
TGDragWindow * fDragWin
Definition: TGDNDManager.h:109
Atom_t * fTypelist
Definition: TGDNDManager.h:94
Bool_t Drop()
Drop.
Bool_t SetRootProxy()
Set root window proxy.
static Atom_t GetDNDActionCopy()
Bool_t EndDrag()
End dragging.
static Atom_t GetDNDActionMove()
static Atom_t GetDNDLeave()
virtual ~TGDragWindow()
TGDragWindow destructor.
virtual void DoRedraw()
Redraw TGDragWindow.
virtual void MapRaised()
Map and Raise TGDragWindow.
virtual void Layout()
Layout TGDragWindow.
virtual void RaiseWindow()
Raise TGDragWindow.
virtual void UnmapWindow()
Unmap TGDragWindow.
Bool_t HasWindow(Window_t w) const
Definition: TGDNDManager.h:51
virtual TGDimension GetDefaultSize() const
std::cout << fWidth << "x" << fHeight << std::endl;
Definition: TGDNDManager.h:40
TGDragWindow(const TGWindow *p, Pixmap_t pic, Pixmap_t mask, UInt_t options=kChildFrame, Pixel_t back=GetWhitePixel())
TGDragWindow constructor.
Window_t GetInputId() const
Definition: TGDNDManager.h:50
virtual void LowerWindow()
Lower TGDragWindow.
Window_t fInput
Definition: TGDNDManager.h:31
Pixmap_t fMask
Definition: TGDNDManager.h:32
Pixmap_t fPic
Definition: TGDNDManager.h:32
static Cursor_t fgDefaultCursor
Definition: TGDNDManager.h:26
virtual void MapWindow()
Map TGDragWindow.
virtual Atom_t HandleDNDEnter(Atom_t *)
Definition: TGFrame.h:326
virtual Atom_t HandleDNDPosition(Int_t, Int_t, Atom_t, Int_t, Int_t)
Definition: TGFrame.h:324
virtual Bool_t HandleDNDDrop(TDNDData *)
Definition: TGFrame.h:323
virtual void MapRaised()
Definition: TGFrame.h:252
UInt_t fHeight
Definition: TGFrame.h:135
virtual Bool_t HandleDNDFinished()
Definition: TGFrame.h:328
virtual void DeleteWindow()
Delete window.
Definition: TGFrame.cxx:258
virtual Bool_t HandleDNDLeave()
Definition: TGFrame.h:327
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition: TGFrame.cxx:575
virtual TDNDData * GetDNDData(Atom_t)
Definition: TGFrame.h:322
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition: TGFrame.cxx:587
UInt_t fWidth
Definition: TGFrame.h:134
virtual void MapWindow()
Definition: TGFrame.h:251
virtual void MapSubwindows()
Definition: TGFrame.h:247
static const TGGC & GetBckgndGC()
Get background color graphics context.
Definition: TGFrame.cxx:757
virtual void UnmapWindow()
Definition: TGFrame.h:253
Handle_t GetId() const
Definition: TGObject.h:47
Handle_t fId
Definition: TGObject.h:36
virtual const TGWindow * GetMainFrame() const
Returns top level main frame.
Definition: TGWindow.cxx:133
virtual void LowerWindow()
Definition: TGWindow.h:95
virtual void RaiseWindow()
Definition: TGWindow.h:94
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
int main(int argc, char **argv)
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
static constexpr double L
EGEventType fType
Definition: GuiTypes.h:174
Handle_t fHandle
Definition: GuiTypes.h:184
Long_t fUser[5]
Definition: GuiTypes.h:186
Time_t fTime
Definition: GuiTypes.h:176
Short_t fX
Definition: GuiTypes.h:361
UShort_t fHeight
Definition: GuiTypes.h:362
Short_t fY
Definition: GuiTypes.h:361
UShort_t fWidth
Definition: GuiTypes.h:362
Bool_t fOverrideRedirect
Definition: GuiTypes.h:106
auto * a
Definition: textangle.C:12