* drag & drop for X11 skins. Still mysterious problems but it's better
authorCyril Deguet <asmax@videolan.org>
Mon, 9 Jun 2003 00:07:09 +0000 (00:07 +0000)
committerCyril Deguet <asmax@videolan.org>
Mon, 9 Jun 2003 00:07:09 +0000 (00:07 +0000)
  than nothing

modules/gui/skins/x11/x11_dragdrop.cpp
modules/gui/skins/x11/x11_dragdrop.h
modules/gui/skins/x11/x11_window.cpp

index 000cd4c..b981d11 100644 (file)
@@ -2,7 +2,7 @@
  * x11_dragdrop.cpp: X11 implementation of the drag & drop
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: x11_dragdrop.cpp,v 1.2 2003/06/08 18:17:50 asmax Exp $
+ * $Id: x11_dragdrop.cpp,v 1.3 2003/06/09 00:07:09 asmax Exp $
  *
  * Authors: Cyril Deguet     <asmax@videolan.org>
  *
 
 //--- X11 -------------------------------------------------------------------
 #include <X11/Xlib.h>
+#include <X11/Xatom.h>
 
 //--- VLC -------------------------------------------------------------------
 #include <vlc/intf.h>
 
 //--- SKIN ------------------------------------------------------------------
+#include "../src/skin_common.h"
 #include "../src/event.h"
 #include "../os_api.h"
+#include "../src/theme.h"
+#include "../os_theme.h"
 #include "x11_dragdrop.h"
 
+#include <string.h>
+
 
 //---------------------------------------------------------------------------
-X11DropObject::X11DropObject( intf_thread_t *_p_intf )
+X11DropObject::X11DropObject( intf_thread_t *_p_intf, Window win)
 {
     p_intf = _p_intf;
+    Win = win;
+    display = p_intf->p_sys->display;
 }
 //---------------------------------------------------------------------------
 X11DropObject::~X11DropObject()
@@ -48,89 +56,149 @@ X11DropObject::~X11DropObject()
 //---------------------------------------------------------------------------
 void X11DropObject::DndEnter( ldata_t data )
 {
-    fprintf(stderr,"dnd enter\n");
-}
-//---------------------------------------------------------------------------
-void X11DropObject::DndPosition( ldata_t data )
-{
-    fprintf(stderr,"dnd position\n");
-}
-//---------------------------------------------------------------------------
-void X11DropObject::DndLeave( ldata_t data )
-{
-    fprintf(stderr,"dnd leave\n");
-}
-//---------------------------------------------------------------------------
-void X11DropObject::DndDrop( ldata_t data )
-{
-    fprintf(stderr,"dnd drop\n");
-}
-#if 0
-void X11DropObject::HandleDropStart( GdkDragContext *context )
-{
-/*    GdkAtom atom = gdk_drag_get_selection( context );
-    
-    guchar *buffer;
-    GdkAtom prop_type;
-    gint prop_format;
-    
-    // Get the owner of the selection
-    GdkWindow *owner = gdk_selection_owner_get( atom ); 
+    Window src = data[0];
 
-    // Find the possible targets for the selection
-    string target = "";
-    gdk_selection_convert( owner, atom, gdk_atom_intern("TARGETS", FALSE), 
-                           OSAPI_GetTime() );
-    int len = gdk_selection_property_get( owner, &buffer, &prop_type, 
-                                          &prop_format );
-    for( int i = 0; i < len / sizeof(GdkAtom); i++ )
+    // Retrieve available data types
+    list<string> dataTypes;
+    if( data[1] & 1 )   // more than 3 data types ?
     {
-        GdkAtom atom = ( (GdkAtom*)buffer )[i];
-        gchar *name = gdk_atom_name( atom );
-        if( name )
+        Atom type;
+        int format;
+        unsigned long nitems, nbytes;
+        Atom *dataList;
+        XLOCK;
+        Atom typeListAtom = XInternAtom( display, "XdndTypeList", 0 );
+        XGetWindowProperty( display, src, typeListAtom, 0, 65536, False,
+                            XA_ATOM, &type, &format, &nitems, &nbytes,  
+                            (unsigned char**)&dataList );
+        XUNLOCK;
+        for( unsigned long i=0; i<nitems; i++ )
         {
-            string curTarget = name;
-            if( (curTarget == "text/plain" || curTarget == "STRING") )
+            XLOCK;
+            string dataType = XGetAtomName( display, dataList[i] );
+            XUNLOCK;
+            dataTypes.push_back( dataType );
+        }
+        XFree( (void*)dataList );
+    }
+    else
+    {
+        for( int i=2; i<5; i++ )
+        {
+            if( data[i] != None )
             {
-                target = curTarget;
-                break;
+                XLOCK;
+                string dataType = XGetAtomName( display, data[i] );
+                XUNLOCK;
+                dataTypes.push_back( dataType );
             }
         }
     }
 
-    if( target == "" )
+    // Find the right target
+    target = None;
+    list<string>::iterator it;
+    for( it = dataTypes.begin(); it != dataTypes.end(); it++ )
+    {
+        if( *it == "text/plain" || *it == "STRING" )
+        {
+            XLOCK;
+            target = XInternAtom( display, (*it).c_str(), 0 );
+            XUNLOCK;
+            break;
+        }
+    }
+}
+//---------------------------------------------------------------------------
+void X11DropObject::DndPosition( ldata_t data )
+{   
+    Window src = data[0];
+    
+    XLOCK;
+    Atom actionAtom = XInternAtom( display, "XdndActionCopy", 0 );
+    Atom typeAtom = XInternAtom( display, "XdndStatus", 0 );
+
+    XEvent event;
+    event.type = ClientMessage;
+    event.xclient.window = src;
+    event.xclient.display = display;
+    event.xclient.message_type = typeAtom;
+    event.xclient.format = 32;
+    event.xclient.data.l[0] = Win;
+    if( target != None )
     {
-        msg_Warn( p_intf, "Drag&Drop: target not found\n" );
+        event.xclient.data.l[1] = 1;          // accept the drop
     }
     else
     {
-        gdk_selection_convert( owner, atom, gdk_atom_intern(target.c_str(), 
-                               FALSE), OSAPI_GetTime() );
-        len = gdk_selection_property_get( owner, &buffer, &prop_type, 
-                                          &prop_format);
-        OSAPI_PostMessage( NULL, VLC_DROP, (unsigned int)buffer, 0 );
+        event.xclient.data.l[1] = 0;          // do not accept
     }
-*/
-/*    // Get number of files that are dropped into vlc
-    int NbFiles = DragQueryFile( (HDROP)HDrop, 0xFFFFFFFF, NULL, 0 );
+    event.xclient.data.l[2] = 0;              // empty rectangle
+    event.xclient.data.l[3] = 0;
+    event.xclient.data.l[4] = actionAtom;
+    // Tell the source whether we accept the drop
+    XSendEvent( display, src, False, 0, &event );
+    XUNLOCK;
+}
+//---------------------------------------------------------------------------
+void X11DropObject::DndLeave( ldata_t data )
+{
+}
+//---------------------------------------------------------------------------
+void X11DropObject::DndDrop( ldata_t data )
+{
+    Window src = data[0];
+    Time time = data[2];
 
-    // For each dropped files
-    for( int i = 0; i < NbFiles; i++ )
-    {
-        // Get the name of the file
-        int NameLength = DragQueryFile( (HDROP)HDrop, i, NULL, 0 ) + 1;
-        char *FileName = new char[NameLength];
-        DragQueryFile( (HDROP)HDrop, i, FileName, NameLength );
+    XLOCK;
+    Atom selectionAtom = XInternAtom( display, "XdndSelection", 0 );
+    Atom targetAtom = XInternAtom( display, "text/plain", 0 );
+    Atom propAtom = XInternAtom( display, "VLC_SELECTION", 0 );
+   
+    Atom actionAtom = XInternAtom( display, "XdndActionCopy", 0 );
+    Atom typeAtom = XInternAtom( display, "XdndFinished", 0 );
 
-        // The pointer must not be deleted here because it will be deleted
-        // in the VLC specific messages processing function
-        PostMessage( NULL, VLC_DROP, (WPARAM)FileName, 0 );
-    }
+    // Convert the selection into the given target
+    XConvertSelection( display, selectionAtom, targetAtom, propAtom, src, 
+                       time );
 
-    DragFinish( (HDROP)HDrop );
+    // Read the selection 
+    Atom type;
+    int format;
+    unsigned long nitems, nbytes;
+    char *buffer;
+    XGetWindowProperty( display, src, propAtom, 0, 1024, False, 
+                        AnyPropertyType, &type, &format, &nitems, &nbytes, 
+                        (unsigned char**)&buffer );
+    string selection = buffer;
+    XFree( buffer );
+    XUNLOCK;
     
-*/
-  //  gdk_drop_finish( context, TRUE,OSAPI_GetTime() );
+    // Find the protocol, if any
+    string::size_type pos = selection.find( ":", 0 );
+    if( selection.find("///", pos + 1 ) == pos + 1 )
+    {
+        selection.erase( pos + 1, 2 );
+    }
+    
+    char *name = new char[selection.size()+1];
+    strncpy( name, selection.c_str(), selection.size()+1 );
+    msg_Dbg( p_intf, "drop: %s\n", name );
+    OSAPI_PostMessage( NULL, VLC_DROP, (unsigned int)name, 0 );
+    
+    // Tell the source we accepted the drop
+    XEvent event;
+    event.type = ClientMessage;
+    event.xclient.window = src;
+    event.xclient.display = display;
+    event.xclient.message_type = typeAtom;
+    event.xclient.format = 32;
+    event.xclient.data.l[0] = Win;
+    event.xclient.data.l[1] = 1;          // drop accepted
+    event.xclient.data.l[2] = actionAtom;
+    XLOCK;
+    XSendEvent( display, src, False, 0, &event );
+    XUNLOCK;
 }
 #endif
-#endif
index f2c1117..a4263ad 100644 (file)
@@ -2,7 +2,7 @@
  * x11_dragdrop.h: X11 implementation of the drag & drop
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: x11_dragdrop.h,v 1.2 2003/06/08 18:17:50 asmax Exp $
+ * $Id: x11_dragdrop.h,v 1.3 2003/06/09 00:07:09 asmax Exp $
  *
  * Authors: Cyril Deguet     <asmax@videolan.org>
  *
@@ -37,9 +37,12 @@ class X11DropObject
 {
     private:
         intf_thread_t *p_intf;
-
+        Window Win;
+        Display *display;
+        Atom target;
+        
     public:
-       X11DropObject( intf_thread_t *_p_intf );
+       X11DropObject( intf_thread_t *_p_intf, Window win );
        virtual ~X11DropObject();
 
        void DndEnter( ldata_t data );
index 8121a81..9c51f99 100644 (file)
@@ -2,7 +2,7 @@
  * x11_window.cpp: X11 implementation of the Window class
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: x11_window.cpp,v 1.17 2003/06/08 18:40:10 gbazin Exp $
+ * $Id: x11_window.cpp,v 1.18 2003/06/09 00:07:09 asmax Exp $
  *
  * Authors: Cyril Deguet     <asmax@videolan.org>
  *
@@ -85,7 +85,7 @@ X11Window::X11Window( intf_thread_t *p_intf, Window wnd, int x, int y,
     if( DragDrop )
     {
         // register the listview as a drop target
-        DropObject = new X11DropObject( p_intf );
+        DropObject = new X11DropObject( p_intf, Wnd );
 
         Atom xdndAtom = XInternAtom( display, "XdndAware", False );
         char xdndVersion = 4;
@@ -160,7 +160,9 @@ X11Window::~X11Window()
 //---------------------------------------------------------------------------
 void X11Window::OSShow( bool show )
 {
+    XLOCK;
     XResizeWindow( display, Wnd, 1, 1 ); // Avoid flicker
+    XUNLOCK;
 
     if( show )
     {
@@ -343,8 +345,10 @@ bool X11Window::ProcessOSEvent( Event *evt )
 
         case ClientMessage:
             {
+            XLOCK;
             string type = XGetAtomName( display, ( (XClientMessageEvent*)
                                                     p2 )->message_type );
+            XUNLOCK;
             if( type == "XdndEnter" )
             {
                 DropObject->DndEnter( ((XClientMessageEvent*)p2)->data.l );