00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGFrame.h"
00013 #include "TTimer.h"
00014 #include "TGDNDManager.h"
00015 #include "TRootCanvas.h"
00016
00017 #define ROOTDND_PROTOCOL_VERSION 4
00018 #define XA_ATOM ((Atom_t) 4)
00019 #define XA_WINDOW ((Atom_t) 33)
00020
00021 Atom_t TGDNDManager::fgDNDAware = kNone;
00022 Atom_t TGDNDManager::fgDNDSelection = kNone;
00023 Atom_t TGDNDManager::fgDNDProxy = kNone;
00024
00025 Atom_t TGDNDManager::fgDNDEnter = kNone;
00026 Atom_t TGDNDManager::fgDNDLeave = kNone;
00027 Atom_t TGDNDManager::fgDNDPosition = kNone;
00028 Atom_t TGDNDManager::fgDNDStatus = kNone;
00029 Atom_t TGDNDManager::fgDNDDrop = kNone;
00030 Atom_t TGDNDManager::fgDNDFinished = kNone;
00031 Atom_t TGDNDManager::fgDNDVersion = kNone;
00032
00033 Atom_t TGDNDManager::fgDNDActionCopy = kNone;
00034 Atom_t TGDNDManager::fgDNDActionMove = kNone;
00035 Atom_t TGDNDManager::fgDNDActionLink = kNone;
00036 Atom_t TGDNDManager::fgDNDActionAsk = kNone;
00037 Atom_t TGDNDManager::fgDNDActionPrivate = kNone;
00038
00039 Atom_t TGDNDManager::fgDNDTypeList = kNone;
00040 Atom_t TGDNDManager::fgDNDActionList = kNone;
00041 Atom_t TGDNDManager::fgDNDActionDescrip = kNone;
00042
00043 Atom_t TGDNDManager::fgXAWMState = kNone;
00044 Atom_t TGDNDManager::fgXCDNDData = kNone;
00045
00046 Bool_t TGDNDManager::fgInit = kFALSE;
00047
00048
00049
00050
00051
00052
00053 TGDNDManager *gDNDManager = 0;
00054
00055 Cursor_t TGDragWindow::fgDefaultCursor = kNone;
00056
00057
00058
00059
00060
00061
00062
00063
00064 ClassImp(TGDragWindow)
00065
00066
00067 TGDragWindow::TGDragWindow(const TGWindow *p, Pixmap_t pic, Pixmap_t mask,
00068 UInt_t options, Pixel_t back) :
00069 TGFrame(p, 32, 32, options, back)
00070 {
00071
00072
00073 if (fgDefaultCursor == kNone) {
00074 fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
00075 }
00076
00077 fPic = pic;
00078 fMask = mask;
00079
00080 SetWindowAttributes_t wattr;
00081
00082 wattr.fMask = kWAOverrideRedirect | kWASaveUnder;
00083 wattr.fSaveUnder = kTRUE;
00084 wattr.fOverrideRedirect = kTRUE;
00085
00086 gVirtualX->ChangeWindowAttributes(fId, &wattr);
00087
00088 int x, y;
00089
00090 gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
00091
00092 wattr.fMask = kWAOverrideRedirect;
00093 wattr.fOverrideRedirect = kTRUE;
00094
00095
00096
00097
00098
00099
00100
00101
00102 fInput = fId;
00103
00104 Resize(GetDefaultSize());
00105
00106 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
00107
00108 gVirtualX->SetCursor(fId, fgDefaultCursor);
00109 }
00110
00111
00112 TGDragWindow::~TGDragWindow()
00113 {
00114
00115
00116
00117 }
00118
00119
00120 void TGDragWindow::MapWindow()
00121 {
00122
00123
00124 TGFrame::MapWindow();
00125
00126 }
00127
00128
00129 void TGDragWindow::UnmapWindow()
00130 {
00131
00132
00133 TGFrame::UnmapWindow();
00134
00135 }
00136
00137
00138 void TGDragWindow::RaiseWindow()
00139 {
00140
00141
00142 TGFrame::RaiseWindow();
00143
00144 }
00145
00146
00147 void TGDragWindow::LowerWindow()
00148 {
00149
00150
00151
00152 TGFrame::LowerWindow();
00153 }
00154
00155
00156 void TGDragWindow::MapRaised()
00157 {
00158
00159
00160 TGFrame::MapRaised();
00161
00162 }
00163
00164
00165 void TGDragWindow::Layout()
00166 {
00167
00168
00169 gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
00170 }
00171
00172
00173 void TGDragWindow::DoRedraw()
00174 {
00175
00176
00177 gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187 ClassImp(TGDNDManager)
00188
00189
00190 TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t * )
00191 {
00192
00193
00194 if (gDNDManager)
00195 return;
00196
00197 fMain = toplevel;
00198 fVersion = ROOTDND_PROTOCOL_VERSION;
00199 fUseVersion = kTRUE;
00200
00201 fTypelist = new Atom_t[3];
00202 fTypelist[0] = gVirtualX->InternAtom("application/root", kFALSE);
00203 fTypelist[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
00204 fTypelist[2] = 0;
00205
00206 if (!fgInit) {
00207 InitAtoms();
00208 fgInit = kTRUE;
00209 }
00210
00211
00212 fDropTimeout = 0;
00213
00214 fSource = kNone;
00215 fTarget = kNone;
00216 fTargetIsDNDAware = kFALSE;
00217 fStatusPending = kFALSE;
00218 fDropAccepted = kFALSE;
00219 fAcceptedAction = kNone;
00220 fLocalAction = kNone;
00221 fDragging = kFALSE;
00222 fDragWin = 0;
00223 fLocalSource = 0;
00224 fLocalTarget = 0;
00225 fPic = fMask = kNone;
00226 fDraggerTypes = 0;
00227 fDropType = kNone;
00228 fHotx = fHoty = 0;
00229
00230 fGrabEventMask = kButtonPressMask | kButtonReleaseMask | kButtonMotionMask;
00231
00232 fDNDNoDropCursor = gVirtualX->CreateCursor(kNoDrop);
00233
00234
00235
00236 fProxyOurs = kFALSE;
00237 gDNDManager = this;
00238 }
00239
00240
00241 TGDNDManager::~TGDNDManager()
00242 {
00243
00244
00245
00246 if (fProxyOurs)
00247 RemoveRootProxy();
00248
00249
00250 if (fMain) {
00251 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDAware);
00252 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDTypeList);
00253 }
00254 if (fDropTimeout) delete fDropTimeout;
00255
00256
00257 if (fDragWin) {
00258 fDragWin->DeleteWindow();
00259 fDragWin = 0;
00260 }
00261 if (fPic != kNone) gVirtualX->DeletePixmap(fPic);
00262 if (fMask != kNone) gVirtualX->DeletePixmap(fMask);
00263
00264 if (fDraggerTypes) delete[] fDraggerTypes;
00265 }
00266
00267 Atom_t TGDNDManager::GetDNDAware() { return fgDNDAware; }
00268 Atom_t TGDNDManager::GetDNDSelection() { return fgDNDSelection; }
00269 Atom_t TGDNDManager::GetDNDProxy() { return fgDNDProxy; }
00270 Atom_t TGDNDManager::GetDNDEnter() { return fgDNDEnter; }
00271 Atom_t TGDNDManager::GetDNDLeave() { return fgDNDLeave; }
00272 Atom_t TGDNDManager::GetDNDPosition() { return fgDNDPosition; }
00273 Atom_t TGDNDManager::GetDNDStatus() { return fgDNDStatus; }
00274 Atom_t TGDNDManager::GetDNDDrop() { return fgDNDDrop; }
00275 Atom_t TGDNDManager::GetDNDFinished() { return fgDNDFinished; }
00276 Atom_t TGDNDManager::GetDNDVersion() { return fgDNDVersion; }
00277 Atom_t TGDNDManager::GetDNDActionCopy() { return fgDNDActionCopy; }
00278 Atom_t TGDNDManager::GetDNDActionMove() { return fgDNDActionMove; }
00279 Atom_t TGDNDManager::GetDNDActionLink() { return fgDNDActionLink; }
00280 Atom_t TGDNDManager::GetDNDActionAsk() { return fgDNDActionAsk; }
00281 Atom_t TGDNDManager::GetDNDActionPrivate() { return fgDNDActionPrivate; }
00282 Atom_t TGDNDManager::GetDNDTypeList() { return fgDNDTypeList; }
00283 Atom_t TGDNDManager::GetDNDActionList() { return fgDNDActionList; }
00284 Atom_t TGDNDManager::GetDNDActionDescrip() { return fgDNDActionDescrip; }
00285 Atom_t TGDNDManager::GetXCDNDData() { return fgXCDNDData; }
00286
00287
00288 void TGDNDManager::InitAtoms()
00289 {
00290
00291
00292
00293 fgDNDAware = gVirtualX->InternAtom("XdndAware", kFALSE);
00294
00295
00296 fgDNDSelection = gVirtualX->InternAtom("XdndSelection", kFALSE);
00297
00298
00299 fgDNDProxy = gVirtualX->InternAtom("XdndProxy", kFALSE);
00300
00301
00302 fgDNDEnter = gVirtualX->InternAtom("XdndEnter", kFALSE);
00303 fgDNDLeave = gVirtualX->InternAtom("XdndLeave", kFALSE);
00304 fgDNDPosition = gVirtualX->InternAtom("XdndPosition", kFALSE);
00305 fgDNDStatus = gVirtualX->InternAtom("XdndStatus", kFALSE);
00306 fgDNDDrop = gVirtualX->InternAtom("XdndDrop", kFALSE);
00307 fgDNDFinished = gVirtualX->InternAtom("XdndFinished", kFALSE);
00308
00309
00310 fgDNDActionCopy = gVirtualX->InternAtom("XdndActionCopy", kFALSE);
00311 fgDNDActionMove = gVirtualX->InternAtom("XdndActionMove", kFALSE);
00312 fgDNDActionLink = gVirtualX->InternAtom("XdndActionLink", kFALSE);
00313 fgDNDActionAsk = gVirtualX->InternAtom("XdndActionAsk", kFALSE);
00314 fgDNDActionPrivate = gVirtualX->InternAtom("XdndActionPrivate", kFALSE);
00315
00316
00317 fgDNDTypeList = gVirtualX->InternAtom("XdndTypeList", kFALSE);
00318 fgDNDActionList = gVirtualX->InternAtom("XdndActionList", kFALSE);
00319 fgDNDActionDescrip = gVirtualX->InternAtom("XdndActionDescription", kFALSE);
00320
00321
00322 fgXAWMState = gVirtualX->InternAtom("WM_STATE", kFALSE);
00323 fgXCDNDData = gVirtualX->InternAtom("_XC_DND_DATA", kFALSE);
00324 }
00325
00326 static int ArrayLength(Atom_t *a)
00327 {
00328
00329
00330 int n;
00331
00332 for (n = 0; a[n]; n++) { }
00333 return n;
00334 }
00335
00336
00337 Bool_t TGDNDManager::IsDNDAware(Window_t win, Atom_t *typelist)
00338 {
00339
00340
00341 return gVirtualX->IsDNDAware(win, typelist);
00342 }
00343
00344
00345 Window_t TGDNDManager::FindWindow(Window_t root, int x, int y, int maxd)
00346 {
00347
00348
00349 if (maxd <= 0) return kNone;
00350
00351 if (fDragWin && fDragWin->HasWindow(root)) return kNone;
00352
00353 return gVirtualX->FindRWindow(root, fDragWin ? fDragWin->GetId() : 0,
00354 fDragWin ? fDragWin->GetInputId() : 0,
00355 x, y, maxd);
00356 }
00357
00358
00359
00360 Window_t TGDNDManager::GetRootProxy()
00361 {
00362
00363
00364 Atom_t actual;
00365 Int_t format = 32;
00366 ULong_t count, remaining;
00367 unsigned char *data = 0;
00368 Window_t win, proxy = kNone;
00369
00370
00371
00372
00373 gVirtualX->UpdateWindow(0);
00374
00375
00376
00377
00378 gVirtualX->GetProperty(gVirtualX->GetDefaultRootWindow(),
00379 fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
00380 &actual, &format, &count, &remaining, &data);
00381
00382 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
00383
00384
00385 win = *((Window_t *) data);
00386 delete[] data;
00387 data = 0;
00388
00389 gVirtualX->GetProperty(win, fgDNDProxy, 0, 1, kFALSE, XA_WINDOW,
00390 &actual, &format, &count, &remaining, &data);
00391
00392
00393 gVirtualX->UpdateWindow(0);
00394
00395 if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
00396 if (*((Window_t *) data) == win) {
00397
00398
00399 proxy = win;
00400 }
00401 }
00402 }
00403 if (data) delete[] data;
00404
00405 return proxy;
00406 }
00407
00408
00409 Bool_t TGDNDManager::HandleClientMessage(Event_t *event)
00410 {
00411
00412
00413 if (event->fHandle == fgDNDEnter) {
00414 HandleDNDEnter((Window_t) event->fUser[0], event->fUser[1],
00415 (Atom_t *) &event->fUser[2]);
00416
00417 } else if (event->fHandle == fgDNDLeave) {
00418 HandleDNDLeave((Window_t) event->fUser[0]);
00419
00420 } else if (event->fHandle == fgDNDPosition) {
00421 HandleDNDPosition((Window_t) event->fUser[0],
00422 (Int_t) (event->fUser[2] >> 16) & 0xFFFF,
00423 (Int_t) (event->fUser[2] & 0xFFFF),
00424 (Atom_t) event->fUser[4],
00425 (Time_t) event->fUser[3]);
00426
00427 } else if (event->fHandle == fgDNDStatus) {
00428 Rectangle_t skip;
00429 skip.fX = (event->fUser[2] >> 16) & 0xFFFF;
00430 skip.fY = (event->fUser[2] & 0xFFFF);
00431 skip.fWidth = (event->fUser[3] >> 16) & 0xFFFF;
00432 skip.fHeight = (event->fUser[3] & 0xFFFF);
00433
00434 HandleDNDStatus((Window_t) event->fUser[0],
00435 (int) (event->fUser[1] & 0x1),
00436 skip, (Atom_t) event->fUser[4]);
00437
00438 } else if (event->fHandle == fgDNDDrop) {
00439 HandleDNDDrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
00440
00441 } else if (event->fHandle == fgDNDFinished) {
00442 HandleDNDFinished((Window_t) event->fUser[0]);
00443
00444 } else {
00445 return kFALSE;
00446 }
00447 return kTRUE;
00448 }
00449
00450
00451 Bool_t TGDNDManager::HandleTimer(TTimer *t)
00452 {
00453
00454
00455 if (t == fDropTimeout) {
00456
00457
00458
00459 delete fDropTimeout;
00460 fDropTimeout = 0;
00461
00462 SendDNDLeave(fTarget);
00463 fStatusPending = kFALSE;
00464
00465 if (fLocalSource) fLocalSource->HandleDNDFinished();
00466 return kTRUE;
00467 }
00468 return kFALSE;
00469 }
00470
00471
00472 void TGDNDManager::SendDNDEnter(Window_t target)
00473 {
00474
00475
00476 Int_t i, n;
00477 Event_t event;
00478
00479 event.fType = kClientMessage;
00480 event.fWindow = target;
00481 event.fHandle = fgDNDEnter;
00482 event.fFormat = 32;
00483
00484 event.fUser[0] = fMain->GetId();
00485
00486 n = ArrayLength(fTypelist);
00487
00488 event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
00489
00490
00491
00492 for (i = 0; i < 3; ++i)
00493 event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
00494
00495 if (fLocalSource) {
00496 TDNDData *dnddata = 0;
00497 Atom_t dataType;
00498
00499
00500 if (fLocalSource)
00501 dnddata = fLocalSource->GetDNDData(0);
00502 dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
00503 event.fUser[2] = dataType;
00504 event.fUser[3] = kNone;
00505 event.fUser[4] = kNone;
00506 }
00507
00508 gVirtualX->SendEvent(target, &event);
00509 }
00510
00511
00512 void TGDNDManager::SendDNDLeave(Window_t target)
00513 {
00514
00515
00516 Event_t event;
00517
00518 event.fType = kClientMessage;
00519 event.fWindow = target;
00520 event.fHandle = fgDNDLeave;
00521 event.fFormat = 32;
00522
00523 event.fUser[0] = fMain->GetId();
00524 event.fUser[1] = 0L;
00525
00526 event.fUser[2] = 0L;
00527 event.fUser[3] = 0L;
00528 event.fUser[4] = 0L;
00529
00530 gVirtualX->SendEvent(target, &event);
00531 }
00532
00533
00534 void TGDNDManager::SendDNDPosition(Window_t target, int x, int y,
00535 Atom_t action, Time_t timestamp)
00536 {
00537
00538
00539 Event_t event;
00540
00541 event.fType = kClientMessage;
00542 event.fWindow = target;
00543 event.fHandle = fgDNDPosition;
00544 event.fFormat = 32;
00545
00546 event.fUser[0] = fMain->GetId();
00547 event.fUser[1] = 0L;
00548
00549 event.fUser[2] = (x << 16) | y;
00550 event.fUser[3] = timestamp;
00551 event.fUser[4] = action;
00552
00553 gVirtualX->SendEvent(target, &event);
00554 }
00555
00556
00557 void TGDNDManager::SendDNDStatus(Window_t source, Atom_t action)
00558 {
00559
00560
00561 Event_t event;
00562
00563 event.fType = kClientMessage;
00564 event.fWindow = source;
00565 event.fHandle = fgDNDStatus;
00566 event.fFormat = 32;
00567
00568 event.fUser[0] = fMain->GetId();
00569 event.fUser[1] = (action == kNone) ? 0L : 1L;
00570
00571 event.fUser[2] = 0L;
00572 event.fUser[3] = 0L;
00573 event.fUser[4] = action;
00574
00575 gVirtualX->SendEvent(source, &event);
00576 }
00577
00578
00579 void TGDNDManager::SendDNDDrop(Window_t target)
00580 {
00581
00582
00583 Event_t event;
00584
00585 event.fType = kClientMessage;
00586 event.fWindow = target;
00587 event.fHandle = fgDNDDrop;
00588 event.fFormat = 32;
00589
00590 event.fUser[0] = fMain->GetId();
00591 event.fUser[1] = 0L;
00592 event.fUser[2] = 0L;
00593 event.fUser[3] = 0L;
00594 event.fUser[4] = 0L;
00595
00596 gVirtualX->SendEvent(target, &event);
00597 }
00598
00599
00600 void TGDNDManager::SendDNDFinished(Window_t source)
00601 {
00602
00603
00604 Event_t event;
00605
00606 event.fType = kClientMessage;
00607 event.fWindow = source;
00608 event.fHandle = fgDNDFinished;
00609 event.fFormat = 32;
00610
00611 event.fUser[0] = fMain->GetId();
00612 event.fUser[1] = 0L;
00613 event.fUser[2] = 0L;
00614 event.fUser[3] = 0L;
00615 event.fUser[4] = 0L;
00616
00617 gVirtualX->SendEvent(source, &event);
00618 }
00619
00620
00621 Bool_t TGDNDManager::HandleDNDEnter(Window_t src, Long_t vers, Atom_t dataTypes[3])
00622 {
00623
00624
00625 fSource = src;
00626
00627 if (fDraggerTypes) delete[] fDraggerTypes;
00628
00629 if (vers & 1) {
00630 Atom_t type, *a;
00631 Int_t format = 32;
00632 ULong_t i, count, remaining;
00633 unsigned char *data = 0;
00634
00635 gVirtualX->GetProperty(src, fgDNDTypeList,
00636 0, 0x8000000L, kFALSE, XA_ATOM,
00637 &type, &format, &count, &remaining, &data);
00638
00639 if (type != XA_ATOM || format != 32 || !data) {
00640 count = 0;
00641 }
00642
00643 fDraggerTypes = new Atom_t[count+4];
00644
00645 a = (Atom_t *) data;
00646 for (i = 0; i < count; i++)
00647 fDraggerTypes[i] = a[i];
00648
00649 fDraggerTypes[i] = kNone;
00650
00651 if (data) delete[] data;
00652
00653 } else {
00654 fDraggerTypes = new Atom_t[4];
00655
00656 fDraggerTypes[0] = dataTypes[0];
00657 fDraggerTypes[1] = dataTypes[1];
00658 fDraggerTypes[2] = dataTypes[2];
00659
00660 fDraggerTypes[3] = kNone;
00661 }
00662
00663
00664
00665 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
00666 fLocalTarget = 0;
00667
00668 return kTRUE;
00669 }
00670
00671
00672 Bool_t TGDNDManager::HandleDNDLeave(Window_t )
00673 {
00674
00675
00676 fSource = kNone;
00677 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
00678 fLocalTarget = 0;
00679
00680 if (fDraggerTypes) delete[] fDraggerTypes;
00681 fDraggerTypes = 0;
00682
00683 return kTRUE;
00684 }
00685
00686
00687 Bool_t TGDNDManager::HandleDNDPosition(Window_t source, Int_t x_root, Int_t y_root,
00688 Atom_t action, Time_t )
00689 {
00690
00691
00692 Int_t x, y;
00693 Window_t child;
00694 TGFrame *f = 0, *main = 0;
00695 TGWindow *w = 0;
00696 Window_t wtarget = 0;
00697
00698 wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 15);
00699
00700 if (wtarget) {
00701 gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
00702 wtarget, x_root, y_root, x, y, child);
00703 w = gClient->GetWindowById(wtarget);
00704 if (w)
00705 f = dynamic_cast<TGFrame *>(w);
00706 }
00707
00708 if (f != fLocalTarget) {
00709 if (fLocalTarget) fLocalTarget->HandleDNDLeave();
00710 fLocalTarget = f;
00711 if (fLocalTarget) {
00712 main = (TGFrame *)fLocalTarget->GetMainFrame();
00713 main->RaiseWindow();
00714 if (fMain == 0)
00715 fMain = main;
00716 fDropType = fLocalTarget->HandleDNDEnter(fDraggerTypes);
00717 }
00718 }
00719
00720
00721 if (fLocalTarget) {
00722 action = (fDropType == kNone) ? kNone :
00723 fLocalTarget->HandleDNDPosition(x, y, action, x_root, y_root);
00724 } else if (fProxyOurs) {
00725 action = fMain->HandleDNDPosition(x, y, action, x_root, y_root);
00726 } else {
00727 action = kNone;
00728 }
00729 SendDNDStatus(source, fLocalAction = action);
00730 return kTRUE;
00731 }
00732
00733
00734 Bool_t TGDNDManager::HandleDNDStatus(Window_t target, Int_t accepted,
00735 Rectangle_t , Atom_t action)
00736 {
00737
00738
00739 if (target) {
00740 fStatusPending = kFALSE;
00741 if (accepted) {
00742 fDropAccepted = kTRUE;
00743 fAcceptedAction = action;
00744 if (fDragWin)
00745 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
00746 fGrabEventMask, kNone);
00747 } else {
00748 fDropAccepted = kFALSE;
00749 fAcceptedAction = kNone;
00750 if (fDragWin)
00751 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
00752 fGrabEventMask,
00753 fDNDNoDropCursor);
00754 }
00755 if (fDropTimeout) {
00756 delete fDropTimeout;
00757 fDropTimeout = 0;
00758 SendDNDDrop(fTarget);
00759 }
00760 }
00761 return kTRUE;
00762 }
00763
00764
00765 Bool_t TGDNDManager::HandleDNDDrop(Window_t source, Time_t timestamp)
00766 {
00767
00768
00769
00770
00771
00772
00773
00774 if (fMain && fDropType != kNone) {
00775 gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
00776 8, (unsigned char *) 0, 0);
00777
00778 gVirtualX->ConvertSelection(fMain->GetId(), fgDNDSelection, fDropType,
00779 fgXCDNDData, timestamp);
00780 }
00781
00782 fSource = source;
00783 if (fMain) SendDNDFinished(source);
00784
00785 return kTRUE;
00786 }
00787
00788
00789 Bool_t TGDNDManager::HandleDNDFinished(Window_t )
00790 {
00791
00792
00793 if (fLocalSource) fLocalSource->HandleDNDFinished();
00794 return kTRUE;
00795 }
00796
00797
00798 Bool_t TGDNDManager::HandleSelectionRequest(Event_t *event)
00799 {
00800
00801
00802 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
00803 Event_t xevent;
00804 TDNDData *dnddata = 0;
00805 char *data;
00806 int len;
00807
00808
00809 if (fLocalSource)
00810 dnddata = fLocalSource->GetDNDData(event->fUser[2]);
00811
00812 data = dnddata ? (char *) dnddata->fData : (char *) "";
00813 len = dnddata ? dnddata->fDataLength : 0;
00814
00815 if ((Atom_t)event->fUser[3] == kNone) {
00816
00817 event->fUser[3] = fgXCDNDData;
00818 }
00819
00820 gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
00821 event->fUser[2], 8,
00822 (unsigned char *) data, len);
00823
00824 xevent.fType = kSelectionNotify;
00825 xevent.fTime = event->fTime;
00826 xevent.fUser[0] = event->fUser[0];
00827 xevent.fUser[1] = event->fUser[1];
00828 xevent.fUser[2] = event->fUser[2];
00829 xevent.fUser[3] = event->fUser[3];
00830 gVirtualX->SendEvent(event->fUser[0], &xevent);
00831
00832 return kTRUE;
00833
00834 } else {
00835 return kFALSE;
00836 }
00837 }
00838
00839
00840 Bool_t TGDNDManager::HandleSelection(Event_t *event)
00841 {
00842
00843
00844 if ((Atom_t)event->fUser[1] == fgDNDSelection) {
00845 Atom_t actual = fDropType;
00846 Int_t format = 8;
00847 ULong_t count, remaining;
00848 unsigned char *data = 0;
00849
00850 gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
00851 0, 0x8000000L, kTRUE, event->fUser[2],
00852 &actual, &format, &count, &remaining, &data);
00853
00854 if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
00855 if (data) delete[] data;
00856 return kFALSE;
00857 }
00858
00859 if (fSource != kNone) SendDNDFinished(fSource);
00860
00861
00862
00863 if (fLocalTarget) {
00864 TDNDData dndData(actual, data, count, fLocalAction);
00865 fLocalTarget->HandleDNDDrop(&dndData);
00866 if (fDraggerTypes) delete[] fDraggerTypes;
00867 fDraggerTypes = 0;
00868 }
00869
00870 fSource = kNone;
00871 fLocalAction = kNone;
00872
00873
00874
00875 return kTRUE;
00876
00877 } else {
00878 return kFALSE;
00879 }
00880 }
00881
00882
00883 void TGDNDManager::SetDragPixmap(Pixmap_t pic, Pixmap_t mask,
00884 int hot_x, int hot_y)
00885 {
00886
00887
00888 fPic = pic;
00889 fMask = mask;
00890 fHotx = hot_x;
00891 fHoty = hot_y;
00892 }
00893
00894
00895 Bool_t TGDNDManager::StartDrag(TGFrame *src, int x_root, int y_root,
00896 Window_t grabWin)
00897 {
00898
00899
00900 if (fDragging) return kTRUE;
00901
00902 fLocalSource = src;
00903
00904 if ((TGWindow *)fMain != src->GetMainFrame()) {
00905 fMain = (TGFrame *)src->GetMainFrame();
00906 }
00907
00908 if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDSelection)) {
00909
00910 return kFALSE;
00911 }
00912
00913 if (grabWin == kNone) grabWin = fMain->GetId();
00914
00915 gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
00916
00917 fLocalTarget = 0;
00918 fDragging = kTRUE;
00919 fTarget = kNone;
00920 fTargetIsDNDAware = kFALSE;
00921 fStatusPending = kFALSE;
00922 if (fDropTimeout) delete fDropTimeout;
00923 fDropTimeout = 0;
00924 fDropAccepted = kFALSE;
00925 fAcceptedAction = kNone;
00926 fLocalAction = kNone;
00927
00928 if (!fDragWin && fPic != kNone && fMask != kNone) {
00929 fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
00930 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
00931 fDragWin->MapSubwindows();
00932 fDragWin->MapRaised();
00933 }
00934 return kTRUE;
00935 }
00936
00937
00938 Bool_t TGDNDManager::Drop()
00939 {
00940
00941
00942 if (!fDragging) return kFALSE;
00943
00944 if (fTargetIsDNDAware) {
00945 if (fDropAccepted) {
00946 if (fStatusPending) {
00947 if (fDropTimeout) delete fDropTimeout;
00948 fDropTimeout = new TTimer(this, 5000);
00949 } else {
00950 SendDNDDrop(fTarget);
00951 }
00952 } else {
00953 SendDNDLeave(fTarget);
00954 fStatusPending = kFALSE;
00955 }
00956 }
00957 EndDrag();
00958 return kTRUE;
00959 }
00960
00961
00962 Bool_t TGDNDManager::EndDrag()
00963 {
00964
00965
00966 if (!fDragging) return kFALSE;
00967
00968 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
00969
00970 if (fSource)
00971 SendDNDFinished(fSource);
00972 if (fLocalSource)
00973 fLocalSource->HandleDNDFinished();
00974
00975 fDragging = kFALSE;
00976 if (fDragWin) {
00977 fDragWin->DeleteWindow();
00978 fDragWin = 0;
00979 }
00980 return kTRUE;
00981 }
00982
00983
00984 Bool_t TGDNDManager::Drag(int x_root, int y_root, Atom_t action, Time_t timestamp)
00985 {
00986
00987
00988 if (!fDragging) return kFALSE;
00989
00990 Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
00991 x_root, y_root, 15);
00992
00993 if (newTarget == kNone) {
00994 Window_t t = GetRootProxy();
00995 if (t != kNone) newTarget = t;
00996 }
00997
00998 if (fTarget != newTarget) {
00999
01000 if (fTargetIsDNDAware) SendDNDLeave(fTarget);
01001
01002 fTarget = newTarget;
01003 fTargetIsDNDAware = IsDNDAware(fTarget);
01004 fStatusPending = kFALSE;
01005 fDropAccepted = kFALSE;
01006 fAcceptedAction = kNone;
01007
01008 if (fTargetIsDNDAware) SendDNDEnter(fTarget);
01009
01010 if (fDragWin)
01011 gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
01012 fDNDNoDropCursor);
01013 }
01014
01015 if (fTargetIsDNDAware && !fStatusPending) {
01016 SendDNDPosition(fTarget, x_root, y_root, action, timestamp);
01017
01018
01019
01020 fStatusPending = kTRUE;
01021 }
01022
01023 if (fDragWin) {
01024 fDragWin->RaiseWindow();
01025 fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
01026 }
01027 return kTRUE;
01028 }
01029
01030
01031 Bool_t TGDNDManager::SetRootProxy()
01032 {
01033
01034
01035 Window_t mainw = fMain->GetId();
01036 int result = kFALSE;
01037
01038 if (GetRootProxy() == kNone) {
01039 gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
01040 fgDNDProxy, XA_WINDOW, 32,
01041 (unsigned char *) &mainw, 1);
01042 gVirtualX->ChangeProperties(mainw, fgDNDProxy, XA_WINDOW, 32,
01043 (unsigned char *) &mainw, 1);
01044
01045 fProxyOurs = kTRUE;
01046 result = kTRUE;
01047 }
01048
01049 gVirtualX->UpdateWindow(0);
01050 return result;
01051 }
01052
01053
01054 Bool_t TGDNDManager::RemoveRootProxy()
01055 {
01056
01057
01058 if (!fProxyOurs) return kFALSE;
01059
01060 gVirtualX->DeleteProperty(fMain->GetId(), fgDNDProxy);
01061 gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDProxy);
01062
01063
01064
01065
01066
01067 gVirtualX->UpdateWindow(0);
01068
01069 fProxyOurs = kFALSE;
01070
01071 return kTRUE;
01072 }