17 #define ROOTDND_PROTOCOL_VERSION 4
18 #define XA_ATOM ((Atom_t) 4)
19 #define XA_WINDOW ((Atom_t) 33)
21 Atom_t TGDNDManager::fgDNDAware = kNone;
22 Atom_t TGDNDManager::fgDNDSelection = kNone;
23 Atom_t TGDNDManager::fgDNDProxy = kNone;
25 Atom_t TGDNDManager::fgDNDEnter = kNone;
26 Atom_t TGDNDManager::fgDNDLeave = kNone;
27 Atom_t TGDNDManager::fgDNDPosition = kNone;
28 Atom_t TGDNDManager::fgDNDStatus = kNone;
29 Atom_t TGDNDManager::fgDNDDrop = kNone;
30 Atom_t TGDNDManager::fgDNDFinished = kNone;
31 Atom_t TGDNDManager::fgDNDVersion = kNone;
33 Atom_t TGDNDManager::fgDNDActionCopy = kNone;
34 Atom_t TGDNDManager::fgDNDActionMove = kNone;
35 Atom_t TGDNDManager::fgDNDActionLink = kNone;
36 Atom_t TGDNDManager::fgDNDActionAsk = kNone;
37 Atom_t TGDNDManager::fgDNDActionPrivate = kNone;
39 Atom_t TGDNDManager::fgDNDTypeList = kNone;
40 Atom_t TGDNDManager::fgDNDActionList = kNone;
41 Atom_t TGDNDManager::fgDNDActionDescrip = kNone;
43 Atom_t TGDNDManager::fgXAWMState = kNone;
44 Atom_t TGDNDManager::fgXCDNDData = kNone;
46 Bool_t TGDNDManager::fgInit = kFALSE;
53 TGDNDManager *gDNDManager = 0;
55 Cursor_t TGDragWindow::fgDefaultCursor = kNone;
64 ClassImp(TGDragWindow);
69 TGDragWindow::TGDragWindow(
const TGWindow *p, Pixmap_t pic, Pixmap_t mask,
70 UInt_t options, Pixel_t back) :
71 TGFrame(p, 32, 32, options, back)
73 if (fgDefaultCursor == kNone) {
74 fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
80 SetWindowAttributes_t wattr;
82 wattr.fMask = kWAOverrideRedirect | kWASaveUnder;
83 wattr.fSaveUnder = kTRUE;
84 wattr.fOverrideRedirect = kTRUE;
86 gVirtualX->ChangeWindowAttributes(fId, &wattr);
90 gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
92 wattr.fMask = kWAOverrideRedirect;
93 wattr.fOverrideRedirect = kTRUE;
104 Resize(GetDefaultSize());
106 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
108 gVirtualX->SetCursor(fId, fgDefaultCursor);
114 TGDragWindow::~TGDragWindow()
122 void TGDragWindow::MapWindow()
124 TGFrame::MapWindow();
131 void TGDragWindow::UnmapWindow()
133 TGFrame::UnmapWindow();
140 void TGDragWindow::RaiseWindow()
142 TGFrame::RaiseWindow();
149 void TGDragWindow::LowerWindow()
152 TGFrame::LowerWindow();
158 void TGDragWindow::MapRaised()
160 TGFrame::MapRaised();
167 void TGDragWindow::Layout()
169 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
175 void TGDragWindow::DoRedraw()
177 gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
187 ClassImp(TGDNDManager);
192 TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t * )
199 fVersion = ROOTDND_PROTOCOL_VERSION;
202 fTypelist =
new Atom_t[3];
203 fTypelist[0] = gVirtualX->InternAtom(
"application/root", kFALSE);
204 fTypelist[1] = gVirtualX->InternAtom(
"text/uri-list", kFALSE);
217 fTargetIsDNDAware = kFALSE;
218 fStatusPending = kFALSE;
219 fDropAccepted = kFALSE;
220 fAcceptedAction = kNone;
221 fLocalAction = kNone;
226 fPic = fMask = kNone;
231 fGrabEventMask = kButtonPressMask | kButtonReleaseMask | kButtonMotionMask;
233 fDNDNoDropCursor = gVirtualX->CreateCursor(kNoDrop);
244 TGDNDManager::~TGDNDManager()
252 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDAware);
253 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDTypeList);
255 if (fDropTimeout)
delete fDropTimeout;
259 fDragWin->DeleteWindow();
262 if (fPic != kNone) gVirtualX->DeletePixmap(fPic);
263 if (fMask != kNone) gVirtualX->DeletePixmap(fMask);
265 if (fDraggerTypes)
delete[] fDraggerTypes;
266 if (fTypelist)
delete[] fTypelist;
269 Atom_t TGDNDManager::GetDNDAware() {
return fgDNDAware; }
270 Atom_t TGDNDManager::GetDNDSelection() {
return fgDNDSelection; }
271 Atom_t TGDNDManager::GetDNDProxy() {
return fgDNDProxy; }
272 Atom_t TGDNDManager::GetDNDEnter() {
return fgDNDEnter; }
273 Atom_t TGDNDManager::GetDNDLeave() {
return fgDNDLeave; }
274 Atom_t TGDNDManager::GetDNDPosition() {
return fgDNDPosition; }
275 Atom_t TGDNDManager::GetDNDStatus() {
return fgDNDStatus; }
276 Atom_t TGDNDManager::GetDNDDrop() {
return fgDNDDrop; }
277 Atom_t TGDNDManager::GetDNDFinished() {
return fgDNDFinished; }
278 Atom_t TGDNDManager::GetDNDVersion() {
return fgDNDVersion; }
279 Atom_t TGDNDManager::GetDNDActionCopy() {
return fgDNDActionCopy; }
280 Atom_t TGDNDManager::GetDNDActionMove() {
return fgDNDActionMove; }
281 Atom_t TGDNDManager::GetDNDActionLink() {
return fgDNDActionLink; }
282 Atom_t TGDNDManager::GetDNDActionAsk() {
return fgDNDActionAsk; }
283 Atom_t TGDNDManager::GetDNDActionPrivate() {
return fgDNDActionPrivate; }
284 Atom_t TGDNDManager::GetDNDTypeList() {
return fgDNDTypeList; }
285 Atom_t TGDNDManager::GetDNDActionList() {
return fgDNDActionList; }
286 Atom_t TGDNDManager::GetDNDActionDescrip() {
return fgDNDActionDescrip; }
287 Atom_t TGDNDManager::GetXCDNDData() {
return fgXCDNDData; }
292 void TGDNDManager::InitAtoms()
295 fgDNDAware = gVirtualX->InternAtom(
"XdndAware", kFALSE);
298 fgDNDSelection = gVirtualX->InternAtom(
"XdndSelection", kFALSE);
301 fgDNDProxy = gVirtualX->InternAtom(
"XdndProxy", kFALSE);
304 fgDNDEnter = gVirtualX->InternAtom(
"XdndEnter", kFALSE);
305 fgDNDLeave = gVirtualX->InternAtom(
"XdndLeave", kFALSE);
306 fgDNDPosition = gVirtualX->InternAtom(
"XdndPosition", kFALSE);
307 fgDNDStatus = gVirtualX->InternAtom(
"XdndStatus", kFALSE);
308 fgDNDDrop = gVirtualX->InternAtom(
"XdndDrop", kFALSE);
309 fgDNDFinished = gVirtualX->InternAtom(
"XdndFinished", kFALSE);
312 fgDNDActionCopy = gVirtualX->InternAtom(
"XdndActionCopy", kFALSE);
313 fgDNDActionMove = gVirtualX->InternAtom(
"XdndActionMove", kFALSE);
314 fgDNDActionLink = gVirtualX->InternAtom(
"XdndActionLink", kFALSE);
315 fgDNDActionAsk = gVirtualX->InternAtom(
"XdndActionAsk", kFALSE);
316 fgDNDActionPrivate = gVirtualX->InternAtom(
"XdndActionPrivate", kFALSE);
319 fgDNDTypeList = gVirtualX->InternAtom(
"XdndTypeList", kFALSE);
320 fgDNDActionList = gVirtualX->InternAtom(
"XdndActionList", kFALSE);
321 fgDNDActionDescrip = gVirtualX->InternAtom(
"XdndActionDescription", kFALSE);
324 fgXAWMState = gVirtualX->InternAtom(
"WM_STATE", kFALSE);
325 fgXCDNDData = gVirtualX->InternAtom(
"_XC_DND_DATA", kFALSE);
328 static int ArrayLength(Atom_t *a)
334 for (n = 0; a[n]; n++) { }
341 Bool_t TGDNDManager::IsDNDAware(Window_t win, Atom_t *typelist)
343 return gVirtualX->IsDNDAware(win, typelist);
349 Window_t TGDNDManager::FindWindow(Window_t root,
int x,
int y,
int maxd)
351 if (maxd <= 0)
return kNone;
353 if (fDragWin && fDragWin->HasWindow(root))
return kNone;
355 return gVirtualX->FindRWindow(root, fDragWin ? fDragWin->GetId() : 0,
356 fDragWin ? fDragWin->GetInputId() : 0,
364 Window_t TGDNDManager::GetRootProxy()
368 ULong_t count, remaining;
369 unsigned char *data = 0;
370 Window_t win, proxy = kNone;
375 gVirtualX->UpdateWindow(0);
380 gVirtualX->GetProperty(gVirtualX->GetDefaultRootWindow(),
381 fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
382 &actual, &format, &count, &remaining, &data);
384 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
387 win = *((Window_t *) data);
391 gVirtualX->GetProperty(win, fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
392 &actual, &format, &count, &remaining, &data);
395 gVirtualX->UpdateWindow(0);
397 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
398 if (*((Window_t *) data) == win) {
405 if (data)
delete[] data;
413 Bool_t TGDNDManager::HandleClientMessage(Event_t *event)
415 if (event->fHandle == fgDNDEnter) {
416 HandleDNDEnter((Window_t) event->fUser[0], event->fUser[1],
417 (Atom_t *) &event->fUser[2]);
419 }
else if (event->fHandle == fgDNDLeave) {
420 HandleDNDLeave((Window_t) event->fUser[0]);
422 }
else if (event->fHandle == fgDNDPosition) {
423 HandleDNDPosition((Window_t) event->fUser[0],
424 (Int_t) (event->fUser[2] >> 16) & 0xFFFF,
425 (Int_t) (event->fUser[2] & 0xFFFF),
426 (Atom_t) event->fUser[4],
427 (Time_t) event->fUser[3]);
429 }
else if (event->fHandle == fgDNDStatus) {
431 skip.fX = (
event->fUser[2] >> 16) & 0xFFFF;
432 skip.fY = (
event->fUser[2] & 0xFFFF);
433 skip.fWidth = (
event->fUser[3] >> 16) & 0xFFFF;
434 skip.fHeight = (
event->fUser[3] & 0xFFFF);
436 HandleDNDStatus((Window_t) event->fUser[0],
437 (
int) (event->fUser[1] & 0x1),
438 skip, (Atom_t) event->fUser[4]);
440 }
else if (event->fHandle == fgDNDDrop) {
441 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
443 }
else if (event->fHandle == fgDNDFinished) {
444 HandleDNDFinished((Window_t) event->fUser[0]);
455 Bool_t TGDNDManager::HandleTimer(TTimer *t)
457 if (t == fDropTimeout) {
464 SendDNDLeave(fTarget);
465 fStatusPending = kFALSE;
467 if (fLocalSource) fLocalSource->HandleDNDFinished();
476 void TGDNDManager::SendDNDEnter(Window_t target)
481 event.fType = kClientMessage;
482 event.fWindow = target;
483 event.fHandle = fgDNDEnter;
486 event.fUser[0] = fMain->GetId();
488 n = ArrayLength(fTypelist);
490 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
494 for (i = 0; i < 3; ++i)
495 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
498 TDNDData *dnddata = 0;
503 dnddata = fLocalSource->GetDNDData(0);
504 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
505 event.fUser[2] = dataType;
506 event.fUser[3] = kNone;
507 event.fUser[4] = kNone;
510 gVirtualX->SendEvent(target, &event);
516 void TGDNDManager::SendDNDLeave(Window_t target)
520 event.fType = kClientMessage;
521 event.fWindow = target;
522 event.fHandle = fgDNDLeave;
525 event.fUser[0] = fMain->GetId();
532 gVirtualX->SendEvent(target, &event);
538 void TGDNDManager::SendDNDPosition(Window_t target,
int x,
int y,
539 Atom_t action, Time_t timestamp)
543 event.fType = kClientMessage;
544 event.fWindow = target;
545 event.fHandle = fgDNDPosition;
548 event.fUser[0] = fMain->GetId();
551 event.fUser[2] = (x << 16) | y;
552 event.fUser[3] = timestamp;
553 event.fUser[4] = action;
555 gVirtualX->SendEvent(target, &event);
561 void TGDNDManager::SendDNDStatus(Window_t source, Atom_t action)
565 event.fType = kClientMessage;
566 event.fWindow = source;
567 event.fHandle = fgDNDStatus;
570 event.fUser[0] = fMain->GetId();
571 event.fUser[1] = (action == kNone) ? 0L : 1L;
575 event.fUser[4] = action;
577 gVirtualX->SendEvent(source, &event);
583 void TGDNDManager::SendDNDDrop(Window_t target)
587 event.fType = kClientMessage;
588 event.fWindow = target;
589 event.fHandle = fgDNDDrop;
592 event.fUser[0] = fMain->GetId();
598 gVirtualX->SendEvent(target, &event);
604 void TGDNDManager::SendDNDFinished(Window_t source)
608 event.fType = kClientMessage;
609 event.fWindow = source;
610 event.fHandle = fgDNDFinished;
613 event.fUser[0] = fMain->GetId();
619 gVirtualX->SendEvent(source, &event);
625 Bool_t TGDNDManager::HandleDNDEnter(Window_t src, Long_t vers, Atom_t dataTypes[3])
629 if (fDraggerTypes)
delete[] fDraggerTypes;
634 ULong_t i, count, remaining;
635 unsigned char *data = 0;
637 gVirtualX->GetProperty(src, fgDNDTypeList,
638 0, 0x8000000L, kFALSE, XA_ATOM,
639 &type, &format, &count, &remaining, &data);
641 if (type != XA_ATOM || format != 32 || !data) {
645 fDraggerTypes =
new Atom_t[count+4];
648 for (i = 0; i < count; i++)
649 fDraggerTypes[i] = a[i];
651 fDraggerTypes[i] = kNone;
653 if (data)
delete[] data;
656 fDraggerTypes =
new Atom_t[4];
658 fDraggerTypes[0] = dataTypes[0];
659 fDraggerTypes[1] = dataTypes[1];
660 fDraggerTypes[2] = dataTypes[2];
662 fDraggerTypes[3] = kNone;
667 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
676 Bool_t TGDNDManager::HandleDNDLeave(Window_t )
679 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
682 if (fDraggerTypes)
delete[] fDraggerTypes;
691 Bool_t TGDNDManager::HandleDNDPosition(Window_t source, Int_t x_root, Int_t y_root,
692 Atom_t action, Time_t )
696 TGFrame *f = 0, *main = 0;
698 Window_t wtarget = 0;
700 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
703 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
704 wtarget, x_root, y_root, x, y, child);
705 w = gClient->GetWindowById(wtarget);
707 f =
dynamic_cast<TGFrame *
>(w);
710 if (f != fLocalTarget) {
711 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
714 main = (TGFrame *)fLocalTarget->GetMainFrame();
718 fDropType = fLocalTarget->HandleDNDEnter(fDraggerTypes);
724 action = (fDropType == kNone) ? kNone :
725 fLocalTarget->HandleDNDPosition(x, y, action, x_root, y_root);
726 }
else if (fProxyOurs) {
727 action = fMain->HandleDNDPosition(x, y, action, x_root, y_root);
731 SendDNDStatus(source, fLocalAction = action);
738 Bool_t TGDNDManager::HandleDNDStatus(Window_t target, Int_t accepted,
739 Rectangle_t , Atom_t action)
742 fStatusPending = kFALSE;
744 fDropAccepted = kTRUE;
745 fAcceptedAction = action;
747 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
748 fGrabEventMask, kNone);
750 fDropAccepted = kFALSE;
751 fAcceptedAction = kNone;
753 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
760 SendDNDDrop(fTarget);
769 Bool_t TGDNDManager::HandleDNDDrop(Window_t source, Time_t timestamp)
776 if (fMain && fDropType != kNone) {
777 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
778 8, (
unsigned char *) 0, 0);
780 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
781 fgXCDNDData, timestamp);
785 if (fMain) SendDNDFinished(source);
793 Bool_t TGDNDManager::HandleDNDFinished(Window_t )
795 if (fLocalSource) fLocalSource->HandleDNDFinished();
802 Bool_t TGDNDManager::HandleSelectionRequest(Event_t *event)
804 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
806 TDNDData *dnddata = 0;
812 dnddata = fLocalSource->GetDNDData(event->fUser[2]);
814 data = dnddata ? (
char *) dnddata->fData : (
char *)
"";
815 len = dnddata ? dnddata->fDataLength : 0;
817 if ((Atom_t)
event->fUser[3] == kNone) {
819 event->fUser[3] = fgXCDNDData;
822 gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
824 (
unsigned char *) data, len);
826 xevent.fType = kSelectionNotify;
827 xevent.fTime =
event->fTime;
828 xevent.fUser[0] =
event->fUser[0];
829 xevent.fUser[1] =
event->fUser[1];
830 xevent.fUser[2] =
event->fUser[2];
831 xevent.fUser[3] =
event->fUser[3];
832 gVirtualX->SendEvent(event->fUser[0], &xevent);
843 Bool_t TGDNDManager::HandleSelection(Event_t *event)
845 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
846 Atom_t actual = fDropType;
848 ULong_t count, remaining;
849 unsigned char *data = 0;
852 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
853 0, 0x8000000L, kTRUE, event->fUser[2],
854 &actual, &format, &count, &remaining, &data);
856 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
857 if (data)
delete[] data;
862 if (fSource != kNone) SendDNDFinished(fSource);
867 TDNDData dndData(actual, data, count, fLocalAction);
868 fLocalTarget->HandleDNDDrop(&dndData);
869 if (fDraggerTypes)
delete[] fDraggerTypes;
874 fLocalAction = kNone;
888 void TGDNDManager::SetDragPixmap(Pixmap_t pic, Pixmap_t mask,
889 int hot_x,
int hot_y)
900 Bool_t TGDNDManager::StartDrag(TGFrame *src,
int x_root,
int y_root,
903 if (fDragging)
return kTRUE;
907 if ((TGWindow *)fMain != src->GetMainFrame()) {
908 fMain = (TGFrame *)src->GetMainFrame();
911 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
916 if (grabWin == kNone) grabWin = fMain->GetId();
918 gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
923 fTargetIsDNDAware = kFALSE;
924 fStatusPending = kFALSE;
925 if (fDropTimeout)
delete fDropTimeout;
927 fDropAccepted = kFALSE;
928 fAcceptedAction = kNone;
929 fLocalAction = kNone;
931 if (!fDragWin && fPic != kNone && fMask != kNone) {
932 fDragWin =
new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
933 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
934 fDragWin->MapSubwindows();
935 fDragWin->MapRaised();
943 Bool_t TGDNDManager::Drop()
945 if (!fDragging)
return kFALSE;
947 if (fTargetIsDNDAware) {
949 if (fStatusPending) {
950 if (fDropTimeout)
delete fDropTimeout;
951 fDropTimeout =
new TTimer(
this, 5000);
953 SendDNDDrop(fTarget);
956 SendDNDLeave(fTarget);
957 fStatusPending = kFALSE;
967 Bool_t TGDNDManager::EndDrag()
969 if (!fDragging)
return kFALSE;
971 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
974 SendDNDFinished(fSource);
976 fLocalSource->HandleDNDFinished();
980 fDragWin->DeleteWindow();
989 Bool_t TGDNDManager::Drag(
int x_root,
int y_root, Atom_t action, Time_t timestamp)
991 if (!fDragging)
return kFALSE;
993 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
996 if (newTarget == kNone) {
997 Window_t t = GetRootProxy();
998 if (t != kNone) newTarget = t;
1001 if (fTarget != newTarget) {
1003 if (fTargetIsDNDAware) SendDNDLeave(fTarget);
1005 fTarget = newTarget;
1006 fTargetIsDNDAware = IsDNDAware(fTarget);
1007 fStatusPending = kFALSE;
1008 fDropAccepted = kFALSE;
1009 fAcceptedAction = kNone;
1011 if (fTargetIsDNDAware) SendDNDEnter(fTarget);
1014 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
1018 if (fTargetIsDNDAware && !fStatusPending) {
1019 SendDNDPosition(fTarget, x_root, y_root, action, timestamp);
1023 fStatusPending = kTRUE;
1027 fDragWin->RaiseWindow();
1028 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
1036 Bool_t TGDNDManager::SetRootProxy()
1038 Window_t mainw = fMain->GetId();
1039 int result = kFALSE;
1041 if (GetRootProxy() == kNone) {
1042 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
1043 fgDNDProxy, XA_WINDOW, 32,
1044 (
unsigned char *) &mainw, 1);
1045 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
1046 (
unsigned char *) &mainw, 1);
1052 gVirtualX->UpdateWindow(0);
1059 Bool_t TGDNDManager::RemoveRootProxy()
1061 if (!fProxyOurs)
return kFALSE;
1063 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
1064 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
1070 gVirtualX->UpdateWindow(0);
1072 fProxyOurs = kFALSE;