x11_dragdrop.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:7k
源码类别:

多媒体

开发平台:

MultiPlatform

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