[vlc-commits] skins2(x11): fix Drag&Drop issues on X11.

Erwan Tulou git at videolan.org
Wed Jan 17 00:39:57 CET 2018


vlc/vlc-3.0 | branch: master | Erwan Tulou <erwan10 at videolan.org> | Tue Jan 16 19:02:13 2018 +0100| [715833ba19414b26128098c802a2e2183d4fa673] | committer: Erwan Tulou

skins2(x11): fix Drag&Drop issues on X11.

this patch fixes issues that limited the scope of Drag&Drop.
- set the version number to the latest one (version 5 in 2003!)
- ensure the data type is not hardcoded but selected at runtime.
- add a XSync to ascertain full completion of Drag and Drop.
- protect against possible overflow
- add some debugging info

(cherry picked from commit c5213920b8fb6d5a5ed5c430356831f14c170a6a)
Signed-off-by: Erwan Tulou <erwan10 at videolan.org>

> http://git.videolan.org/gitweb.cgi/vlc/vlc-3.0.git/?a=commit;h=715833ba19414b26128098c802a2e2183d4fa673
---

 modules/gui/skins2/x11/x11_dragdrop.cpp | 64 +++++++++++++++++++--------------
 modules/gui/skins2/x11/x11_window.cpp   |  2 +-
 2 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/modules/gui/skins2/x11/x11_dragdrop.cpp b/modules/gui/skins2/x11/x11_dragdrop.cpp
index 47587fbfa3..9244a2532e 100644
--- a/modules/gui/skins2/x11/x11_dragdrop.cpp
+++ b/modules/gui/skins2/x11/x11_dragdrop.cpp
@@ -48,7 +48,9 @@ X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
 void X11DragDrop::dndEnter( ldata_t data )
 {
     Window src = data[0];
+    int version = data[1]>>24;
     m_xPos = m_yPos = -1;
+    (void)version;
 
     // Retrieve available data types
     std::list<std::string> dataTypes;
@@ -81,16 +83,23 @@ void X11DragDrop::dndEnter( ldata_t data )
         }
     }
 
+    // list all data types available
+    std::list<std::string>::iterator it;
+    for( it = dataTypes.begin(); it != dataTypes.end(); ++it )
+        msg_Dbg( getIntf(), "D&D data type: %s", (*it).c_str() );
+
     // Find the right target
     m_target = None;
-    std::list<std::string>::iterator it;
     for( it = dataTypes.begin(); it != dataTypes.end(); ++it )
     {
         if( *it == "text/uri-list" ||
             *it == "text/plain" ||
-            *it == "STRING" )
+            *it == "text/plain;charset=utf-8" ||
+            *it == "STRING" ||
+            *it == "UTF8_STRING" )
         {
             m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
+            msg_Dbg( getIntf(), "D&D data type chosen: %s", (*it).c_str() );
             break;
         }
     }
@@ -107,22 +116,11 @@ void X11DragDrop::dndPosition( ldata_t data )
     m_xPos = data[2] >> 16;
     m_yPos = data[2] & 0xffff;
     Time time = data[3];
-
-    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
-    //Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
-    Atom targetAtom = XInternAtom( XDISPLAY, "text/uri-list", 0 );
-    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
+    Atom action = data[4];
+    (void)time; (void)action;
 
     Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
-    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
-
-    // Convert the selection into the given target
-    // NEEDED or it doesn't work!
-    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
-                       time );
-
-    actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
-    typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
+    Atom typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
 
     XEvent event;
     event.type = ClientMessage;
@@ -149,6 +147,8 @@ void X11DragDrop::dndPosition( ldata_t data )
 void X11DragDrop::dndLeave( ldata_t data )
 {
     (void)data;
+    m_target = None;
+
     // transmit DragLeave event
     EvtDragLeave evt( getIntf() );
     m_pWin->processEvent( evt );
@@ -163,26 +163,33 @@ void X11DragDrop::dndDrop( ldata_t data )
     Time time = data[2];
 
     Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
-    Atom targetAtom = XInternAtom( XDISPLAY, "text/uri-list", 0 );
     Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
-
-    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
-    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
-
     // Convert the selection into the given target
-    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
+    XConvertSelection( XDISPLAY, selectionAtom, m_target, propAtom, src,
                        time );
+    // Needed to ensure XGetWindowProperty returns something
+    XSync( XDISPLAY, False );
 
     // Read the selection
     Atom type;
     int format;
-    unsigned long nitems, nbytes;
+    unsigned long nitems, nbytes_after_return;
     char *buffer;
-    XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
-                        AnyPropertyType, &type, &format, &nitems, &nbytes,
-                        (unsigned char**)&buffer );
+    long length_max = 1024;
+    XGetWindowProperty( XDISPLAY, src, propAtom, 0, length_max, False,
+                        AnyPropertyType, &type, &format, &nitems,
+                        &nbytes_after_return, (unsigned char**)&buffer );
+    if( buffer && nbytes_after_return > 0 )
+    {
+        XFree( buffer );
+        length_max += nbytes_after_return;
+        XGetWindowProperty( XDISPLAY, src, propAtom, 0, length_max, False,
+                        AnyPropertyType, &type, &format, &nitems,
+                        &nbytes_after_return, (unsigned char**)&buffer );
+    }
     if( buffer != NULL )
     {
+        msg_Dbg( getIntf(), "buffer received: %s", buffer );
         char* psz_dup = strdup( buffer );
         char* psz_new = psz_dup;
         while( psz_new && *psz_new )
@@ -198,7 +205,7 @@ void X11DragDrop::dndDrop( ldata_t data )
                 skip = strlen( sep[i] );
                 break;
             }
-            if( *psz_new )
+            if( *psz_new && strstr( psz_new, "://" ) )
             {
                 files.push_back( psz_new );
             }
@@ -209,6 +216,9 @@ void X11DragDrop::dndDrop( ldata_t data )
         XFree( buffer );
     }
 
+    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
+    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
+
     // Tell the source we accepted the drop
     XEvent event;
     event.type = ClientMessage;
diff --git a/modules/gui/skins2/x11/x11_window.cpp b/modules/gui/skins2/x11/x11_window.cpp
index 57850299c4..e469ed64cb 100644
--- a/modules/gui/skins2/x11/x11_window.cpp
+++ b/modules/gui/skins2/x11/x11_window.cpp
@@ -148,7 +148,7 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
 
         // Register the window as a drop target
         Atom xdndAtom = XInternAtom( XDISPLAY, "XdndAware", False );
-        char xdndVersion = 4;
+        char xdndVersion = 5;
         XChangeProperty( XDISPLAY, m_wnd, xdndAtom, XA_ATOM, 32,
                          PropModeReplace, (unsigned char *)&xdndVersion, 1 );
 



More information about the vlc-commits mailing list