]> git.sesse.net Git - vlc/blob - modules/gui/skins2/x11/x11_dragdrop.cpp
skins2(X11): add icon to vlc
[vlc] / modules / gui / skins2 / x11 / x11_dragdrop.cpp
1 /*****************************************************************************
2  * x11_dragdrop.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@via.ecp.fr>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 #ifdef X11_SKINS
26
27 #include <X11/Xlib.h>
28 #include <X11/Xatom.h>
29
30 #include "x11_dragdrop.hpp"
31 #include "x11_display.hpp"
32 #include "x11_factory.hpp"
33 #include "../commands/cmd_add_item.hpp"
34
35 #include <string>
36 #include <list>
37
38
39 X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
40                           Window win, bool playOnDrop ):
41     SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
42     m_playOnDrop( playOnDrop )
43 {
44 }
45
46
47 void X11DragDrop::dndEnter( ldata_t data )
48 {
49     Window src = data[0];
50
51     // Retrieve available data types
52     list<string> dataTypes;
53     if( data[1] & 1 )   // More than 3 data types ?
54     {
55         Atom type;
56         int format;
57         unsigned long nitems, nbytes;
58         Atom *dataList;
59         Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 );
60         XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False,
61                             XA_ATOM, &type, &format, &nitems, &nbytes,
62                             (unsigned char**)&dataList );
63         for( unsigned long i=0; i<nitems; i++ )
64         {
65             string dataType = XGetAtomName( XDISPLAY, dataList[i] );
66             dataTypes.push_back( dataType );
67         }
68         XFree( (void*)dataList );
69     }
70     else
71     {
72         for( int i = 2; i < 5; i++ )
73         {
74             if( data[i] != None )
75             {
76                 string dataType = XGetAtomName( XDISPLAY, data[i] );
77                 dataTypes.push_back( dataType );
78             }
79         }
80     }
81
82     // Find the right target
83     m_target = None;
84     list<string>::iterator it;
85     for( it = dataTypes.begin(); it != dataTypes.end(); it++ )
86     {
87         if( *it == "text/plain" || *it == "STRING" )
88         {
89             m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
90             break;
91         }
92     }
93 }
94
95
96 void X11DragDrop::dndPosition( ldata_t data )
97 {
98     Window src = data[0];
99     Time time = data[2];
100
101     Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
102     Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
103     Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
104
105     Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
106     Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
107
108     // Convert the selection into the given target
109     // NEEDED or it doesn't work!
110     XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
111                        time );
112
113     actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
114     typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
115
116     XEvent event;
117     event.type = ClientMessage;
118     event.xclient.window = src;
119     event.xclient.display = XDISPLAY;
120     event.xclient.message_type = typeAtom;
121     event.xclient.format = 32;
122     event.xclient.data.l[0] = m_wnd;
123     // Accept the drop (1), or not (0).
124     event.xclient.data.l[1] = m_target != None ? 1 : 0;
125     OSFactory *pOsFactory = X11Factory::instance( getIntf() );
126     int w = pOsFactory->getScreenWidth();
127     int h = pOsFactory->getScreenHeight();
128     event.xclient.data.l[2] = 0;
129     event.xclient.data.l[3] = (w << 16) | h;
130     event.xclient.data.l[4] = actionAtom;
131
132     // Tell the source whether we accept the drop
133     XSendEvent( XDISPLAY, src, False, 0, &event );
134 }
135
136
137 void X11DragDrop::dndLeave( ldata_t data )
138 {
139 }
140
141
142 void X11DragDrop::dndDrop( ldata_t data )
143 {
144     Window src = data[0];
145     Time time = data[2];
146
147     Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
148     Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
149     Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
150
151     Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
152     Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
153
154     // Convert the selection into the given target
155     XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
156                        time );
157
158     // Read the selection
159     Atom type;
160     int format;
161     unsigned long nitems, nbytes;
162     char *buffer;
163     XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
164                         AnyPropertyType, &type, &format, &nitems, &nbytes,
165                         (unsigned char**)&buffer );
166
167     if( buffer != NULL )
168     {
169         char* psz_dup = strdup( buffer );
170         char* psz_new = psz_dup;
171         while( psz_new && *psz_new )
172         {
173             char* psz_end = strchr( psz_new, '\n' );
174             if( psz_end )
175                 *psz_end = '\0';
176
177             CmdAddItem cmd( getIntf(), psz_new, m_playOnDrop );
178             cmd.execute();
179
180             psz_new = psz_end ? psz_end + 1 : NULL;
181         }
182         free( psz_dup );
183         XFree( buffer );
184     }
185
186     // Tell the source we accepted the drop
187     XEvent event;
188     event.type = ClientMessage;
189     event.xclient.window = src;
190     event.xclient.display = XDISPLAY;
191     event.xclient.message_type = typeAtom;
192     event.xclient.format = 32;
193     event.xclient.data.l[0] = m_wnd;
194     event.xclient.data.l[1] = 1;            // drop accepted
195     event.xclient.data.l[2] = actionAtom;
196     XSendEvent( XDISPLAY, src, False, 0, &event );
197 }
198
199 #endif