Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGDNDManager.cxx
Go to the documentation of this file.
1// @(#)root/gui:$Id$
2// Author: Bertrand Bellenot 19/04/07
3
4/*************************************************************************
5 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TGFrame.h"
13#include "TTimer.h"
14#include "TGDNDManager.h"
15#include "TRootCanvas.h"
16#include "TVirtualX.h"
17
18
19#define ROOTDND_PROTOCOL_VERSION 4
20#define XA_ATOM ((Atom_t) 4)
21#define XA_WINDOW ((Atom_t) 33)
22
26
34
40
44
47
49
50// TODO:
51// - add an TGFrame::HandleDNDStatus event handler?
52// - implement INCR protocol
53// - cache several requests?
54
56
58
59
60/** \class TGDragWindow
61 \ingroup guiwidgets
62
63Window used as drag icon during drag and drop operations.
64
65*/
66
67
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 Atom_t action = (Atom_t)event->fUser[4] ? event->fUser[4] : 1;
429 (Int_t)(event->fUser[2] >> 16) & 0xFFFF, // x_root
430 (Int_t)(event->fUser[2] & 0xFFFF), // y_root
431 (Atom_t)action, // action
432 (Time_t)event->fUser[3]); // timestamp
433
434 } else if (event->fHandle == fgDNDStatus) {
435 Rectangle_t skip;
436 skip.fX = (event->fUser[2] >> 16) & 0xFFFF;
437 skip.fY = (event->fUser[2] & 0xFFFF);
438 skip.fWidth = (event->fUser[3] >> 16) & 0xFFFF;
439 skip.fHeight = (event->fUser[3] & 0xFFFF);
440
441 HandleDNDStatus((Window_t) event->fUser[0],
442 (int) (event->fUser[1] & 0x1),
443 skip, (Atom_t) event->fUser[4]);
444
445 } else if (event->fHandle == fgDNDDrop) {
446 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
447
448 } else if (event->fHandle == fgDNDFinished) {
449 HandleDNDFinished((Window_t) event->fUser[0]);
450
451 } else {
452 return kFALSE; // not for us...
453 }
454 return kTRUE;
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Handle Drop timeout.
459
461{
462 if (t == fDropTimeout) {
463 // The drop operation timed out without receiving
464 // status confirmation from the target. Send a
465 // leave message instead (and notify the user or widget).
466 delete fDropTimeout;
467 fDropTimeout = 0;
468
471
473 return kTRUE;
474 }
475 return kFALSE;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Send DND enter message to target window.
480
482{
483 Int_t i, n;
485
486 event.fType = kClientMessage;
487 event.fWindow = target;
488 event.fHandle = fgDNDEnter;
489 event.fFormat = 32;
490
491 event.fUser[0] = fMain->GetId(); // from;
492
494
495 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
496
497 // set the first 1-3 data types
498
499 for (i = 0; i < 3; ++i)
500 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
501
502 if (fLocalSource) {
503 TDNDData *dnddata = 0;
504 Atom_t dataType;
505
506 // get the data type from the drag source widget
507 if (fLocalSource)
508 dnddata = fLocalSource->GetDNDData(0);
509 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
510 event.fUser[2] = dataType;
511 event.fUser[3] = kNone;
512 event.fUser[4] = kNone;
513 }
514
515 gVirtualX->SendEvent(target, &event);
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Send DND leave message to target window.
520
522{
524
525 event.fType = kClientMessage;
526 event.fWindow = target;
527 event.fHandle = fgDNDLeave;
528 event.fFormat = 32;
529
530 event.fUser[0] = fMain->GetId(); // from;
531 event.fUser[1] = 0L;
532
533 event.fUser[2] = 0L;
534 event.fUser[3] = 0L;
535 event.fUser[4] = 0L;
536
537 gVirtualX->SendEvent(target, &event);
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Send DND position message to target window.
542
544 Atom_t action, Time_t timestamp)
545{
547
548 event.fType = kClientMessage;
549 event.fWindow = target;
550 event.fHandle = fgDNDPosition;
551 event.fFormat = 32;
552
553 event.fUser[0] = fMain->GetId(); // from;
554 event.fUser[1] = 0L;
555
556 event.fUser[2] = (x << 16) | y; // root coordinates
557 event.fUser[3] = timestamp; // timestamp for retrieving data
558 event.fUser[4] = action; // requested action
559
560 gVirtualX->SendEvent(target, &event);
561}
562
563////////////////////////////////////////////////////////////////////////////////
564/// Send DND status message to source window.
565
567{
569
570 event.fType = kClientMessage;
571 event.fWindow = source;
572 event.fHandle = fgDNDStatus;
573 event.fFormat = 32;
574
575 event.fUser[0] = fMain->GetId(); // from;
576 event.fUser[1] = (action == kNone) ? 0L : 1L;
577
578 event.fUser[2] = 0L; // empty rectangle
579 event.fUser[3] = 0L;
580 event.fUser[4] = action; // accepted action
581
582 gVirtualX->SendEvent(source, &event);
583}
584
585////////////////////////////////////////////////////////////////////////////////
586/// Send DND drop message to target window.
587
589{
591
592 event.fType = kClientMessage;
593 event.fWindow = target;
594 event.fHandle = fgDNDDrop;
595 event.fFormat = 32;
596
597 event.fUser[0] = fMain->GetId(); // from;
598 event.fUser[1] = 0L; // reserved
599 event.fUser[2] = 0L; //CurrentTime; // timestamp
600 event.fUser[3] = 0L;
601 event.fUser[4] = 0L;
602
603 gVirtualX->SendEvent(target, &event);
604}
605
606////////////////////////////////////////////////////////////////////////////////
607/// Send DND finished message to source window.
608
610{
612
613 event.fType = kClientMessage;
614 event.fWindow = source;
615 event.fHandle = fgDNDFinished;
616 event.fFormat = 32;
617
618 event.fUser[0] = fMain->GetId(); // from;
619 event.fUser[1] = 0L; // reserved
620 event.fUser[2] = 0L;
621 event.fUser[3] = 0L;
622 event.fUser[4] = 0L;
623
624 gVirtualX->SendEvent(source, &event);
625}
626
627////////////////////////////////////////////////////////////////////////////////
628/// Handle DND enter event.
629
631{
632 fSource = src;
633
634 if (fDraggerTypes) delete[] fDraggerTypes;
635
636 if (vers & 1) { // more than 3 data types?
637 Atom_t type, *a;
638 Int_t format = 32;
639 ULong_t i, count, remaining;
640 unsigned char *data = 0;
641
642 gVirtualX->GetProperty(src, fgDNDTypeList,
643 0, 0x8000000L, kFALSE, XA_ATOM,
644 &type, &format, &count, &remaining, &data);
645
646 if (type != XA_ATOM || format != 32 || !data) {
647 count = 0;
648 }
649
650 fDraggerTypes = new Atom_t[count+4];
651
652 a = (Atom_t *) data;
653 for (i = 0; i < count; i++)
654 fDraggerTypes[i] = a[i];
655
656 fDraggerTypes[i] = kNone;
657
658 if (data) delete[] data;
659
660 } else {
661 fDraggerTypes = new Atom_t[4];
662
663 fDraggerTypes[0] = dataTypes[0];
664 fDraggerTypes[1] = dataTypes[1];
665 fDraggerTypes[2] = dataTypes[2];
666
667 fDraggerTypes[3] = kNone;
668 }
669
670 // the following is not strictly necessary, unless the previous
671 // dragging application crashed without sending XdndLeave
673 fLocalTarget = 0;
674
675 return kTRUE;
676}
677
678////////////////////////////////////////////////////////////////////////////////
679/// Handle DND leave event.
680
682{
683 fSource = kNone;
685 fLocalTarget = 0;
686
687 if (fDraggerTypes) delete[] fDraggerTypes;
688 fDraggerTypes = 0;
689
690 return kTRUE;
691}
692
693////////////////////////////////////////////////////////////////////////////////
694/// Handle DND position event.
695
697 Atom_t action, Time_t /*timestamp*/)
698{
699 Int_t x = 0, y = 0;
700 Window_t child;
701 TGFrame *f = 0, *main = 0;
702 TGWindow *w = 0;
703 Window_t wtarget = 0;
704
705 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
706
707 if (wtarget) {
708 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
709 wtarget, x_root, y_root, x, y, child);
710 w = gClient->GetWindowById(wtarget);
711 if (w)
712 f = dynamic_cast<TGFrame *>(w);
713 }
714
715 if (f != fLocalTarget) {
717 fLocalTarget = f;
718 if (fLocalTarget) {
720 main->RaiseWindow();
721 if (fMain == 0)
722 fMain = main;
724 }
725 }
726 // query the target widget to determine whether it accepts the
727 // required action
728 if (fLocalTarget) {
729 action = (fDropType == kNone) ? kNone :
730 fLocalTarget->HandleDNDPosition(x, y, action, x_root, y_root);
731 } else if (fProxyOurs) {
732 action = fMain->HandleDNDPosition(x, y, action, x_root, y_root);
733 } else {
734 action = kNone;
735 }
736 SendDNDStatus(source, fLocalAction = action);
737 return kTRUE;
738}
739
740////////////////////////////////////////////////////////////////////////////////
741/// Handle DND status event.
742
744 Rectangle_t /*area*/, Atom_t action)
745{
746 if (target) {
748 if (accepted) {
750 fAcceptedAction = action;
751 if (fDragWin)
752 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
754 } else {
757 if (fDragWin)
758 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
761 }
762 if (fDropTimeout) { // were we waiting for this to do the drop?
763 delete fDropTimeout;
764 fDropTimeout = 0;
766 }
767 }
768 return kTRUE;
769}
770
771////////////////////////////////////////////////////////////////////////////////
772/// Handle DND drop event.
773
775{
776 // to get the data, we must call XConvertSelection with
777 // the timestamp in XdndDrop, wait for SelectionNotify
778 // to arrive to retrieve the data, and when we are finished,
779 // send a XdndFinished message to the source.
780
781 if (fMain && fDropType != kNone) {
782 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
783 8, (unsigned char *) 0, 0);
784
785 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
786 fgXCDNDData, timestamp);
787 }
788
789 fSource = source;
790 if (fMain) SendDNDFinished(source);
791
792 return kTRUE;
793}
794
795////////////////////////////////////////////////////////////////////////////////
796/// Handle DND finished event.
797
799{
801 return kTRUE;
802}
803
804////////////////////////////////////////////////////////////////////////////////
805/// Handle selection request event.
806
808{
809 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
810 Event_t xevent;
811 TDNDData *dnddata = 0;
812 char *data;
813 int len;
814
815 // get the data from the drag source widget
816 if (fLocalSource)
817 dnddata = fLocalSource->GetDNDData(event->fUser[2]);
818
819 data = dnddata ? (char *) dnddata->fData : (char *) "";
820 len = dnddata ? dnddata->fDataLength : 0;
821
822 if ((Atom_t)event->fUser[3] == kNone) {
823 //printf("warning: kNone property specified in SelectionRequest\n");
824 event->fUser[3] = fgXCDNDData;
825 }
826
827 gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
828 event->fUser[2], 8,
829 (unsigned char *) data, len);
830#ifndef R__WIN32
831 xevent.fType = kSelectionNotify;
832 xevent.fTime = event->fTime;
833 xevent.fUser[0] = event->fUser[0]; // requestor
834 xevent.fUser[1] = event->fUser[1]; // selection
835 xevent.fUser[2] = event->fUser[2]; // target;
836 xevent.fUser[3] = event->fUser[3]; // property;
837 gVirtualX->SendEvent(event->fUser[0], &xevent);
838#endif
839 return kTRUE;
840 } else {
841 return kFALSE; // not for us...
842 }
843}
844
845////////////////////////////////////////////////////////////////////////////////
846/// Handle selection event.
847
849{
850 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
851 Atom_t actual = fDropType;
852 Int_t format = 8;
853 ULong_t count, remaining;
854 unsigned char *data = 0;
855
856
857 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
858 0, 0x8000000L, kTRUE, event->fUser[2],
859 &actual, &format, &count, &remaining, &data);
860
861 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
862 if (data) delete[] data;
863
864 return kFALSE;
865 }
866
868
869 // send the data to the target widget
870
871 if (fLocalTarget) {
872 TDNDData dndData(actual, data, count, fLocalAction);
873 fLocalTarget->HandleDNDDrop(&dndData);
874 if (fDraggerTypes) delete[] fDraggerTypes;
875 fDraggerTypes = 0;
876 }
877
878 fSource = kNone;
880
881// delete[] data;
882
883 return kTRUE;
884
885 } else {
886 return kFALSE; // not for us...
887 }
888}
889
890////////////////////////////////////////////////////////////////////////////////
891/// Set drag window pixmaps and hotpoint.
892
894 int hot_x, int hot_y)
895{
896 fPic = pic;
897 fMask = mask;
898 fHotx = hot_x;
899 fHoty = hot_y;
900}
901
902////////////////////////////////////////////////////////////////////////////////
903/// Start dragging.
904
905Bool_t TGDNDManager::StartDrag(TGFrame *src, int x_root, int y_root,
906 Window_t grabWin)
907{
908 if (fDragging) return kTRUE;
909
910 fLocalSource = src;
911
912 if ((TGWindow *)fMain != src->GetMainFrame()) {
913 fMain = (TGFrame *)src->GetMainFrame();
914 }
915
916 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
917 // hmmm... failed to acquire ownership of XdndSelection!
918 return kFALSE;
919 }
920
921 if (grabWin == kNone) grabWin = fMain->GetId();
922
923 gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
924
925 fLocalTarget = 0;
927 fTarget = kNone;
930 if (fDropTimeout) delete fDropTimeout;
931 fDropTimeout = 0;
935
936 if (!fDragWin && fPic != kNone && fMask != kNone) {
937 fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
938 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
941 }
942 return kTRUE;
943}
944
945////////////////////////////////////////////////////////////////////////////////
946/// Drop.
947
949{
950 if (!fDragging) return kFALSE;
951
952 if (fTargetIsDNDAware) {
953 if (fDropAccepted) {
954 if (fStatusPending) {
955 if (fDropTimeout) delete fDropTimeout;
956 fDropTimeout = new TTimer(this, 5000);
957 } else {
959 }
960 } else {
963 }
964 }
965 EndDrag();
966 return kTRUE;
967}
968
969////////////////////////////////////////////////////////////////////////////////
970/// End dragging.
971
973{
974 if (!fDragging) return kFALSE;
975
976 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
977
978 if (fSource)
980 if (fLocalSource)
982
984 if (fDragWin) {
986 fDragWin = 0;
987 }
988 return kTRUE;
989}
990
991////////////////////////////////////////////////////////////////////////////////
992/// Process drag event.
993
994Bool_t TGDNDManager::Drag(int x_root, int y_root, Atom_t action, Time_t timestamp)
995{
996 if (!fDragging) return kFALSE;
997
998 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
999 x_root, y_root, 15);
1000
1001 if (newTarget == kNone) {
1002 Window_t t = GetRootProxy();
1003 if (t != kNone) newTarget = t;
1004 }
1005
1006 if (fTarget != newTarget) {
1007
1009
1010 fTarget = newTarget;
1015
1017
1018 if (fDragWin)
1019 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
1021 }
1022
1024 SendDNDPosition(fTarget, x_root, y_root, action, timestamp);
1025
1026 // this is to avoid sending XdndPosition messages over and over
1027 // if the target is not responding
1029 }
1030
1031 if (fDragWin) {
1033 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
1034 }
1035 return kTRUE;
1036}
1037
1038////////////////////////////////////////////////////////////////////////////////
1039/// Set root window proxy.
1040
1042{
1043 Window_t mainw = fMain->GetId();
1044 int result = kFALSE;
1045
1046 if (GetRootProxy() == kNone) {
1047 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
1048 fgDNDProxy, XA_WINDOW, 32,
1049 (unsigned char *) &mainw, 1);
1050 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
1051 (unsigned char *) &mainw, 1);
1052
1053 fProxyOurs = kTRUE;
1054 result = kTRUE;
1055 }
1056 // XSync(_dpy, kFALSE);
1057 gVirtualX->UpdateWindow(0);
1058 return result;
1059}
1060
1061////////////////////////////////////////////////////////////////////////////////
1062/// Remove root window proxy.
1063
1065{
1066 if (!fProxyOurs) return kFALSE;
1067
1068 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
1069 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
1070 // the following is to ensure that the properties
1071 // (specially the one on the root window) are deleted
1072 // in case the application is exiting...
1073
1074 // XSync(_dpy, kFALSE);
1075 gVirtualX->UpdateWindow(0);
1076
1078
1079 return kTRUE;
1080}
@ 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
int main()
Definition Prototype.cxx:12
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
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
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
Drag and drop data container.
Atom_t fDataType
Data type description.
Int_t fDataLength
Length of data.
void * fData
Actual data.
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
pointer on TGMainFrame
static Atom_t fgDNDActionMove
Pixmap_t fMask
pixmap used for the drag window
Bool_t HandleSelectionRequest(Event_t *event)
Handle selection request event.
static Atom_t fgDNDActionLink
Int_t fHoty
hot point coordinates
Bool_t HandleClientMessage(Event_t *event)
Handle DND related client messages.
TTimer * fDropTimeout
drop timeout
static Atom_t fgDNDActionDescrip
void SendDNDEnter(Window_t target)
Send DND enter message to target window.
static Atom_t fgDNDSelection
Bool_t fTargetIsDNDAware
kTRUE if target is DND aware
Bool_t fStatusPending
kTRUE if status is pending
TGDNDManager(const TGDNDManager &)=delete
void InitAtoms()
Initialize drag and drop atoms.
static Atom_t fgDNDFinished
Atom_t fDropType
drop type
static Atom_t fgDNDDrop
static Atom_t GetXCDNDData()
static Atom_t GetDNDVersion()
Bool_t fProxyOurs
kTRUE if root proxy is ours
static Atom_t GetDNDActionLink()
static Atom_t fgDNDEnter
Bool_t 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
static Atom_t fgXCDNDData
Bool_t HandleDNDFinished(Window_t target)
Handle DND finished event.
static Atom_t fgDNDPosition
static Atom_t fgDNDLeave
Bool_t HandleSelection(Event_t *event)
Handle selection event.
Atom_t fLocalAction
accepted and local actions
TGFrame * fLocalSource
static Atom_t GetDNDTypeList()
static Bool_t fgInit
Window_t GetRootProxy()
Get root window proxy.
Bool_t HandleDNDStatus(Window_t from, int accepted, Rectangle_t skip, Atom_t action)
Handle DND status event.
static Atom_t fgDNDActionCopy
static Atom_t GetDNDProxy()
static Atom_t fgDNDProxy
static Atom_t GetDNDActionDescrip()
Bool_t StartDrag(TGFrame *src, Int_t x_root, Int_t y_root, Window_t grabWin=kNone)
Start dragging.
Bool_t fUseVersion
kTRUE if DND version is used
void SendDNDStatus(Window_t target, Atom_t action)
Send DND status message to source window.
Bool_t fDragging
kTRUE while dragging
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
pointer grab event mask
Bool_t fDropAccepted
kTRUE if drop accepted
static Atom_t GetDNDActionList()
Window_t FindWindow(Window_t root, Int_t x, Int_t y, Int_t maxd)
Search for DND aware window at position x,y.
static Atom_t fgDNDTypeList
Atom_t fVersion
not really an Atom, but a long
Bool_t RemoveRootProxy()
Remove root window proxy.
static Atom_t GetDNDEnter()
Bool_t HandleDNDPosition(Window_t src, int x_root, int y_root, Atom_t action, Time_t timestamp)
Handle DND position event.
static Atom_t fgXAWMState
Pixmap_t fPic
void SendDNDPosition(Window_t target, int x, int y, Atom_t action, Time_t timestamp)
Send DND position message to target window.
void SendDNDFinished(Window_t src)
Send DND finished message to source window.
Cursor_t fDNDNoDropCursor
no drop cursor type
Bool_t Drag(Int_t x_root, Int_t y_root, Atom_t action, Time_t timestamp)
Process drag event.
TGFrame * fLocalTarget
local source and target
void SendDNDDrop(Window_t target)
Send DND drop message to target window.
static Atom_t GetDNDPosition()
static Atom_t GetDNDActionPrivate()
static Atom_t fgDNDStatus
Window_t fTarget
source and target windows
Bool_t HandleDNDLeave(Window_t src)
Handle DND leave event.
Atom_t fAcceptedAction
void SendDNDLeave(Window_t target)
Send DND leave message to target window.
TGDragWindow * fDragWin
drag window
Atom_t * fTypelist
Bool_t Drop()
Drop.
Bool_t SetRootProxy()
Set root window proxy.
static Atom_t GetDNDActionCopy()
Bool_t EndDrag()
End dragging.
static Atom_t GetDNDActionMove()
static Atom_t GetDNDLeave()
Window used as drag icon during drag and drop operations.
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
Input Window.
Pixmap_t fMask
Pixmaps used as Window shape.
Pixmap_t fPic
UInt_t fPh
Hot point coordinates (x and y)
static Cursor_t fgDefaultCursor
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
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
#define XA_ATOM
Definition xatom.h:13
#define XA_WINDOW
Definition xatom.h:42