#include "TGFrame.h"
#include "TTimer.h"
#include "TGDNDManager.h"
#include "TRootCanvas.h"
#define ROOTDND_PROTOCOL_VERSION      4
#define XA_ATOM ((Atom_t) 4)
#define XA_WINDOW ((Atom_t) 33)
Atom_t TGDNDManager::fgDNDaware         = kNone;
Atom_t TGDNDManager::fgDNDselection     = kNone;
Atom_t TGDNDManager::fgDNDproxy         = kNone;
Atom_t TGDNDManager::fgDNDenter         = kNone;
Atom_t TGDNDManager::fgDNDleave         = kNone;
Atom_t TGDNDManager::fgDNDposition      = kNone;
Atom_t TGDNDManager::fgDNDstatus        = kNone;
Atom_t TGDNDManager::fgDNDdrop          = kNone;
Atom_t TGDNDManager::fgDNDfinished      = kNone;
Atom_t TGDNDManager::fgDNDversion       = kNone;
Atom_t TGDNDManager::fgDNDactionCopy    = kNone;
Atom_t TGDNDManager::fgDNDactionMove    = kNone;
Atom_t TGDNDManager::fgDNDactionLink    = kNone;
Atom_t TGDNDManager::fgDNDactionAsk     = kNone;
Atom_t TGDNDManager::fgDNDactionPrivate = kNone;
Atom_t TGDNDManager::fgDNDtypeList      = kNone;
Atom_t TGDNDManager::fgDNDactionList    = kNone;
Atom_t TGDNDManager::fgDNDactionDescrip = kNone;
Atom_t TGDNDManager::fgXAWMState     = kNone;
Atom_t TGDNDManager::fgXCDNDData     = kNone;
Bool_t TGDNDManager::fgInit = kFALSE;
TGDNDManager *gDNDManager = 0;
Cursor_t TGDragWindow::fgDefaultCursor = kNone;
ClassImp(TGDragWindow)
ClassImp(TGDNDManager)
TGDragWindow::TGDragWindow(const TGWindow *p, Pixmap_t pic, Pixmap_t mask,
                           UInt_t options, Pixel_t back) :
   TGFrame(p, 32, 32, options, back)
{
   
   if (fgDefaultCursor == kNone) {
      fgDefaultCursor = gVirtualX->CreateCursor(kTopLeft);
   }
   fPic = pic;
   fMask = mask;
   SetWindowAttributes_t wattr;
   wattr.fMask = kWAOverrideRedirect | kWASaveUnder;
   wattr.fSaveUnder = kTRUE;
   wattr.fOverrideRedirect = kTRUE;
   gVirtualX->ChangeWindowAttributes(fId, &wattr);
   int x, y;
   gVirtualX->GetWindowSize(fPic, x, y, fPw, fPh);
   wattr.fMask = kWAOverrideRedirect;
   wattr.fOverrideRedirect = kTRUE;
   
   
   
   
   
   
   fInput = fId;
   Resize(GetDefaultSize());
   gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
   gVirtualX->SetCursor(fId, fgDefaultCursor);
}
TGDragWindow::~TGDragWindow()
{
   
   
}
void TGDragWindow::MapWindow()
{
   
   TGFrame::MapWindow();
   
}
void TGDragWindow::UnmapWindow()
{
   
   TGFrame::UnmapWindow();
   
}
void TGDragWindow::RaiseWindow()
{
   
   TGFrame::RaiseWindow();
   
}
void TGDragWindow::LowerWindow()
{
   
   
   TGFrame::LowerWindow();
}
void TGDragWindow::MapRaised()
{
   
   TGFrame::MapRaised();
   
}
void TGDragWindow::Layout()
{
   
   gVirtualX->ShapeCombineMask(fId, 0, 0, fMask);
}
void TGDragWindow::DoRedraw()
{
   
   gVirtualX->CopyArea(fPic, fId, GetBckgndGC()(), 0, 0, fWidth, fHeight, 0, 0);
}
TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t *typelist)
{
   
   if (gDNDManager)
      return;
   fMain = toplevel;
   fVersion = ROOTDND_PROTOCOL_VERSION;
   fTypelist = typelist;
   if (!fgInit) {
      InitAtoms();
      fgInit = kTRUE;
   }
   
   fDropTimeout = 0;
   fSource = kNone;
   fTarget = kNone;
   fTargetIsDNDaware = kFALSE;
   fStatusPending = kFALSE;
   fDropAccepted = kFALSE;  
   fAcceptedAction = kNone; 
   fLocalAction = kNone;    
   fDragging = kFALSE;
   fDragWin = 0;
   fLocalSource = 0;
   fLocalTarget = 0;
   fPic = fMask = kNone;
   fDraggerTypes = 0;
   fDropType = kNone;
   fGrabEventMask = kButtonPressMask | kButtonReleaseMask | kButtonMotionMask;
   fDNDNoDropCursor = gVirtualX->CreateCursor(kNoDrop); 
   
   fProxyOurs = kFALSE;
   gDNDManager = this;
}
TGDNDManager::~TGDNDManager()
{
   
   
   if (fProxyOurs)
      RemoveRootProxy();
   
   if (fMain) {
      gVirtualX->DeleteProperty(fMain->GetId(), fgDNDaware);
      gVirtualX->DeleteProperty(fMain->GetId(), fgDNDtypeList);
   }
   if (fDropTimeout) delete fDropTimeout;
   
   if (fDragWin) {
      fDragWin->DeleteWindow();
      fDragWin = 0;
   }
   if (fPic != kNone) gVirtualX->DeletePixmap(fPic);
   if (fMask != kNone) gVirtualX->DeletePixmap(fMask);
   if (fDraggerTypes) delete[] fDraggerTypes;
}
Atom_t TGDNDManager::GetDNDaware() { return fgDNDaware; }
Atom_t TGDNDManager::GetDNDselection() { return fgDNDselection; }
Atom_t TGDNDManager::GetDNDproxy() { return fgDNDproxy; }
Atom_t TGDNDManager::GetDNDenter() { return fgDNDenter; }
Atom_t TGDNDManager::GetDNDleave() { return fgDNDleave; }
Atom_t TGDNDManager::GetDNDposition() { return fgDNDposition; }
Atom_t TGDNDManager::GetDNDstatus() { return fgDNDstatus; }
Atom_t TGDNDManager::GetDNDdrop() { return fgDNDdrop; }
Atom_t TGDNDManager::GetDNDfinished() { return fgDNDfinished; }
Atom_t TGDNDManager::GetDNDversion() { return fgDNDversion; }
Atom_t TGDNDManager::GetDNDactionCopy() { return fgDNDactionCopy; }
Atom_t TGDNDManager::GetDNDactionMove() { return fgDNDactionMove; }
Atom_t TGDNDManager::GetDNDactionLink() { return fgDNDactionLink; }
Atom_t TGDNDManager::GetDNDactionAsk() { return fgDNDactionAsk; }
Atom_t TGDNDManager::GetDNDactionPrivate() { return fgDNDactionPrivate; }
Atom_t TGDNDManager::GetDNDtypeList() { return fgDNDtypeList; }
Atom_t TGDNDManager::GetDNDactionList() { return fgDNDactionList; }
Atom_t TGDNDManager::GetDNDactionDescrip() { return fgDNDactionDescrip; }
Atom_t TGDNDManager::GetXCDNDData() { return fgXCDNDData; }
void TGDNDManager::InitAtoms()
{
   
   
   fgDNDaware = gVirtualX->InternAtom("XdndAware", kFALSE);
   
   fgDNDselection = gVirtualX->InternAtom("XdndSelection", kFALSE);
   
   fgDNDproxy = gVirtualX->InternAtom("XdndProxy", kFALSE);
   
   fgDNDenter    = gVirtualX->InternAtom("XdndEnter", kFALSE);
   fgDNDleave    = gVirtualX->InternAtom("XdndLeave", kFALSE);
   fgDNDposition = gVirtualX->InternAtom("XdndPosition", kFALSE);
   fgDNDstatus   = gVirtualX->InternAtom("XdndStatus", kFALSE);
   fgDNDdrop     = gVirtualX->InternAtom("XdndDrop", kFALSE);
   fgDNDfinished = gVirtualX->InternAtom("XdndFinished", kFALSE);
   
   fgDNDactionCopy    = gVirtualX->InternAtom("XdndActionCopy", kFALSE);
   fgDNDactionMove    = gVirtualX->InternAtom("XdndActionMove", kFALSE);
   fgDNDactionLink    = gVirtualX->InternAtom("XdndActionLink", kFALSE);
   fgDNDactionAsk     = gVirtualX->InternAtom("XdndActionAsk", kFALSE);
   fgDNDactionPrivate = gVirtualX->InternAtom("XdndActionPrivate", kFALSE);
   
   fgDNDtypeList      = gVirtualX->InternAtom("XdndTypeList", kFALSE);
   fgDNDactionList    = gVirtualX->InternAtom("XdndActionList", kFALSE);
   fgDNDactionDescrip = gVirtualX->InternAtom("XdndActionDescription", kFALSE);
   
   fgXAWMState = gVirtualX->InternAtom("WM_STATE", kFALSE);
   fgXCDNDData = gVirtualX->InternAtom("_XC_DND_DATA", kFALSE);
}
static int ArrayLength(Atom_t *a)
{
   
   int n;
   for (n = 0; a[n]; n++);
   return n;
}
Bool_t TGDNDManager::IsDNDAware(Window_t win, Atom_t *typelist)
{
   
   return gVirtualX->IsDNDAware(win, typelist);
}
Window_t TGDNDManager::FindWindow(Window_t root, int x, int y, int maxd)
{
   
   if (maxd <= 0) return kNone;
   if (fDragWin && fDragWin->HasWindow(root)) return kNone;
   return gVirtualX->FindRWindow(root, fDragWin ? fDragWin->GetId() : 0,
                                 fDragWin ? fDragWin->GetInputId() : 0,
                                 x, y, maxd);
}
Window_t TGDNDManager::GetRootProxy()
{
   
   Atom_t actual;
   Int_t format = 32;
   ULong_t count, remaining;
   unsigned char *data = 0;
   Window_t win, proxy = kNone;
   
   
   gVirtualX->UpdateWindow(0);
   
   
   gVirtualX->GetProperty(gVirtualX->GetDefaultRootWindow(),
                          fgDNDproxy, 0, 1, kFALSE, XA_WINDOW,
                          &actual, &format, &count, &remaining, &data);
   if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
      
      win = *((Window_t *) data);
      delete[] data;
      data = 0;
      gVirtualX->GetProperty(win, fgDNDproxy, 0, 1, kFALSE, XA_WINDOW,
                             &actual, &format, &count, &remaining, &data);
      
      gVirtualX->UpdateWindow(0);
      if ((actual == XA_WINDOW) && (format == 32) && (count > 0) && data) {
         if (*((Window_t *) data) == win) {
            
            proxy = win;
         }
      }
   }
   if (data) delete[] data;
   
   return proxy;
}
Bool_t TGDNDManager::HandleClientMessage(Event_t *event)
{
   
   if (event->fHandle == fgDNDenter) {
      HandleDNDenter((Window_t) event->fUser[0], event->fUser[1],
                     (Atom_t *) &event->fUser[2]);
   } else if (event->fHandle == fgDNDleave) {
      HandleDNDleave((Window_t) event->fUser[0]);
   } else if (event->fHandle == fgDNDposition) {
      HandleDNDposition((Window_t) event->fUser[0],
                       (Int_t) (event->fUser[2] >> 16) & 0xFFFF,  
                       (Int_t) (event->fUser[2] & 0xFFFF),        
                       (Atom_t) event->fUser[4],                  
                       (Time_t) event->fUser[3]);                 
   } else if (event->fHandle == fgDNDstatus) {
      Rectangle_t skip;
      skip.fX      = (event->fUser[2] >> 16) & 0xFFFF;
      skip.fY      = (event->fUser[2] & 0xFFFF);
      skip.fWidth  = (event->fUser[3] >> 16) & 0xFFFF;
      skip.fHeight = (event->fUser[3] & 0xFFFF);
      HandleDNDstatus((Window_t) event->fUser[0],
                      (int) (event->fUser[1] & 0x1),
                       skip, (Atom_t) event->fUser[4]);
   } else if (event->fHandle == fgDNDdrop) {
      HandleDNDdrop((Window_t) event->fUser[0], (Time_t) event->fUser[2]);
   } else if (event->fHandle == fgDNDfinished) {
      HandleDNDfinished((Window_t) event->fUser[0]);
   } else {
      return kFALSE;  
   }
   return kTRUE;
}
Bool_t TGDNDManager::HandleTimer(TTimer *t)
{
   
   if (t == fDropTimeout) {
      
      
      
      delete fDropTimeout;
      fDropTimeout = 0;
      SendDNDleave(fTarget);
      fStatusPending = kFALSE;
      if (fLocalSource) fLocalSource->HandleDNDfinished();
      return kTRUE;
   }
   return kFALSE;
}
void TGDNDManager::SendDNDenter(Window_t target)
{
   
   Int_t i, n;
   Event_t event;
   event.fType   = kClientMessage;
   event.fWindow = target;
   event.fHandle = fgDNDenter;
   event.fFormat = 32;
   event.fUser[0] = fMain->GetId();  
   n = ArrayLength(fTypelist);
   event.fUser[1] = ((n > 3) ? 1L : 0L) | (fUseVersion << 24);
   
   for (i = 0; i < 3; ++i)
      event.fUser[2+i] = (i < n) ? fTypelist[i] : kNone;
   if (fLocalSource) {
      TDNDdata *dnddata = 0;
      Atom_t dataType;
      
      if (fLocalSource)
         dnddata = fLocalSource->GetDNDdata(0);
      dataType = dnddata ? (Atom_t) dnddata->fDataType : (Atom_t) kNone;
      event.fUser[2] = dataType;
      event.fUser[3] = kNone;
      event.fUser[4] = kNone;
   }
   
   gVirtualX->SendEvent(target, &event);
}
void TGDNDManager::SendDNDleave(Window_t target)
{
   
   Event_t event;
   event.fType    = kClientMessage;
   event.fWindow  = target;
   event.fHandle  = fgDNDleave;
   event.fFormat  = 32;
   event.fUser[0] = fMain->GetId();  
   event.fUser[1] = 0L;
   event.fUser[2] = 0L;
   event.fUser[3] = 0L;
   event.fUser[4] = 0L;
   gVirtualX->SendEvent(target, &event);
}
void TGDNDManager::SendDNDposition(Window_t target, int x, int y,
                                  Atom_t action, Time_t timestamp)
{
   
   Event_t event;
   event.fType    = kClientMessage;
   event.fWindow  = target;
   event.fHandle  = fgDNDposition;
   event.fFormat  = 32;
   event.fUser[0] = fMain->GetId();  
   event.fUser[1] = 0L;
   event.fUser[2] = (x << 16) | y;   
   event.fUser[3] = timestamp;       
   event.fUser[4] = action;          
   gVirtualX->SendEvent(target, &event);
}
void TGDNDManager::SendDNDstatus(Window_t source, Atom_t action)
{
   
   Event_t event;
   event.fType    = kClientMessage;
   event.fWindow  = source;
   event.fHandle  = fgDNDstatus;
   event.fFormat  = 32;
   event.fUser[0] = fMain->GetId();    
   event.fUser[1] = (action == kNone) ? 0L : 1L;
   event.fUser[2] = 0L;                
   event.fUser[3] = 0L;
   event.fUser[4] = action;            
   gVirtualX->SendEvent(source, &event);
}
void TGDNDManager::SendDNDdrop(Window_t target)
{
   
   Event_t event;
   event.fType    = kClientMessage;
   event.fWindow  = target;
   event.fHandle  = fgDNDdrop;
   event.fFormat  = 32;
   event.fUser[0] = fMain->GetId();    
   event.fUser[1] = 0L;                
   event.fUser[2] = 0L; 
   event.fUser[3] = 0L;
   event.fUser[4] = 0L;
   gVirtualX->SendEvent(target, &event);
}
void TGDNDManager::SendDNDfinished(Window_t source)
{
   
   Event_t event;
   event.fType    = kClientMessage;
   event.fWindow  = source;
   event.fHandle  = fgDNDfinished;
   event.fFormat  = 32;
   event.fUser[0] = fMain->GetId();    
   event.fUser[1] = 0L;                
   event.fUser[2] = 0L;
   event.fUser[3] = 0L;
   event.fUser[4] = 0L;
   gVirtualX->SendEvent(source, &event);
}
Bool_t TGDNDManager::HandleDNDenter(Window_t src, Long_t vers, Atom_t dataTypes[3])
{
   
   fSource = src;
   if (fDraggerTypes) delete[] fDraggerTypes;
   if (vers & 1) {  
      Atom_t type, *a;
      Int_t format = 32;
      ULong_t i, count, remaining;
      unsigned char *data = 0;
      gVirtualX->GetProperty(src, fgDNDtypeList,
                             0, 0x8000000L, kFALSE, XA_ATOM,
                             &type, &format, &count, &remaining, &data);
      if (type != XA_ATOM || format != 32 || !data) {
         count = 0;
      }
      fDraggerTypes = new Atom_t[count+4];
      a = (Atom_t *) data;
      for (i = 0; i < count; i++)
         fDraggerTypes[i] = a[i];
      fDraggerTypes[i] = kNone;
      if (data) delete[] data;
   } else {
      fDraggerTypes = new Atom_t[4];
      fDraggerTypes[0] = dataTypes[0];
      fDraggerTypes[1] = dataTypes[1];
      fDraggerTypes[2] = dataTypes[2];
      fDraggerTypes[3] = kNone;
   }
   
   
   if (fLocalTarget) fLocalTarget->HandleDNDleave();
   fLocalTarget = 0;
   return kTRUE;
}
Bool_t TGDNDManager::HandleDNDleave(Window_t )
{
   
   fSource = kNone;
   if (fLocalTarget) fLocalTarget->HandleDNDleave();
   fLocalTarget = 0;
   if (fDraggerTypes) delete[] fDraggerTypes;
   fDraggerTypes = 0;
   return kTRUE;
}
Bool_t TGDNDManager::HandleDNDposition(Window_t source, Int_t x_root, Int_t y_root,
                                      Atom_t action, Time_t )
{
   
   Int_t x, y;
   Window_t child;
   TGFrame *f = 0, *main = 0;
   TGWindow *w = 0;
   Window_t wtarget = 0;
   wtarget = FindWindow(gVirtualX->GetDefaultRootWindow(), x_root, y_root, 10);
   if (wtarget) {
      gVirtualX->TranslateCoordinates(gVirtualX->GetDefaultRootWindow(),
                                      wtarget, x_root, y_root, x, y, child);
      w = gClient->GetWindowById(wtarget);
      if (w)
         f = dynamic_cast<TGFrame *>(w);
   }
   if (f != fLocalTarget) {
      if (fLocalTarget) fLocalTarget->HandleDNDleave();
      fLocalTarget = f;
      if (fLocalTarget) {
         main = (TGFrame *)fLocalTarget->GetMainFrame();
         main->RaiseWindow();
         if (fMain == 0)
            fMain = main;
         fDropType = fLocalTarget->HandleDNDenter(fDraggerTypes);
      }
   }
   
   
   if (fLocalTarget) {
      action = (fDropType == kNone) ? kNone :
              fLocalTarget->HandleDNDposition(x, y, action, x_root, y_root);
   } else if (fProxyOurs) {
      action = fMain->HandleDNDposition(x, y, action, x_root, y_root);
   } else {
      action = kNone;
   }
   SendDNDstatus(source, fLocalAction = action);
   return kTRUE;
}
Bool_t TGDNDManager::HandleDNDstatus(Window_t target, Int_t accepted,
                                    Rectangle_t , Atom_t action)
{
   
   if (target) {
      fStatusPending = kFALSE;
      if (accepted) {
         fDropAccepted = kTRUE;
         fAcceptedAction = action;
         if (fDragWin)
            gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
                                               fGrabEventMask, kNone);
      } else {
         fDropAccepted = kFALSE;
         fAcceptedAction = kNone;
         if (fDragWin)
            gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(),
                                               fGrabEventMask,
                                               fDNDNoDropCursor);
      }
      if (fDropTimeout) {   
         delete fDropTimeout;
         fDropTimeout = 0;
         SendDNDdrop(fTarget);
      }
   }
   return kTRUE;
}
Bool_t TGDNDManager::HandleDNDdrop(Window_t source, Time_t timestamp)
{
   
   
   
   
   
   if (fMain && fDropType != kNone) {
      gVirtualX->ChangeProperties(fMain->GetId(), fgXCDNDData, fDropType,
                                  8, (unsigned char *) 0, 0);
      gVirtualX->ConvertSelection(fMain->GetId(), fgDNDselection, fDropType,
                                  fgXCDNDData, timestamp);
   }
   fSource = source;
   SendDNDfinished(source);
   return kTRUE;
}
Bool_t TGDNDManager::HandleDNDfinished(Window_t )
{
   
   if (fLocalSource) fLocalSource->HandleDNDfinished();
   return kTRUE;
}
Bool_t TGDNDManager::HandleSelectionRequest(Event_t *event)
{
   
   if ((Atom_t)event->fUser[1] == fgDNDselection) {
      Event_t xevent;
      TDNDdata *dnddata = 0;
      char *data;
      int len;
      
      if (fLocalSource)
         dnddata = fLocalSource->GetDNDdata(event->fUser[2]);
      data = dnddata ? (char *) dnddata->fData : (char *) "";
      len  = dnddata ? dnddata->fDataLength : 0;
      if ((Atom_t)event->fUser[3] == kNone) {
         
         event->fUser[3] = fgXCDNDData;
      }
      gVirtualX->ChangeProperties(event->fUser[0], event->fUser[3],
                                  event->fUser[2], 8,
                                  (unsigned char *) data, len);
      xevent.fType    = kSelectionNotify;
      xevent.fTime    = event->fTime;
      xevent.fUser[0] = event->fUser[0]; 
      xevent.fUser[1] = event->fUser[1]; 
      xevent.fUser[2] = event->fUser[2]; 
      xevent.fUser[3] = event->fUser[3]; 
      gVirtualX->SendEvent(event->fUser[0], &xevent);
      return kTRUE;
   } else {
      return kFALSE;  
   }
}
Bool_t TGDNDManager::HandleSelection(Event_t *event)
{
   
   if ((Atom_t)event->fUser[1] == fgDNDselection) {
      Atom_t actual = fDropType;
      Int_t format = 8;
      ULong_t count, remaining;
      unsigned char *data = 0;
      gVirtualX->GetProperty(event->fUser[0], event->fUser[3],
                             0, 0x8000000L, kTRUE, event->fUser[2],
                             &actual, &format, &count, &remaining, &data);
      if ((actual != fDropType) || (format != 8) || (count == 0) || !data) {
         if (data) delete[] data;
         return kFALSE;
      }
      if (fSource != kNone) SendDNDfinished(fSource);
      
      if (fLocalTarget) {
         TDNDdata dndData(actual, data, count, fLocalAction);
         fLocalTarget->HandleDNDdrop(&dndData);
         if (fDraggerTypes) delete[] fDraggerTypes;
         fDraggerTypes = 0;
      }
      fSource = kNone;
      fLocalAction = kNone;
      return kTRUE;
   } else {
      return kFALSE;  
   }
}
void TGDNDManager::SetDragPixmap(Pixmap_t pic, Pixmap_t mask,
                                int hot_x, int hot_y)
{
   
   fPic  = pic;
   fMask = mask;
   fHotx = hot_x;
   fHoty = hot_y;
}
Bool_t TGDNDManager::StartDrag(TGFrame *src, int x_root, int y_root,
                              Window_t grabWin)
{
   
   if (fDragging) return kTRUE;
   fLocalSource = src;
   if ((TGWindow *)fMain != src->GetMainFrame()) {
      fMain = (TGFrame *)src->GetMainFrame();
   }
   if (!gVirtualX->SetSelectionOwner(fMain->GetId(), fgDNDselection)) {
      
      return kFALSE;
   }
   if (grabWin == kNone) grabWin = fMain->GetId();
   gVirtualX->GrabPointer(grabWin, fGrabEventMask, kNone, fDNDNoDropCursor, kTRUE, kFALSE);
   fLocalTarget = 0;
   fDragging = kTRUE;
   fTarget = kNone;
   fTargetIsDNDaware = kFALSE;
   fStatusPending = kFALSE;
   if (fDropTimeout) delete fDropTimeout;
   fDropTimeout = 0;
   fDropAccepted = kFALSE;
   fAcceptedAction = kNone;
   fLocalAction = kNone;
   if (!fDragWin && fPic != kNone && fMask != kNone) {
      fDragWin = new TGDragWindow(gClient->GetDefaultRoot(), fPic, fMask);
      fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
      fDragWin->MapSubwindows();
      fDragWin->MapRaised();
   }
   return kTRUE;
}
Bool_t TGDNDManager::Drop()
{
   
   if (!fDragging) return kFALSE;
   if (fTargetIsDNDaware) {
      if (fDropAccepted) {
         if (fStatusPending) {
            if (fDropTimeout) delete fDropTimeout;
            fDropTimeout = new TTimer(this, 5000);
         } else {
            SendDNDdrop(fTarget);
         }
      } else {
         SendDNDleave(fTarget);
         fStatusPending = kFALSE;
      }
   }
   EndDrag();
   return kTRUE;
}
Bool_t TGDNDManager::EndDrag()
{
   
   if (!fDragging) return kFALSE;
   gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
   if (fSource)
      SendDNDfinished(fSource);
   if (fLocalSource)
      fLocalSource->HandleDNDfinished();
   fDragging = kFALSE;
   if (fDragWin) {
      fDragWin->DeleteWindow();
      fDragWin = 0;
   }
   return kTRUE;
}
Bool_t TGDNDManager::Drag(int x_root, int y_root, Atom_t action, Time_t timestamp)
{
   
   if (!fDragging) return kFALSE;
   Window_t newTarget = FindWindow(gVirtualX->GetDefaultRootWindow(),
                                   x_root, y_root, 10);
   if (newTarget == kNone) {
      Window_t t = GetRootProxy();
      if (t != kNone) newTarget = t;
   }
   if (fTarget != newTarget) {
      if (fTargetIsDNDaware) SendDNDleave(fTarget);
      fTarget = newTarget;
      fTargetIsDNDaware = IsDNDAware(fTarget);
      fStatusPending = kFALSE;
      fDropAccepted = kFALSE;
      fAcceptedAction = kNone;
      if (fTargetIsDNDaware) SendDNDenter(fTarget);
      if (fDragWin)
         gVirtualX->ChangeActivePointerGrab(fDragWin->GetId(), fGrabEventMask,
                                            fDNDNoDropCursor);
   }
   if (fTargetIsDNDaware && !fStatusPending) {
      SendDNDposition(fTarget, x_root, y_root, action, timestamp);
      
      
      fStatusPending = kTRUE;
   }
   if (fDragWin) {
      fDragWin->RaiseWindow();
      fDragWin->Move((x_root-fHotx)|1, (y_root-fHoty)|1);
   }
   return kTRUE;
}
Bool_t TGDNDManager::SetRootProxy()
{
   
   Window_t mainw = fMain->GetId();
   int result = kFALSE;
   if (GetRootProxy() == kNone) {
      gVirtualX->ChangeProperties(gVirtualX->GetDefaultRootWindow(),
                                  fgDNDproxy, XA_WINDOW, 32,
                                  (unsigned char *) &mainw, 1);
      gVirtualX->ChangeProperties(mainw, fgDNDproxy, XA_WINDOW, 32,
                                  (unsigned char *) &mainw, 1);
      fProxyOurs = kTRUE;
      result = kTRUE;
   }
   
   gVirtualX->UpdateWindow(0);
   return result;
}
Bool_t TGDNDManager::RemoveRootProxy()
{
   
   if (!fProxyOurs) return kFALSE;
   gVirtualX->DeleteProperty(fMain->GetId(), fgDNDproxy);
   gVirtualX->DeleteProperty(gVirtualX->GetDefaultRootWindow(), fgDNDproxy);
   
   
   
   
   gVirtualX->UpdateWindow(0);
   fProxyOurs = kFALSE;
   return kTRUE;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.