#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)
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);
}
ClassImp(TGDNDManager)
TGDNDManager::TGDNDManager(TGFrame *toplevel, Atom_t *typelist)
{
   
   if (gDNDManager)
      return;
   fMain = toplevel;
   fVersion = ROOTDND_PROTOCOL_VERSION;
   fUseVersion = kTRUE;
   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, 15);
   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, 15);
   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;
}
Last change: Tue May 13 17:07:54 2008
Last generated: 2008-05-13 17:07
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.