vlc | branch: master | Erwan Tulou <[email protected]> | Sun Jan 21 13:12:20 2018 +0100| [b4e31d4bc28d99b101838f954fc8378e5cecb2ee] | committer: Erwan Tulou
skins2(x11): improve Drag&Drop Rely on the XSelectionNotify event to ascertain DragNDrop data are available instead of blindly querying the property. This does fix Drag and Drop sometimes non functioning. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b4e31d4bc28d99b101838f954fc8378e5cecb2ee --- modules/gui/skins2/x11/x11_dragdrop.cpp | 106 +++++++++++++++++--------------- modules/gui/skins2/x11/x11_dragdrop.hpp | 1 + modules/gui/skins2/x11/x11_loop.cpp | 20 ++++++ 3 files changed, 77 insertions(+), 50 deletions(-) diff --git a/modules/gui/skins2/x11/x11_dragdrop.cpp b/modules/gui/skins2/x11/x11_dragdrop.cpp index 9244a2532e..9cfd4e7bbb 100644 --- a/modules/gui/skins2/x11/x11_dragdrop.cpp +++ b/modules/gui/skins2/x11/x11_dragdrop.cpp @@ -61,9 +61,10 @@ void X11DragDrop::dndEnter( ldata_t data ) unsigned long nitems, nbytes; Atom *dataList; Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 ); - XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False, - XA_ATOM, &type, &format, &nitems, &nbytes, - (unsigned char**)&dataList ); + if( XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, + False, XA_ATOM, &type, &format, &nitems, &nbytes, + (unsigned char**)&dataList ) != Success ) + return; for( unsigned long i=0; i<nitems; i++ ) { std::string dataType = XGetAtomName( XDISPLAY, dataList[i] ); @@ -88,20 +89,28 @@ void X11DragDrop::dndEnter( ldata_t data ) for( it = dataTypes.begin(); it != dataTypes.end(); ++it ) msg_Dbg( getIntf(), "D&D data type: %s", (*it).c_str() ); - // Find the right target + // data formats we accept sorted by preference + static const char* preferred[] = { + "text/uri-list", + "text/plain;charset=utf-8", + "text/plain", + "UTF8_STRING", + "STRING", + }; m_target = None; - for( it = dataTypes.begin(); it != dataTypes.end(); ++it ) + for( unsigned i = 0; i < sizeof(preferred)/sizeof(preferred[0]); i++ ) { - if( *it == "text/uri-list" || - *it == "text/plain" || - *it == "text/plain;charset=utf-8" || - *it == "STRING" || - *it == "UTF8_STRING" ) + for( it = dataTypes.begin(); it != dataTypes.end(); ++it ) { - m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 ); - msg_Dbg( getIntf(), "D&D data type chosen: %s", (*it).c_str() ); - break; + if( *it == preferred[i] ) + { + m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 ); + msg_Dbg( getIntf(), "Selected type: %s", (*it).c_str() ); + break; + } } + if( m_target != None ) + break; } // transmit DragEnter event @@ -162,32 +171,44 @@ void X11DragDrop::dndDrop( ldata_t data ) Window src = data[0]; Time time = data[2]; + // Convert the selection into the given target Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 ); Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 ); - // Convert the selection into the given target - XConvertSelection( XDISPLAY, selectionAtom, m_target, propAtom, src, - time ); - // Needed to ensure XGetWindowProperty returns something - XSync( XDISPLAY, False ); + XConvertSelection( XDISPLAY, selectionAtom, m_target, propAtom, + m_wnd, time ); + + + // Tell the source we accepted the drop + Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 ); + Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 ); + XEvent event; + event.type = ClientMessage; + event.xclient.window = src; + event.xclient.display = XDISPLAY; + event.xclient.message_type = typeAtom; + event.xclient.format = 32; + event.xclient.data.l[0] = m_wnd; + event.xclient.data.l[1] = 1; // drop accepted + event.xclient.data.l[2] = actionAtom; + XSendEvent( XDISPLAY, src, False, 0, &event ); +} + + +void X11DragDrop::dndSelectionNotify( ) +{ + std::list<std::string> files; // Read the selection Atom type; int format; unsigned long nitems, nbytes_after_return; 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 ) + Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 ); + int ret = XGetWindowProperty( XDISPLAY, m_wnd, propAtom, 0, 65536, True, + AnyPropertyType, &type, &format, &nitems, + &nbytes_after_return, + (unsigned char**)&buffer ); + if( ret == Success && buffer != NULL ) { msg_Dbg( getIntf(), "buffer received: %s", buffer ); char* psz_dup = strdup( buffer ); @@ -214,26 +235,11 @@ void X11DragDrop::dndDrop( ldata_t data ) } free( psz_dup ); 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; - event.xclient.window = src; - event.xclient.display = XDISPLAY; - event.xclient.message_type = typeAtom; - event.xclient.format = 32; - event.xclient.data.l[0] = m_wnd; - event.xclient.data.l[1] = 1; // drop accepted - event.xclient.data.l[2] = actionAtom; - XSendEvent( XDISPLAY, src, False, 0, &event ); - - // transmit DragDrop event - EvtDragDrop evt( getIntf(), m_xPos, m_yPos, files ); - m_pWin->processEvent( evt ); + // transmit DragDrop event + EvtDragDrop evt( getIntf(), m_xPos, m_yPos, files ); + m_pWin->processEvent( evt ); + } } #endif diff --git a/modules/gui/skins2/x11/x11_dragdrop.hpp b/modules/gui/skins2/x11/x11_dragdrop.hpp index a4fbbd67a0..968c2c1a04 100644 --- a/modules/gui/skins2/x11/x11_dragdrop.hpp +++ b/modules/gui/skins2/x11/x11_dragdrop.hpp @@ -45,6 +45,7 @@ public: void dndPosition( ldata_t data ); void dndLeave( ldata_t data ); void dndDrop( ldata_t data ); + void dndSelectionNotify( ); private: /// X11 display diff --git a/modules/gui/skins2/x11/x11_loop.cpp b/modules/gui/skins2/x11/x11_loop.cpp index 4355c9f232..54e4102aa2 100644 --- a/modules/gui/skins2/x11/x11_loop.cpp +++ b/modules/gui/skins2/x11/x11_loop.cpp @@ -360,6 +360,26 @@ void X11Loop::handleX11Event() pDnd->dndDrop( event.xclient.data.l ); break; } + + case SelectionNotify: + { + // Check XConvertSelection completion + if( event.xselection.property == None ) + { + msg_Err( getIntf(), "Convertion failed for Drag&Drop" ); + return; + } + + // Find the DnD object for this window + X11DragDrop *pDnd = pFactory->m_dndMap[event.xselection.requestor]; + if( !pDnd ) + { + msg_Err( getIntf(), "no associated D&D object" ); + return; + } + pDnd->dndSelectionNotify( ); + } + } } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
