vlc/vlc-3.0 | branch: master | Erwan Tulou <[email protected]> | 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 <[email protected]> > 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 ); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
