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