1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@via.ecp.fr>
8 * Olivier Teulière <ipkiss@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
28 #include <X11/Xatom.h>
30 #include "x11_dragdrop.hpp"
31 #include "x11_display.hpp"
32 #include "x11_factory.hpp"
33 #include "../commands/cmd_add_item.hpp"
34 #include "../events/evt_dragndrop.hpp"
40 X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
41 Window win, bool playOnDrop, GenericWindow *pWin ):
42 SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
43 m_playOnDrop( playOnDrop ), m_pWin( pWin ), m_xPos( -1 ), m_yPos( -1 )
48 void X11DragDrop::dndEnter( ldata_t data )
53 // Retrieve available data types
54 list<string> dataTypes;
55 if( data[1] & 1 ) // More than 3 data types ?
59 unsigned long nitems, nbytes;
61 Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 );
62 XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False,
63 XA_ATOM, &type, &format, &nitems, &nbytes,
64 (unsigned char**)&dataList );
65 for( unsigned long i=0; i<nitems; i++ )
67 string dataType = XGetAtomName( XDISPLAY, dataList[i] );
68 dataTypes.push_back( dataType );
70 XFree( (void*)dataList );
74 for( int i = 2; i < 5; i++ )
78 string dataType = XGetAtomName( XDISPLAY, data[i] );
79 dataTypes.push_back( dataType );
84 // Find the right target
86 list<string>::iterator it;
87 for( it = dataTypes.begin(); it != dataTypes.end(); ++it )
89 if( *it == "text/uri-list" ||
90 *it == "text/plain" ||
93 m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
98 // transmit DragEnter event
99 EvtDragEnter evt( getIntf() );
100 m_pWin->processEvent( evt );
104 void X11DragDrop::dndPosition( ldata_t data )
106 Window src = data[0];
107 //Time time = data[3];
108 m_xPos = data[2] >> 16;
109 m_yPos = data[2] & 0xffff;
111 Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
112 //Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
113 Atom targetAtom = XInternAtom( XDISPLAY, "text/uri-list", 0 );
114 Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
116 Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
117 Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
119 // Convert the selection into the given target
120 // NEEDED or it doesn't work!
121 XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
124 actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
125 typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
128 event.type = ClientMessage;
129 event.xclient.window = src;
130 event.xclient.display = XDISPLAY;
131 event.xclient.message_type = typeAtom;
132 event.xclient.format = 32;
133 event.xclient.data.l[0] = m_wnd;
134 // Accept the drop (1), or not (0).
135 event.xclient.data.l[1] = m_target != None ? 1 : 0;
136 event.xclient.data.l[2] = 0;
137 event.xclient.data.l[3] = 0;
138 event.xclient.data.l[4] = actionAtom;
140 // Tell the source whether we accept the drop
141 XSendEvent( XDISPLAY, src, False, 0, &event );
143 // transmit DragOver event
144 EvtDragOver evt( getIntf(), m_xPos, m_yPos );
145 m_pWin->processEvent( evt );
149 void X11DragDrop::dndLeave( ldata_t data )
152 // transmit DragLeave event
153 EvtDragLeave evt( getIntf() );
154 m_pWin->processEvent( evt );
158 void X11DragDrop::dndDrop( ldata_t data )
162 Window src = data[0];
165 Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
166 Atom targetAtom = XInternAtom( XDISPLAY, "text/uri-list", 0 );
167 Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
169 Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
170 Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
172 // Convert the selection into the given target
173 XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
176 // Read the selection
179 unsigned long nitems, nbytes;
181 XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
182 AnyPropertyType, &type, &format, &nitems, &nbytes,
183 (unsigned char**)&buffer );
186 char* psz_dup = strdup( buffer );
187 char* psz_new = psz_dup;
188 while( psz_new && *psz_new )
191 const char* sep[] = { "\r\n", "\n", NULL };
192 for( int i = 0; sep[i]; i++ )
194 char* psz_end = strstr( psz_new, sep[i] );
198 skip = strlen( sep[i] );
203 files.push_back( psz_new );
206 psz_new += strlen( psz_new ) + skip;
212 // Tell the source we accepted the drop
214 event.type = ClientMessage;
215 event.xclient.window = src;
216 event.xclient.display = XDISPLAY;
217 event.xclient.message_type = typeAtom;
218 event.xclient.format = 32;
219 event.xclient.data.l[0] = m_wnd;
220 event.xclient.data.l[1] = 1; // drop accepted
221 event.xclient.data.l[2] = actionAtom;
222 XSendEvent( XDISPLAY, src, False, 0, &event );
224 // transmit DragDrop event
225 EvtDragDrop evt( getIntf(), m_xPos, m_yPos, files );
226 m_pWin->processEvent( evt );