Commit 1653a66d authored by Erwan Tulou's avatar Erwan Tulou

skins2: drap&drop enhancement

Pass drap&drop coordinates over to visual controls.
This feature will be used to allow users to finely insert items in the
playtree control instead of just appending them at the end.
parent 48884d48
......@@ -82,6 +82,7 @@ SOURCES_skins2 = \
events/evt_special.hpp \
events/evt_scroll.cpp \
events/evt_scroll.hpp \
events/evt_dragndrop.hpp \
\
parser/builder.cpp \
parser/builder.hpp \
......
/*****************************************************************************
* evt_dragndrop.hpp
*****************************************************************************
* Copyright (C) 2011 the VideoLAN team
* $Id$
*
* Author: Erwan Tulou <erwan10 At videolan Dot org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef EVT_DRAGNDROP_HPP
#define EVT_DRAGNDROP_HPP
#include "evt_generic.hpp"
#include <list>
/// Drag'n'Drop generic event
class EvtDrag: public EvtGeneric
{
public:
EvtDrag( intf_thread_t *pIntf ): EvtGeneric( pIntf ) { }
virtual ~EvtDrag() { }
virtual const string getAsString() const { return "drag"; }
};
class EvtDragEnter: public EvtDrag
{
public:
EvtDragEnter( intf_thread_t *pIntf ): EvtDrag( pIntf ) { }
virtual ~EvtDragEnter() { }
virtual const string getAsString() const { return "drag:enter"; }
};
class EvtDragLeave: public EvtDrag
{
public:
EvtDragLeave( intf_thread_t *pIntf ): EvtDrag( pIntf ) { }
virtual ~EvtDragLeave() { }
virtual const string getAsString() const { return "drag:leave"; }
};
class EvtDragOver: public EvtDrag
{
public:
EvtDragOver( intf_thread_t *pIntf, int x, int y )
: EvtDrag( pIntf ), m_xPos( x ), m_yPos( y ) { }
virtual ~EvtDragOver() { }
virtual const string getAsString() const { return "drag:over"; }
// Return the event coordinates
int getXPos() const { return m_xPos; }
int getYPos() const { return m_yPos; }
private:
int m_xPos;
int m_yPos;
};
class EvtDragDrop: public EvtDrag
{
public:
EvtDragDrop( intf_thread_t *pIntf, int x, int y, const list<string>& files )
: EvtDrag( pIntf ), m_files( files ), m_xPos( x ), m_yPos( y ) { }
virtual ~EvtDragDrop() { }
virtual const string getAsString() const { return "drag:drop"; }
// Return the event coordinates
int getXPos() const { return m_xPos; }
int getYPos() const { return m_yPos; }
const list<string>& getFiles() const { return m_files; }
private:
list<string> m_files;
int m_xPos;
int m_yPos;
};
#endif
......@@ -38,6 +38,10 @@ class EvtMouse;
class EvtKey;
class EvtRefresh;
class EvtScroll;
class EvtDragEnter;
class EvtDragLeave;
class EvtDragOver;
class EvtDragDrop;
class WindowManager;
......@@ -73,6 +77,15 @@ public:
virtual void processEvent( EvtKey &rEvtKey ) { (void)rEvtKey; }
virtual void processEvent( EvtScroll &rEvtScroll ) { (void)rEvtScroll; }
virtual void processEvent( EvtDragEnter &rEvtDragEnter )
{ (void)rEvtDragEnter; }
virtual void processEvent( EvtDragLeave &rEvtDragLeave )
{ (void)rEvtDragLeave; }
virtual void processEvent( EvtDragOver &rEvtDragOver )
{ (void)rEvtDragOver; }
virtual void processEvent( EvtDragDrop &rEvtDragDrop )
{ (void)rEvtDragDrop; }
virtual void processEvent( EvtRefresh &rEvtRefresh );
/// Resize the window
......
......@@ -31,6 +31,7 @@
#include "var_manager.hpp"
#include "../commands/cmd_on_top.hpp"
#include "../commands/cmd_dialogs.hpp"
#include "../commands/cmd_add_item.hpp"
#include "../controls/ctrl_generic.hpp"
#include "../events/evt_refresh.hpp"
#include "../events/evt_enter.hpp"
......@@ -42,10 +43,12 @@
#include "../events/evt_key.hpp"
#include "../events/evt_special.hpp"
#include "../events/evt_scroll.hpp"
#include "../events/evt_dragndrop.hpp"
#include "../utils/position.hpp"
#include "../utils/ustring.hpp"
#include <vlc_keys.h>
#include <list>
TopWindow::TopWindow( intf_thread_t *pIntf, int left, int top,
......@@ -53,9 +56,11 @@ TopWindow::TopWindow( intf_thread_t *pIntf, int left, int top,
bool dragDrop, bool playOnDrop, bool visible,
GenericWindow::WindowType_t type ):
GenericWindow( pIntf, left, top, dragDrop, playOnDrop, NULL, type ),
m_initialVisibility( visible ), m_rWindowManager( rWindowManager ),
m_initialVisibility( visible ), m_playOnDrop( playOnDrop ),
m_rWindowManager( rWindowManager ),
m_pActiveLayout( NULL ), m_pLastHitControl( NULL ),
m_pCapturingControl( NULL ), m_pFocusControl( NULL ), m_currModifier( 0 )
m_pCapturingControl( NULL ), m_pFocusControl( NULL ),
m_pDragControl( NULL ), m_currModifier( 0 )
{
// Register as a moving window
m_rWindowManager.registerWindow( *this );
......@@ -264,6 +269,66 @@ void TopWindow::processEvent( EvtScroll &rEvtScroll )
}
}
void TopWindow::processEvent( EvtDragDrop &rEvtDragDrop )
{
// Get the control hit by the mouse
int xPos = rEvtDragDrop.getXPos() - getLeft();
int yPos = rEvtDragDrop.getYPos() - getTop();
CtrlGeneric *pHitControl = findHitControl( xPos, yPos );
if( pHitControl && pHitControl->getType() == "tree" )
{
// Send a dragDrop event
EvtDragDrop evt( getIntf(), xPos, yPos, rEvtDragDrop.getFiles() );
pHitControl->handleEvent( evt );
}
else
{
list<string> files = rEvtDragDrop.getFiles();
list<string>::const_iterator it = files.begin();
for( bool first = true; it != files.end(); ++it, first = false )
{
bool playOnDrop = m_playOnDrop && first;
CmdAddItem( getIntf(), it->c_str(), playOnDrop ).execute();
}
}
m_pDragControl = NULL;
}
void TopWindow::processEvent( EvtDragOver &rEvtDragOver )
{
// Get the control hit by the mouse
int xPos = rEvtDragOver.getXPos() - getLeft();
int yPos = rEvtDragOver.getYPos() - getTop();
CtrlGeneric *pHitControl = findHitControl( xPos, yPos );
if( m_pDragControl && m_pDragControl != pHitControl )
{
EvtDragLeave evt( getIntf() );
m_pDragControl->handleEvent( evt );
}
m_pDragControl = pHitControl;
if( m_pDragControl )
{
// Send a dragOver event
EvtDragOver evt( getIntf(), xPos, yPos );
m_pDragControl->handleEvent( evt );
}
}
void TopWindow::processEvent( EvtDragLeave &rEvtDragLeave )
{
(void)rEvtDragLeave;
if( m_pDragControl )
{
EvtDragLeave evt( getIntf() );
m_pDragControl->handleEvent( evt );
m_pDragControl = NULL;
}
}
void TopWindow::forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl )
{
......
......@@ -56,6 +56,9 @@ public:
virtual void processEvent( EvtLeave &rEvtLeave );
virtual void processEvent( EvtKey &rEvtKey );
virtual void processEvent( EvtScroll &rEvtScroll );
virtual void processEvent( EvtDragDrop &rEvtDragDrop );
virtual void processEvent( EvtDragOver &rEvtDragOver );
virtual void processEvent( EvtDragLeave &rEvtDragLeave );
/// Forward an event to a control
virtual void forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl );
......@@ -102,6 +105,8 @@ private:
/// Initial visibility status
bool m_initialVisibility;
/// indicator if playback is requested on drag&drop
bool m_playOnDrop;
/// Window manager
WindowManager &m_rWindowManager;
/// Current active layout of the window
......@@ -112,6 +117,8 @@ private:
CtrlGeneric *m_pCapturingControl;
/// Control that has the focus
CtrlGeneric *m_pFocusControl;
/// Control over which drag&drop is hovering
CtrlGeneric *m_pDragControl;
/// Current key modifier (also used for mouse)
int m_currModifier;
......
......@@ -27,11 +27,14 @@
#include <windows.h>
#include "win32_dragdrop.hpp"
#include "../commands/cmd_add_item.hpp"
#include "../events/evt_dragndrop.hpp"
#include <list>
Win32DragDrop::Win32DragDrop( intf_thread_t *pIntf, bool playOnDrop ):
SkinObject( pIntf ), IDropTarget(), m_references( 1 ),
m_playOnDrop( playOnDrop )
Win32DragDrop::Win32DragDrop( intf_thread_t *pIntf,
bool playOnDrop, GenericWindow* pWin )
: SkinObject( pIntf ), IDropTarget(), m_references( 1 ),
m_playOnDrop( playOnDrop ), m_pWin( pWin)
{
}
......@@ -89,6 +92,10 @@ STDMETHODIMP Win32DragDrop::DragEnter( LPDATAOBJECT pDataObj,
*pdwEffect = DROPEFFECT_NONE;
}
// transmit DragEnter event
EvtDragEnter evt( getIntf() );
m_pWin->processEvent( evt );
return S_OK;
}
......@@ -96,13 +103,20 @@ STDMETHODIMP Win32DragDrop::DragEnter( LPDATAOBJECT pDataObj,
STDMETHODIMP Win32DragDrop::DragOver( DWORD grfKeyState, POINTL pt,
DWORD *pdwEffect )
{
// For visual feedback
// transmit DragOver event
EvtDragOver evt( getIntf(), pt.x, pt.y );
m_pWin->processEvent( evt );
return S_OK;
}
STDMETHODIMP Win32DragDrop::DragLeave()
{
// transmit DragLeave event
EvtDragLeave evt( getIntf() );
m_pWin->processEvent( evt );
// Remove visual feedback
return S_OK;
}
......@@ -129,7 +143,7 @@ STDMETHODIMP Win32DragDrop::Drop( LPDATAOBJECT pDataObj, DWORD grfKeyState,
HDROP HDrop = (HDROP)GlobalLock( HFiles );
// Notify VLC of the drop
HandleDrop( HDrop );
HandleDrop( HDrop, pt.x, pt.y );
// Release the pointer to the memory
GlobalUnlock( HFiles );
......@@ -144,12 +158,13 @@ STDMETHODIMP Win32DragDrop::Drop( LPDATAOBJECT pDataObj, DWORD grfKeyState,
}
void Win32DragDrop::HandleDrop( HDROP HDrop )
void Win32DragDrop::HandleDrop( HDROP HDrop, int x, int y )
{
list<string> files;
// Get the number of dropped files
int nbFiles = DragQueryFileW( HDrop, 0xFFFFFFFF, NULL, 0 );
// For each dropped file
for( int i = 0; i < nbFiles; i++ )
{
// Get the name of the file
......@@ -157,14 +172,15 @@ void Win32DragDrop::HandleDrop( HDROP HDrop )
wchar_t *psz_fileName = new WCHAR[nameLength];
DragQueryFileW( HDrop, i, psz_fileName, nameLength );
// Add the file
CmdAddItem cmd(getIntf(),sFromWide(psz_fileName),m_playOnDrop);
cmd.execute();
files.push_back( sFromWide(psz_fileName) );
delete[] psz_fileName;
}
DragFinish( HDrop );
// transmit DragDrop event
EvtDragDrop evt( getIntf(), x, y, files );
m_pWin->processEvent( evt );
}
......
......@@ -28,12 +28,13 @@
#include <shellapi.h>
#include <ole2.h>
#include "../src/skin_common.hpp"
#include "../src/generic_window.hpp"
class Win32DragDrop: public SkinObject, public IDropTarget
{
public:
Win32DragDrop( intf_thread_t *pIntf, bool playOnDrop );
Win32DragDrop( intf_thread_t *pIntf, bool playOnDrop, GenericWindow* pWin );
virtual ~Win32DragDrop() { }
protected:
......@@ -55,9 +56,11 @@ private:
unsigned long m_references;
/// Indicates whether the file(s) must be played immediately
bool m_playOnDrop;
///
GenericWindow* m_pWin;
/// Helper function
void HandleDrop( HDROP HDrop );
void HandleDrop( HDROP HDrop, int x, int y );
};
......
......@@ -118,8 +118,8 @@ Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
// Drag & drop
if( m_dragDrop )
{
m_pDropTarget = (LPDROPTARGET) new Win32DragDrop( getIntf(),
playOnDrop );
m_pDropTarget = (LPDROPTARGET)
new Win32DragDrop( getIntf(), playOnDrop, &rWindow );
// Register the window as a drop target
RegisterDragDrop( m_hWnd, m_pDropTarget );
}
......
......@@ -31,15 +31,16 @@
#include "x11_display.hpp"
#include "x11_factory.hpp"
#include "../commands/cmd_add_item.hpp"
#include "../events/evt_dragndrop.hpp"
#include <string>
#include <list>
X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
Window win, bool playOnDrop ):
Window win, bool playOnDrop, GenericWindow *pWin ):
SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
m_playOnDrop( playOnDrop )
m_playOnDrop( playOnDrop ), m_pWin( pWin ), m_xPos( -1 ), m_yPos( -1 )
{
}
......@@ -47,6 +48,7 @@ X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
void X11DragDrop::dndEnter( ldata_t data )
{
Window src = data[0];
m_xPos = m_yPos = -1;
// Retrieve available data types
list<string> dataTypes;
......@@ -84,22 +86,31 @@ void X11DragDrop::dndEnter( ldata_t data )
list<string>::iterator it;
for( it = dataTypes.begin(); it != dataTypes.end(); ++it )
{
if( *it == "text/plain" || *it == "STRING" )
if( *it == "text/uri-list" ||
*it == "text/plain" ||
*it == "STRING" )
{
m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
break;
}
}
// transmit DragEnter event
EvtDragEnter evt( getIntf() );
m_pWin->processEvent( evt );
}
void X11DragDrop::dndPosition( ldata_t data )
{
Window src = data[0];
Time time = data[2];
//Time time = data[3];
m_xPos = data[2] >> 16;
m_yPos = data[2] & 0xffff;
Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
//Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
Atom targetAtom = XInternAtom( XDISPLAY, "text/uri-list", 0 );
Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
......@@ -108,7 +119,7 @@ void X11DragDrop::dndPosition( ldata_t data )
// Convert the selection into the given target
// NEEDED or it doesn't work!
XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
time );
CurrentTime );
actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
......@@ -122,31 +133,37 @@ void X11DragDrop::dndPosition( ldata_t data )
event.xclient.data.l[0] = m_wnd;
// Accept the drop (1), or not (0).
event.xclient.data.l[1] = m_target != None ? 1 : 0;
OSFactory *pOsFactory = X11Factory::instance( getIntf() );
int w = pOsFactory->getScreenWidth();
int h = pOsFactory->getScreenHeight();
event.xclient.data.l[2] = 0;
event.xclient.data.l[3] = (w << 16) | h;
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = actionAtom;
// Tell the source whether we accept the drop
XSendEvent( XDISPLAY, src, False, 0, &event );
// transmit DragOver event
EvtDragOver evt( getIntf(), m_xPos, m_yPos );
m_pWin->processEvent( evt );
}
void X11DragDrop::dndLeave( ldata_t data )
{
(void)data;
// transmit DragLeave event
EvtDragLeave evt( getIntf() );
m_pWin->processEvent( evt );
}
void X11DragDrop::dndDrop( ldata_t data )
{
list<string> files;
Window src = data[0];
Time time = data[2];
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 actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
......@@ -164,12 +181,10 @@ void X11DragDrop::dndDrop( ldata_t data )
XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
AnyPropertyType, &type, &format, &nitems, &nbytes,
(unsigned char**)&buffer );
if( buffer != NULL )
{
char* psz_dup = strdup( buffer );
char* psz_new = psz_dup;
bool first = true;
while( psz_new && *psz_new )
{
int skip = 0;
......@@ -185,9 +200,7 @@ void X11DragDrop::dndDrop( ldata_t data )
}
if( *psz_new )
{
bool playOnDrop = m_playOnDrop && first;
CmdAddItem( getIntf(), psz_new, playOnDrop ).execute();
first = false;
files.push_back( psz_new );
}
psz_new += strlen( psz_new ) + skip;
......@@ -207,6 +220,10 @@ void X11DragDrop::dndDrop( ldata_t data )
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 );
}
#endif
......@@ -27,6 +27,7 @@
#include <X11/Xlib.h>
#include "../src/skin_common.hpp"
#include "../src/generic_window.hpp"
class X11Display;
......@@ -37,7 +38,7 @@ public:
typedef long ldata_t[5];
X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay, Window win,
bool playOnDrop );
bool playOnDrop, GenericWindow *pWin );
virtual ~X11DragDrop() { }
void dndEnter( ldata_t data );
......@@ -54,6 +55,11 @@ private:
bool m_playOnDrop;
/// Target type
Atom m_target;
/// Generic Window
GenericWindow *m_pWin;
/// (x,y) mouse coordinates
int m_xPos;
int m_yPos;
};
......
......@@ -41,7 +41,7 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
X11Display &rDisplay, bool dragDrop, bool playOnDrop,
X11Window *pParentWindow, GenericWindow::WindowType_t type ):
OSWindow( pIntf ), m_rDisplay( rDisplay ), m_pParent( pParentWindow ),
m_dragDrop( dragDrop ), m_type ( type )
m_dragDrop( dragDrop ), m_pDropTarget( NULL ), m_type ( type )
{
XSetWindowAttributes attr;
unsigned long valuemask;
......@@ -150,7 +150,7 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
{
// Create a Dnd object for this window
m_pDropTarget = new X11DragDrop( getIntf(), m_rDisplay, m_wnd,
playOnDrop );
playOnDrop, &rWindow );
// Register the window as a drop target
Atom xdndAtom = XInternAtom( XDISPLAY, "XdndAware", False );
......@@ -229,10 +229,8 @@ X11Window::~X11Window()
pFactory->m_windowMap[m_wnd] = NULL;
pFactory->m_dndMap[m_wnd] = NULL;
if( m_dragDrop )
{
delete m_pDropTarget;
}
XDestroyWindow( XDISPLAY, m_wnd );
XSync( XDISPLAY, False );
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment