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//
61// TGDragWindow
62//
63// Window used as drag icon during drag and drop operations.
64//_____________________________________________________________________________
65
67
68////////////////////////////////////////////////////////////////////////////////
69/// TGDragWindow constructor.
70
72 UInt_t options, Pixel_t back) :
73 TGFrame(p, 32, 32, options, back)
74{
75 if (fgDefaultCursor == kNone) {
76 fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
77 }
78
79 fPic = pic;
80 fMask = mask;
81
83
85 wattr.fSaveUnder = kTRUE;
87
88 gVirtualX->ChangeWindowAttributes(fId, &wattr);
89
90 int x, y;
91
92 gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
93
96
97 // This input window is used to make the dragging smoother when using
98 // highly complicated shapped windows (like labels and semitransparent
99 // icons), for some obscure reason most of the motion events get lost
100 // while the pointer is over the shaped window.
101
102 //fInput = gVirtualX->CreateWindow(fParent->GetId(), 0, 0, fWidth,
103 // fHeight, 0, 0, 0, 0, &wattr, 0);
104 fInput = fId;
105
107
108 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
109
110 gVirtualX->SetCursor(fId, fgDefaultCursor);
111}
112
113////////////////////////////////////////////////////////////////////////////////
114/// TGDragWindow destructor.
115
117{
118 //gVirtualX->DestroyWindow(fInput);
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// Map TGDragWindow.
123
125{
127 //gVirtualX->MapWindow(fInput);
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Unmap TGDragWindow.
132
134{
136 //gVirtualX->UnmapWindow(fInput);
137}
138
139////////////////////////////////////////////////////////////////////////////////
140/// Raise TGDragWindow.
141
143{
145 //gVirtualX->RaiseWindow(fInput);
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Lower TGDragWindow.
150
152{
153 //gVirtualX->LowerWindow(fInput);
155}
156
157////////////////////////////////////////////////////////////////////////////////
158/// Map and Raise TGDragWindow.
159
161{
163 //gVirtualX->MapRaised(fInput);
164}
165
166////////////////////////////////////////////////////////////////////////////////
167/// Layout TGDragWindow.
168
170{
171 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// Redraw TGDragWindow.
176
178{
179 gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
180}
181
182//_____________________________________________________________________________
183//
184// TGDNDManager
185//
186// Central Drag and Drop manager for ROOT.
187//_____________________________________________________________________________
188
190
191////////////////////////////////////////////////////////////////////////////////
192/// TGDNDManager constructor.
193
194TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t * /*typelist*/)
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
344{
345 return gVirtualX->IsDNDAware(win, typelist);
346}
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{
368 Atom_t actual;
369 Int_t format = 32;
370 ULong_t count, remaining;
371 unsigned char *data = 0;
372 Window_t win, proxy = kNone;
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 HandleDNDPosition((Window_t) event->fUser[0],
426 (Int_t) (event->fUser[2] >> 16) & 0xFFFF, // x_root
427 (Int_t) (event->fUser[2] & 0xFFFF), // y_root
428 (Atom_t) event->fUser[4], // action
429 (Time_t) event->fUser[3]); // timestamp
430
431 } else if (event->fHandle == fgDNDStatus) {
432 Rectangle_t skip;
433 skip.fX = (event->fUser[2] >> 16) & 0xFFFF;
434 skip.fY = (event->fUser[2] & 0xFFFF);
435 skip.fWidth = (event->fUser[3] >> 16) & 0xFFFF;
436 skip.fHeight = (event->fUser[3] & 0xFFFF);
437
438 HandleDNDStatus((Window_t) event->fUser[0],
439 (int) (event->fUser[1] & 0x1),
440 skip, (Atom_t) event->fUser[4]);
441
442 } else if (event->fHandle == fgDNDDrop) {
443 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
444
445 } else if (event->fHandle == fgDNDFinished) {
446 HandleDNDFinished((Window_t) event->fUser[0]);
447
448 } else {
449 return kFALSE; // not for us...
450 }
451 return kTRUE;
452}
453
454////////////////////////////////////////////////////////////////////////////////
455/// Handle Drop timeout.
456
458{
459 if (t == fDropTimeout) {
460 // The drop operation timed out without receiving
461 // status confirmation from the target. Send a
462 // leave message instead (and notify the user or widget).
463 delete fDropTimeout;
464 fDropTimeout = 0;
465
468
470 return kTRUE;
471 }
472 return kFALSE;
473}
474
475////////////////////////////////////////////////////////////////////////////////
476/// Send DND enter message to target window.
477
479{
480 Int_t i, n;
481 Event_t event;
482
483 event.fType = kClientMessage;
484 event.fWindow = target;
485 event.fHandle = fgDNDEnter;
486 event.fFormat = 32;
487
488 event.fUser[0] = fMain->GetId(); // from;
489
491
492 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
493
494 // set the first 1-3 data types
495
496 for (i = 0; i < 3; ++i)
497 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
498
499 if (fLocalSource) {
500 TDNDData *dnddata = 0;
501 Atom_t dataType;
502
503 // get the data type from the drag source widget
504 if (fLocalSource)
505 dnddata = fLocalSource->GetDNDData(0);
506 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
507 event.fUser[2] = dataType;
508 event.fUser[3] = kNone;
509 event.fUser[4] = kNone;
510 }
511
512 gVirtualX->SendEvent(target, &event);
513}
514
515////////////////////////////////////////////////////////////////////////////////
516/// Send DND leave message to target window.
517
519{
520 Event_t event;
521
522 event.fType = kClientMessage;
523 event.fWindow = target;
524 event.fHandle = fgDNDLeave;
525 event.fFormat = 32;
526
527 event.fUser[0] = fMain->GetId(); // from;
528 event.fUser[1] = 0L;
529
530 event.fUser[2] = 0L;
531 event.fUser[3] = 0L;
532 event.fUser[4] = 0L;
533
534 gVirtualX->SendEvent(target, &event);
535}
536
537////////////////////////////////////////////////////////////////////////////////
538/// Send DND position message to target window.
539
541 Atom_t action, Time_t timestamp)
542{
543 Event_t event;
544
545 event.fType = kClientMessage;
546 event.fWindow = target;
547 event.fHandle = fgDNDPosition;
548 event.fFormat = 32;
549
550 event.fUser[0] = fMain->GetId(); // from;
551 event.fUser[1] = 0L;
552
553 event.fUser[2] = (x << 16) | y; // root coodinates
554 event.fUser[3] = timestamp; // timestamp for retrieving data
555 event.fUser[4] = action; // requested action
556
557 gVirtualX->SendEvent(target, &event);
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Send DND status message to source window.
562
564{
565 Event_t event;
566
567 event.fType = kClientMessage;
568 event.fWindow = source;
569 event.fHandle = fgDNDStatus;
570 event.fFormat = 32;
571
572 event.fUser[0] = fMain->GetId(); // from;
573 event.fUser[1] = (action == kNone) ? 0L : 1L;
574
575 event.fUser[2] = 0L; // empty rectangle
576 event.fUser[3] = 0L;
577 event.fUser[4] = action; // accepted action
578
579 gVirtualX->SendEvent(source, &event);
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Send DND drop message to target window.
584
586{
587 Event_t event;
588
589 event.fType = kClientMessage;
590 event.fWindow = target;
591 event.fHandle = fgDNDDrop;
592 event.fFormat = 32;
593
594 event.fUser[0] = fMain->GetId(); // from;
595 event.fUser[1] = 0L; // reserved
596 event.fUser[2] = 0L; //CurrentTime; // timestamp
597 event.fUser[3] = 0L;
598 event.fUser[4] = 0L;
599
600 gVirtualX->SendEvent(target, &event);
601}
602
603////////////////////////////////////////////////////////////////////////////////
604/// Send DND finished message to source window.
605
607{
608 Event_t event;
609
610 event.fType = kClientMessage;
611 event.fWindow = source;
612 event.fHandle = fgDNDFinished;
613 event.fFormat = 32;
614
615 event.fUser[0] = fMain->GetId(); // from;
616 event.fUser[1] = 0L; // reserved
617 event.fUser[2] = 0L;
618 event.fUser[3] = 0L;
619 event.fUser[4] = 0L;
620
621 gVirtualX->SendEvent(source, &event);
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// Handle DND enter event.
626
628{
629 fSource = src;
630
631 if (fDraggerTypes) delete[] fDraggerTypes;
632
633 if (vers & 1) { // more than 3 data types?
634 Atom_t type, *a;
635 Int_t format = 32;
636 ULong_t i, count, remaining;
637 unsigned char *data = 0;
638
639 gVirtualX->GetProperty(src, fgDNDTypeList,
640 0, 0x8000000L, kFALSE, XA_ATOM,
641 &type, &format, &count, &remaining, &data);
642
643 if (type != XA_ATOM || format != 32 || !data) {
644 count = 0;
645 }
646
647 fDraggerTypes = new Atom_t[count+4];
648
649 a = (Atom_t *) data;
650 for (i = 0; i < count; i++)
651 fDraggerTypes[i] = a[i];
652
653 fDraggerTypes[i] = kNone;
654
655 if (data) delete[] data;
656
657 } else {
658 fDraggerTypes = new Atom_t[4];
659
660 fDraggerTypes[0] = dataTypes[0];
661 fDraggerTypes[1] = dataTypes[1];
662 fDraggerTypes[2] = dataTypes[2];
663
664 fDraggerTypes[3] = kNone;
665 }
666
667 // the following is not strictly neccessary, unless the previous
668 // dragging application crashed without sending XdndLeave
670 fLocalTarget = 0;
671
672 return kTRUE;
673}
674
675////////////////////////////////////////////////////////////////////////////////
676/// Handle DND leave event.
677
679{
680 fSource = kNone;
682 fLocalTarget = 0;
683
684 if (fDraggerTypes) delete[] fDraggerTypes;
685 fDraggerTypes = 0;
686
687 return kTRUE;
688}
689
690////////////////////////////////////////////////////////////////////////////////
691/// Handle DND position event.
692
694 Atom_t action, Time_t /*timestamp*/)
695{
696 Int_t x = 0, y = 0;
697 Window_t child;
698 TGFrame *f = 0, *main = 0;
699 TGWindow *w = 0;
700 Window_t wtarget = 0;
701
702 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
703
704 if (wtarget) {
705 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
706 wtarget, x_root, y_root, x, y, child);
707 w = gClient->GetWindowById(wtarget);
708 if (w)
709 f = dynamic_cast<TGFrame *>(w);
710 }
711
712 if (f != fLocalTarget) {
714 fLocalTarget = f;
715 if (fLocalTarget) {
717 main->RaiseWindow();
718 if (fMain == 0)
719 fMain = main;
721 }
722 }
723 // query the target widget to determine whether it accepts the
724 // required action
725 if (fLocalTarget) {
726 action = (fDropType == kNone) ? kNone :
727 fLocalTarget->HandleDNDPosition(x, y, action, x_root, y_root);
728 } else if (fProxyOurs) {
729 action = fMain->HandleDNDPosition(x, y, action, x_root, y_root);
730 } else {
731 action = kNone;
732 }
733 SendDNDStatus(source, fLocalAction = action);
734 return kTRUE;
735}
736
737////////////////////////////////////////////////////////////////////////////////
738/// Handle DND status event.
739
741 Rectangle_t /*area*/, Atom_t action)
742{
743 if (target) {
745 if (accepted) {
747 fAcceptedAction = action;
748 if (fDragWin)
749 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
751 } else {
754 if (fDragWin)
755 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
758 }
759 if (fDropTimeout) { // were we waiting for this to do the drop?
760 delete fDropTimeout;
761 fDropTimeout = 0;
763 }
764 }
765 return kTRUE;
766}
767
768////////////////////////////////////////////////////////////////////////////////
769/// Handle DND drop event.
770
772{
773 // to get the data, we must call XConvertSelection with
774 // the timestamp in XdndDrop, wait for SelectionNotify
775 // to arrive to retrieve the data, and when we are finished,
776 // send a XdndFinished message to the source.
777
778 if (fMain && fDropType != kNone) {
779 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
780 8, (unsigned char *) 0, 0);
781
782 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
783 fgXCDNDData, timestamp);
784 }
785
786 fSource = source;
787 if (fMain) SendDNDFinished(source);
788
789 return kTRUE;
790}
791
792////////////////////////////////////////////////////////////////////////////////
793/// Handle DND finished event.
794
796{
798 return kTRUE;
799}
800
801////////////////////////////////////////////////////////////////////////////////
802/// Handle selection request event.
803
805{
806 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
807 Event_t xevent;
808 TDNDData *dnddata = 0;
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
828 xevent.fType = kSelectionNotify;
829 xevent.fTime = event->fTime;
830 xevent.fUser[0] = event->fUser[0]; // requestor
831 xevent.fUser[1] = event->fUser[1]; // selection
832 xevent.fUser[2] = event->fUser[2]; // target;
833 xevent.fUser[3] = event->fUser[3]; // property;
834 gVirtualX->SendEvent(event->fUser[0], &xevent);
835
836 return kTRUE;
837 } else {
838 return kFALSE; // not for us...
839 }
840}
841
842////////////////////////////////////////////////////////////////////////////////
843/// Handle selection event.
844
846{
847 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
848 Atom_t actual = fDropType;
849 Int_t format = 8;
850 ULong_t count, remaining;
851 unsigned char *data = 0;
852
853
854 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
855 0, 0x8000000L, kTRUE, event->fUser[2],
856 &actual, &format, &count, &remaining, &data);
857
858 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
859 if (data) delete[] data;
860
861 return kFALSE;
862 }
863
865
866 // send the data to the target widget
867
868 if (fLocalTarget) {
869 TDNDData dndData(actual, data, count, fLocalAction);
870 fLocalTarget->HandleDNDDrop(&dndData);
871 if (fDraggerTypes) delete[] fDraggerTypes;
872 fDraggerTypes = 0;
873 }
874
875 fSource = kNone;
877
878// delete[] data;
879
880 return kTRUE;
881
882 } else {
883 return kFALSE; // not for us...
884 }
885}
886
887////////////////////////////////////////////////////////////////////////////////
888/// Set drag window pixmaps and hotpoint.
889
891 int hot_x, int hot_y)
892{
893 fPic = pic;
894 fMask = mask;
895 fHotx = hot_x;
896 fHoty = hot_y;
897}
898
899////////////////////////////////////////////////////////////////////////////////
900/// Start dragging.
901
902Bool_t TGDNDManager::StartDrag(TGFrame *src, int x_root, int y_root,
903 Window_t grabWin)
904{
905 if (fDragging) return kTRUE;
906
907 fLocalSource = src;
908
909 if ((TGWindow *)fMain != src->GetMainFrame()) {
910 fMain = (TGFrame *)src->GetMainFrame();
911 }
912
913 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
914 // hmmm... failed to acquire ownership of XdndSelection!
915 return kFALSE;
916 }
917
918 if (grabWin == kNone) grabWin = fMain->GetId();
919
920 gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
921
922 fLocalTarget = 0;
924 fTarget = kNone;
927 if (fDropTimeout) delete fDropTimeout;
928 fDropTimeout = 0;
932
933 if (!fDragWin && fPic != kNone && fMask != kNone) {
934 fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
935 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
938 }
939 return kTRUE;
940}
941
942////////////////////////////////////////////////////////////////////////////////
943/// Drop.
944
946{
947 if (!fDragging) return kFALSE;
948
949 if (fTargetIsDNDAware) {
950 if (fDropAccepted) {
951 if (fStatusPending) {
952 if (fDropTimeout) delete fDropTimeout;
953 fDropTimeout = new TTimer(this, 5000);
954 } else {
956 }
957 } else {
960 }
961 }
962 EndDrag();
963 return kTRUE;
964}
965
966////////////////////////////////////////////////////////////////////////////////
967/// End dragging.
968
970{
971 if (!fDragging) return kFALSE;
972
973 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
974
975 if (fSource)
977 if (fLocalSource)
979
981 if (fDragWin) {
983 fDragWin = 0;
984 }
985 return kTRUE;
986}
987
988////////////////////////////////////////////////////////////////////////////////
989/// Process drag event.
990
991Bool_t TGDNDManager::Drag(int x_root, int y_root, Atom_t action, Time_t timestamp)
992{
993 if (!fDragging) return kFALSE;
994
995 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
996 x_root, y_root, 15);
997
998 if (newTarget == kNone) {
1000 if (t != kNone) newTarget = t;
1001 }
1002
1003 if (fTarget != newTarget) {
1004
1006
1007 fTarget = newTarget;
1012
1014
1015 if (fDragWin)
1016 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
1018 }
1019
1021 SendDNDPosition(fTarget, x_root, y_root, action, timestamp);
1022
1023 // this is to avoid sending XdndPosition messages over and over
1024 // if the target is not responding
1026 }
1027
1028 if (fDragWin) {
1030 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
1031 }
1032 return kTRUE;
1033}
1034
1035////////////////////////////////////////////////////////////////////////////////
1036/// Set root window proxy.
1037
1039{
1040 Window_t mainw = fMain->GetId();
1041 int result = kFALSE;
1042
1043 if (GetRootProxy() == kNone) {
1044 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
1045 fgDNDProxy, XA_WINDOW, 32,
1046 (unsigned char *) &mainw, 1);
1047 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
1048 (unsigned char *) &mainw, 1);
1049
1050 fProxyOurs = kTRUE;
1051 result = kTRUE;
1052 }
1053 // XSync(_dpy, kFALSE);
1054 gVirtualX->UpdateWindow(0);
1055 return result;
1056}
1057
1058////////////////////////////////////////////////////////////////////////////////
1059/// Remove root window proxy.
1060
1062{
1063 if (!fProxyOurs) return kFALSE;
1064
1065 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
1066 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
1067 // the following is to ensure that the properties
1068 // (specially the one on the root window) are deleted
1069 // in case the application is exiting...
1070
1071 // XSync(_dpy, kFALSE);
1072 gVirtualX->UpdateWindow(0);
1073
1075
1076 return kTRUE;
1077}
@ 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
#define a(i)
Definition RSha256.hxx:99
const Bool_t kFALSE
Definition RtypesCore.h:92
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:91
#define ClassImp(name)
Definition Rtypes.h:364
#define gClient
Definition TGClient.h:166
TGDNDManager * gDNDManager
#define ROOTDND_PROTOCOL_VERSION
static int ArrayLength(Atom_t *a)
R__EXTERN TGDNDManager * gDNDManager
int type
Definition TGX11.cxx:121
#define gVirtualX
Definition TVirtualX.h:338
Atom_t fDataType
Int_t fDataLength
void * fData
static Atom_t fgDNDAware
static Atom_t fgDNDVersion
Bool_t HandleDNDEnter(Window_t src, long vers, Atom_t dataTypes[3])
Handle DND enter event.
virtual ~TGDNDManager()
TGDNDManager destructor.
static Atom_t fgDNDActionPrivate
Window_t fSource
static Atom_t fgDNDActionAsk
static Atom_t GetDNDDrop()
static Atom_t GetDNDActionAsk()
TGFrame * fMain
static Atom_t fgDNDActionMove
Pixmap_t fMask
Bool_t HandleSelectionRequest(Event_t *event)
Handle selection request event.
static Atom_t fgDNDActionLink
Bool_t HandleClientMessage(Event_t *event)
Handle DND related client messages.
TTimer * fDropTimeout
static Atom_t fgDNDActionDescrip
void SendDNDEnter(Window_t target)
Send DND enter message to target window.
static Atom_t fgDNDSelection
Bool_t fTargetIsDNDAware
Bool_t fStatusPending
TGDNDManager(const TGDNDManager &)=delete
void InitAtoms()
Initialize drag and drop atoms.
static Atom_t fgDNDFinished
Atom_t fDropType
static Atom_t fgDNDDrop
static Atom_t GetXCDNDData()
static Atom_t GetDNDVersion()
Bool_t fProxyOurs
static Atom_t GetDNDActionLink()
static Atom_t fgDNDEnter
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
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
TGFrame * fLocalSource
static Atom_t GetDNDTypeList()
static Bool_t fgInit
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
void SendDNDStatus(Window_t target, Atom_t action)
Send DND status message to source window.
Bool_t fDragging
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
UInt_t fGrabEventMask
Bool_t fDropAccepted
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
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
Bool_t Drag(Int_t x_root, Int_t y_root, Atom_t action, Time_t timestamp)
Process drag event.
TGFrame * fLocalTarget
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
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
Atom_t * fTypelist
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
virtual TGDimension GetDefaultSize() const
std::cout << fWidth << "x" << fHeight << std::endl;
TGDragWindow(const TGWindow *p, Pixmap_t pic, Pixmap_t mask, UInt_t options=kChildFrame, Pixel_t back=GetWhitePixel())
TGDragWindow constructor.
Window_t GetInputId() const
virtual void LowerWindow()
Lower TGDragWindow.
Window_t fInput
Pixmap_t fMask
Pixmap_t fPic
static Cursor_t fgDefaultCursor
virtual void MapWindow()
Map TGDragWindow.
virtual Atom_t HandleDNDEnter(Atom_t *)
Definition TGFrame.h:303
virtual Atom_t HandleDNDPosition(Int_t, Int_t, Atom_t, Int_t, Int_t)
Definition TGFrame.h:301
virtual Bool_t HandleDNDDrop(TDNDData *)
Definition TGFrame.h:300
virtual void MapRaised()
map raised
Definition TGFrame.h:229
UInt_t fHeight
Definition TGFrame.h:112
virtual Bool_t HandleDNDFinished()
Definition TGFrame.h:305
virtual void DeleteWindow()
Delete window.
Definition TGFrame.cxx:261
virtual Bool_t HandleDNDLeave()
Definition TGFrame.h:304
virtual void Move(Int_t x, Int_t y)
Move frame.
Definition TGFrame.cxx:578
virtual TDNDData * GetDNDData(Atom_t)
Definition TGFrame.h:299
virtual void Resize(UInt_t w=0, UInt_t h=0)
Resize the frame.
Definition TGFrame.cxx:590
UInt_t fWidth
Definition TGFrame.h:111
virtual void MapWindow()
map window
Definition TGFrame.h:228
virtual void MapSubwindows()
map sub windows
Definition TGFrame.h:224
static const TGGC & GetBckgndGC()
Get background color graphics context.
Definition TGFrame.cxx:760
virtual void UnmapWindow()
unmap window
Definition TGFrame.h:230
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:151
virtual void LowerWindow()
lower window
Definition TGWindow.cxx:215
virtual void RaiseWindow()
raise window
Definition TGWindow.cxx:207
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
int main()
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
Long_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
Time_t fTime
time event event occurred in ms
Definition GuiTypes.h:177
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
#define XA_ATOM
Definition xatom.h:13
#define XA_WINDOW
Definition xatom.h:42