Commit 04af5c7c authored by Erwan Tulou's avatar Erwan Tulou Committed by Rémi Denis-Courmont

skins2 vout manager

Signed-off-by: default avatarRémi Denis-Courmont <remi@remlab.net>
parent 823b07a0
......@@ -151,6 +151,8 @@ SOURCES_skins2 = \
src/vlcproc.hpp \
src/vout_window.cpp \
src/vout_window.hpp \
src/vout_manager.cpp \
src/vout_manager.hpp \
src/window_manager.cpp \
src/window_manager.hpp \
\
......
......@@ -29,6 +29,8 @@
#include "../src/theme.hpp"
#include "../src/theme_loader.hpp"
#include "../src/window_manager.hpp"
#include "../src/vout_manager.hpp"
#include "../src/vlcproc.hpp"
void CmdChangeSkin::execute()
......@@ -42,6 +44,9 @@ void CmdChangeSkin::execute()
pOldTheme->getWindowManager().hideAll();
}
VoutManager::instance( getIntf() )->lockVout();
VoutManager::instance( getIntf() )->saveVoutConfig();
ThemeLoader loader( getIntf() );
if( loader.load( m_file ) )
{
......@@ -49,16 +54,23 @@ void CmdChangeSkin::execute()
msg_Info( getIntf(), "new theme successfully loaded (%s)",
m_file.c_str() );
delete pOldTheme;
// restore vout config
VoutManager::instance( getIntf() )->restoreVoutConfig( true );
VoutManager::instance( getIntf() )->unlockVout();
}
else if( pOldTheme )
{
msg_Warn( getIntf(), "a problem occurred when loading the new theme,"
" restoring the previous one" );
getIntf()->p_sys->p_theme = pOldTheme;
VoutManager::instance( getIntf() )->restoreVoutConfig( false );
VoutManager::instance( getIntf() )->unlockVout();
pOldTheme->getWindowManager().restoreVisibility();
}
else
{
VoutManager::instance( getIntf() )->unlockVout();
msg_Err( getIntf(), "cannot load the theme, aborting" );
// Quit
CmdQuit cmd( getIntf() );
......
......@@ -26,6 +26,9 @@
#include "../src/generic_layout.hpp"
#include "../src/window_manager.hpp"
#include "../src/vlcproc.hpp"
#include "../src/vout_window.hpp"
#include "../controls/ctrl_video.hpp"
#include <vlc_vout.h>
CmdResize::CmdResize( intf_thread_t *pIntf, const WindowManager &rWindowManager,
......@@ -57,3 +60,16 @@ void CmdResizeVout::execute()
rVoutSize.setSize( m_width, m_height );
}
CmdResizeInnerVout::CmdResizeInnerVout( intf_thread_t *pIntf,
CtrlVideo* pCtrlVideo )
: CmdGeneric( pIntf ), m_pCtrlVideo( pCtrlVideo )
{
}
void CmdResizeInnerVout::execute()
{
m_pCtrlVideo->resizeInnerVout();
}
......@@ -26,9 +26,12 @@
#define CMD_RESIZE_HPP
#include "cmd_generic.hpp"
#include <vlc_vout.h>
class WindowManager;
class GenericLayout;
class CtrlVideo;
class VoutWindow;
/// Command to resize a layout
......@@ -74,4 +77,22 @@ class CmdResizeVout: public CmdGeneric
};
/// Command to resize the inner vout window
class CmdResizeInnerVout: public CmdGeneric
{
public:
/// Resize the given layout
CmdResizeInnerVout( intf_thread_t *pIntf, CtrlVideo* pCtrlVideo );
virtual ~CmdResizeInnerVout() {}
/// This method does the real job of the command
virtual void execute();
/// Return the type of the command
virtual string getType() const { return "resize inner vout"; }
private:
CtrlVideo* m_pCtrlVideo;
};
#endif
......@@ -125,18 +125,21 @@ class CtrlGeneric: public SkinObject, public Observer<VarBool>
/// Overload this method to get notified of bool variable changes
virtual void onVarBoolUpdate( VarBool &rVar ) {}
private:
/// Method called when an observed bool variable is changed
virtual void onUpdate( Subject<VarBool> &rVariable , void* );
/// Associated layout
GenericLayout *m_pLayout;
/// Visibility variable
VarBool *m_pVisible;
private:
/// Position in the layout
Position *m_pPosition;
/// Help text
UString m_help;
/// Visibilty variable
VarBool *m_pVisible;
/// Method called when an observed bool variable is changed
virtual void onUpdate( Subject<VarBool> &rVariable , void* );
};
typedef CountedPtr<CtrlGeneric> CtrlGenericPtr;
......
......@@ -26,6 +26,7 @@
#include "../src/vout_window.hpp"
#include "../src/os_graphics.hpp"
#include "../src/vlcproc.hpp"
#include "../src/vout_manager.hpp"
#include "../src/window_manager.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_resize.hpp"
......@@ -34,15 +35,20 @@
CtrlVideo::CtrlVideo( intf_thread_t *pIntf, GenericLayout &rLayout,
bool autoResize, const UString &rHelp,
VarBool *pVisible ):
CtrlGeneric( pIntf, rHelp, pVisible ), m_pVout( NULL ),
m_rLayout( rLayout ), m_xShift( 0 ), m_yShift( 0 )
CtrlGeneric( pIntf, rHelp, pVisible ), m_rLayout( rLayout ),
m_xShift( 0 ), m_yShift( 0 ), m_bAutoResize( autoResize ),
m_pVoutWindow( NULL ), m_bIsUseable( false )
{
// Observe the vout size variable if the control is auto-resizable
if( autoResize )
if( m_bAutoResize )
{
VarBox &rVoutSize = VlcProc::instance( pIntf )->getVoutSizeVar();
rVoutSize.addObserver( this );
}
// observe visibility variable
if( m_pVisible )
m_pVisible->addObserver( this );
}
......@@ -51,7 +57,10 @@ CtrlVideo::~CtrlVideo()
VarBox &rVoutSize = VlcProc::instance( getIntf() )->getVoutSizeVar();
rVoutSize.delObserver( this );
delete m_pVout;
//m_pLayout->getActiveVar().delObserver( this );
if( m_pVisible )
m_pVisible->delObserver( this );
}
......@@ -69,10 +78,10 @@ bool CtrlVideo::mouseOver( int x, int y ) const
void CtrlVideo::onResize()
{
const Position *pPos = getPosition();
if( pPos && m_pVout )
if( pPos && m_pVoutWindow )
{
m_pVout->move( pPos->getLeft(), pPos->getTop() );
m_pVout->resize( pPos->getWidth(), pPos->getHeight() );
m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
}
}
......@@ -98,10 +107,26 @@ void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
}
void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
void CtrlVideo::setLayout( GenericLayout *pLayout,
const Position &rPosition )
{
int newWidth = ((VarBox&)rVoutSize).getWidth() + m_xShift;
int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
CtrlGeneric::setLayout( pLayout, rPosition );
m_pLayout->getActiveVar().addObserver( this );
m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();
// register Video Control
VoutManager::instance( getIntf() )->registerCtrlVideo( this );
msg_Dbg( getIntf(),"New VideoControl detected(%x), useability=%s",
this, m_bIsUseable ? "true" : "false" );
}
void CtrlVideo::resizeControl( int width, int height )
{
int newWidth = width + m_xShift;
int newHeight = height + m_yShift;
// Create a resize command
// FIXME: this way of getting the window manager kind of sucks
......@@ -112,32 +137,101 @@ void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
m_rLayout, newWidth, newHeight );
// Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
pQueue->push( CmdGenericPtr( pCmd ), false );
// FIXME: this should be a command too
rWindowManager.stopResize();
pCmd = new CmdResizeInnerVout( getIntf(), this );
pQueue->push( CmdGenericPtr( pCmd ), false );
TopWindow* pWin = getWindow();
rWindowManager.show( *pWin );
}
void CtrlVideo::setVisible( bool visible )
void CtrlVideo::onUpdate( Subject<VarBox> &rVoutSize, void *arg )
{
if( visible )
int newWidth = ((VarBox&)rVoutSize).getWidth() + m_xShift;
int newHeight = ((VarBox&)rVoutSize).getHeight() + m_yShift;
resizeControl( newWidth, newHeight );
}
void CtrlVideo::onUpdate( Subject<VarBool> &rVariable, void *arg )
{
// Visibility changed
if( &rVariable == m_pVisible )
{
msg_Dbg( getIntf(), "VideoCtrl : Visibility changed (visible=%d)",
isVisible() );
}
// Active Layout changed
if( &rVariable == &m_pLayout->getActiveVar() )
{
msg_Dbg( getIntf(), "VideoCtrl : Active Layout changed (isActive=%d)",
m_pLayout->getActiveVar().get() );
}
m_bIsUseable = isVisible() && m_pLayout->getActiveVar().get();
if( m_bIsUseable && !isUsed() )
{
VoutManager::instance( getIntf() )->requestVout( this );
}
else if( !m_bIsUseable && isUsed() )
{
GenericWindow *pParent = getWindow();
const Position *pPos = getPosition();
// Create a child window for the vout if it doesn't exist yet
if( !m_pVout && pParent && pPos )
{
m_pVout = new VoutWindow( getIntf(), pPos->getLeft(),
pPos->getTop(), false, false, *pParent );
m_pVout->resize( pPos->getWidth(), pPos->getHeight() );
m_pVout->show();
}
VoutManager::instance( getIntf() )->discardVout( this );
}
else
}
void CtrlVideo::attachVoutWindow( VoutWindow* pVoutWindow )
{
int width = pVoutWindow->getOriginalWidth();
int height = pVoutWindow->getOriginalHeight();
WindowManager &rWindowManager =
getIntf()->p_sys->p_theme->getWindowManager();
TopWindow* pWin = getWindow();
rWindowManager.show( *pWin );
if( m_bAutoResize && width && height )
{
delete m_pVout;
m_pVout = NULL;
int newWidth = width + m_xShift;
int newHeight = height + m_yShift;
rWindowManager.startResize( m_rLayout, WindowManager::kResizeSE );
rWindowManager.resize( m_rLayout, newWidth, newHeight );
rWindowManager.stopResize();
}
pVoutWindow->setCtrlVideo( this );
m_pVoutWindow = pVoutWindow;
}
void CtrlVideo::detachVoutWindow( )
{
m_pVoutWindow->setCtrlVideo( NULL );
m_pVoutWindow = NULL;
}
void CtrlVideo::resizeInnerVout( )
{
WindowManager &rWindowManager =
getIntf()->p_sys->p_theme->getWindowManager();
TopWindow* pWin = getWindow();
const Position *pPos = getPosition();
m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
rWindowManager.show( *pWin );
m_pVoutWindow->show();
}
......@@ -26,8 +26,9 @@
#include "ctrl_generic.hpp"
#include "../utils/position.hpp"
#include "../src/vout_window.hpp"
#include <vlc_vout.h>
class VoutWindow;
/// Control video
class CtrlVideo: public CtrlGeneric, public Observer<VarBox>
......@@ -58,16 +59,52 @@ class CtrlVideo: public CtrlGeneric, public Observer<VarBox>
/// Method called when the vout size is updated
virtual void onUpdate( Subject<VarBox> &rVoutSize, void* );
/// Called by the layout when the control is show/hidden
void setVisible( bool visible );
/// Method called when visibility or ActiveLayout is updated
virtual void onUpdate( Subject<VarBool> &rVariable , void* );
// Attach a voutWindow to a Video Control
void attachVoutWindow( VoutWindow* pVoutWindow );
// Detach a voutWindow from a Video Control
void detachVoutWindow( );
// Update the inner part of the Video Control
void resizeInnerVout( );
// Get TopWindow associated with the video control
virtual TopWindow* getWindow() { return CtrlGeneric::getWindow(); }
// Get the VoutWindow associated with the video control
virtual VoutWindow* getVoutWindow() { return m_pVoutWindow; }
/// Set the position and the associated layout of the control
virtual void setLayout( GenericLayout *pLayout,
const Position &rPosition );
// resize the video Control
virtual void resizeControl( int width, int height );
// Is this control useable (visibility requirements)
virtual bool isUseable() { return m_bIsUseable; }
// Is this control used
virtual bool isUsed() { return m_pVoutWindow ? true : false; }
private:
/// Vout window
VoutWindow *m_pVout;
/// Associated layout
GenericLayout &m_rLayout;
/// Autoresize parameter
bool m_bAutoResize;
/// Difference between layout size and video size
int m_xShift, m_yShift;
/// Is the video Control useable
bool m_bIsUseable;
/// Vout window
VoutWindow *m_pVoutWindow;
};
#endif
......@@ -31,6 +31,7 @@
#include "../controls/ctrl_generic.hpp"
#include "../controls/ctrl_video.hpp"
#include "../utils/var_bool.hpp"
#include <set>
GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
......@@ -38,7 +39,7 @@ GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
int maxHeight ):
SkinObject( pIntf ), m_pWindow( NULL ), m_rect( 0, 0, width, height ),
m_minWidth( minWidth ), m_maxWidth( maxWidth ),
m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoControl( NULL ),
m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_pVideoCtrlSet(),
m_visible( false ), m_pVarActive( NULL )
{
// Get the OSFactory
......@@ -122,7 +123,7 @@ void GenericLayout::addControl( CtrlGeneric *pControl,
// Check if it is a video control
if( pControl->getType() == "video" )
{
m_pVideoControl = (CtrlVideo*)pControl;
m_pVideoCtrlSet.insert( (CtrlVideo*)pControl );
}
}
else
......@@ -233,38 +234,126 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
height = m_rect.getHeight() - y;
// Refresh the window... but do not paint on a visible video control!
if( !m_pVideoControl || !m_pVideoControl->isVisible() )
if( !m_pVideoCtrlSet.size() )
{
// No video control, we can safely repaint the rectangle
pWindow->refresh( x, y, width, height );
}
else
{
// Bad luck, there is a video control somewhere (not necessarily
// in the repainting zone, btw).
// We will divide the repainting into 4 regions (top, left, bottom
// and right). The overlapping parts (i.e. the corners) of these
// regions will be painted twice, because otherwise the algorithm
// becomes a real mess :)
// Use short variable names for convenience
int xx = m_pVideoControl->getPosition()->getLeft();
int yy = m_pVideoControl->getPosition()->getTop();
int ww = m_pVideoControl->getPosition()->getWidth();
int hh = m_pVideoControl->getPosition()->getHeight();
// Top part:
if( y < yy )
pWindow->refresh( x, y, width, yy - y );
// Left part:
if( x < xx )
pWindow->refresh( x, y, xx - x, height );
// Bottom part
if( y + height > yy + hh )
pWindow->refresh( x, yy + hh, width, y + height - (yy + hh) );
// Right part
if( x + width > xx + ww )
pWindow->refresh( xx + ww, y, x + width - (xx + ww), height );
// video control(s) present, we need more calculations
computeRefresh( x, y, width, height );
}
}
}
class rect
{
public:
rect( int v_x = 0, int v_y = 0,
int v_width = 0, int v_height = 0 )
: x( v_x), y( v_y ), width( v_width), height( v_height)
{}
~rect(){}
int x;
int y;
int width;
int height;
static bool isIncluded( rect& rect2, rect& rect1 )
{
int x1 = rect1.x;
int y1 = rect1.y;
int w1 = rect1.width;
int h1 = rect1.height;
int x2 = rect2.x;
int y2 = rect2.y;
int w2 = rect2.width;
int h2 = rect2.height;
return x2 >= x1 && x2 < x1 + w1
&& y2 >= y1 && y2 < y1 + h1
&& w2 <= w1
&& h2 <= h1;
}
};
void GenericLayout::computeRefresh( int x, int y, int width, int height )
{
int w = width;
int h = height;
TopWindow *pWindow = getWindow();
set<int> x_set;
set<int> y_set;
vector<rect> rect_set;
x_set.insert( x + w );
y_set.insert( y + h );
// retrieve video controls being used
// and remember their rectangles
set<CtrlVideo*>::const_iterator it;
for( it = m_pVideoCtrlSet.begin(); it != m_pVideoCtrlSet.end(); it++ )
{
if( (*it)->isUsed() )
{
int xx = (*it)->getPosition()->getLeft();
int yy = (*it)->getPosition()->getTop();
int ww = (*it)->getPosition()->getWidth();
int hh = (*it)->getPosition()->getHeight();
rect r(xx, yy, ww, hh );
rect_set.push_back( r );
if( xx > x && xx < x + w )
x_set.insert( xx );
if( xx + ww > x && xx + ww < x + w )
x_set.insert( xx + ww );
if( yy > y && yy < y + h )
y_set.insert( yy );
if( yy + hh > y && yy + hh < y + h )
y_set.insert( yy + hh );
}
}
// for each subregion, test whether they are part
// of the video control(s) or not
set<int>::const_iterator it_x;
set<int>::const_iterator it_y;
int x_prev, y_prev;
for( x_prev = x, it_x = x_set.begin();
it_x != x_set.end(); x_prev = *it_x, it_x++ )
{
int x0 = x_prev;
int w0 = *it_x - x_prev;
for( y_prev = y, it_y = y_set.begin();
it_y != y_set.end(); y_prev = *it_y, it_y++ )
{
int y0 = y_prev;
int h0 = *it_y - y_prev;
rect r( x0, y0, w0, h0 );
bool b_refresh = true;
vector<rect>::iterator it;
for( it = rect_set.begin(); it != rect_set.end(); it++ )
{
rect r_ctrl = *it;
if( rect::isIncluded( r, r_ctrl ) )
{
b_refresh = false;
break;
}
}
// subregion is not part of a video control
// needs to be refreshed
if( b_refresh )
pWindow->refresh( x0, y0, w0 ,h0 );
}
}
}
......@@ -287,22 +376,11 @@ void GenericLayout::onShow()
m_visible = true;
refreshAll();
// TODO find a better way to handle the vout ?
if( m_pVideoControl )
{
m_pVideoControl->setVisible( true );
}
}
void GenericLayout::onHide()
{
m_visible = false;
// TODO find a better way to handle the vout ?
if( m_pVideoControl )
{
m_pVideoControl->setVisible( false );
}
}
......@@ -105,6 +105,9 @@ class GenericLayout: public SkinObject
virtual int getMinHeight() const { return m_minHeight; }
virtual int getMaxHeight() const { return m_maxHeight; }
/// specific refresh window (if video controls)
virtual void computeRefresh( int x, int y, int width, int height );
/// Resize the layout
virtual void resize( int width, int height );
......@@ -156,8 +159,8 @@ class GenericLayout: public SkinObject
OSGraphics *m_pImage;
/// List of the controls in the layout
list<LayeredControl> m_controlList;
/// Video control
CtrlVideo *m_pVideoControl;
/// Video control(s)
set<CtrlVideo *> m_pVideoCtrlSet;
/// List of the anchors in the layout
list<Anchor*> m_anchorList;
/// Flag to know if the layout is visible
......
......@@ -98,6 +98,10 @@ void GenericWindow::move( int left, int top )
void GenericWindow::resize( int width, int height )
{
// don't try when value is 0 (may crash)
if( !width || ! height )
return;
// Update the window size
m_width = width;
m_height = height;
......@@ -157,3 +161,15 @@ void GenericWindow::innerHide()
}
}
void* GenericWindow::getOSHandle() const
{
return m_pOsWindow->getOSHandle();
}
void GenericWindow::setParent( GenericWindow* pParent, int x, int y, int w, int h )
{
void* handle = pParent ? pParent->getOSHandle() : NULL;
m_pOsWindow->reparent( handle, x, y, w, h );
}
......@@ -46,6 +46,8 @@ class GenericWindow: public SkinObject, public Observer<VarBool>
{
private:
friend class WindowManager;
friend class VoutManager;
friend class CtrlVideo;
public:
GenericWindow( intf_thread_t *pIntf, int xPos, int yPos,
bool dragDrop, bool playOnDrop,
......@@ -81,6 +83,12 @@ class GenericWindow: public SkinObject, public Observer<VarBool>
/// Window type, mainly useful when overloaded (for VoutWindow)
virtual string getType() const { return "Generic"; }
/// windows handle
void* getOSHandle() const;
/// reparent
void setParent( GenericWindow* pParent, int x, int y, int w, int h );
protected:
/// Get the OS window
OSWindow *getOSWindow() const { return m_pOsWindow; }
......
......@@ -56,6 +56,12 @@ class OSWindow: public SkinObject
/// Toggle the window on top
virtual void toggleOnTop( bool onTop ) const = 0;
/// getter for handler
virtual void* getOSHandle( ) const = 0;
/// reparent the window
virtual void reparent( void* OSHandle, int x, int y, int w, int h ) = 0;
protected:
OSWindow( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
};
......
......@@ -44,6 +44,7 @@ class OSFactory;
class OSLoop;
class VarManager;
class VlcProc;
class VoutManager;
class Theme;
class ThemeRepository;
......@@ -132,6 +133,8 @@ struct intf_sys_t
VarManager *p_varManager;
/// VLC state handler
VlcProc *p_vlcProc;
/// Vout manager
VoutManager *p_voutManager;
/// Theme repository
ThemeRepository *p_repository;
......
......@@ -42,6 +42,8 @@
#include "theme_loader.hpp"
#include "theme.hpp"
#include "theme_repository.hpp"
#include "vout_window.hpp"
#include "vout_manager.hpp"
#include "../parser/interpreter.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_quit.hpp"
......@@ -115,6 +117,7 @@ static int Open( vlc_object_t *p_this )
p_intf->p_sys->p_osFactory = NULL;
p_intf->p_sys->p_osLoop = NULL;
p_intf->p_sys->p_varManager = NULL;
p_intf->p_sys->p_voutManager = NULL;
p_intf->p_sys->p_vlcProc = NULL;
p_intf->p_sys->p_repository = NULL;
......@@ -170,6 +173,12 @@ static int Open( vlc_object_t *p_this )
#endif
return VLC_EGENERIC;
}
if( VoutManager::instance( p_intf ) == NULL )
{
msg_Err( p_intf, "cannot instanciate VoutManager" );
vlc_object_release( p_intf->p_sys->p_playlist );
return VLC_EGENERIC;
}
vlc_mutex_lock( &skin_load.mutex );
skin_load.intf = p_intf;
vlc_mutex_unlock( &skin_load.mutex );
......@@ -237,13 +246,23 @@ static void Close( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
msg_Dbg( p_intf, "closing skins2 module" );
vlc_mutex_lock( &skin_load.mutex );
skin_load.intf = NULL;
vlc_mutex_unlock( &skin_load.mutex);
if( p_intf->p_sys->p_theme )
{
delete p_intf->p_sys->p_theme;
p_intf->p_sys->p_theme = NULL;
msg_Dbg( p_intf, "current theme deleted" );
}
// Destroy "singleton" objects
OSFactory::instance( p_intf )->destroyOSLoop();
ThemeRepository::destroy( p_intf );
VoutManager::destroy( p_intf );
//Dialogs::destroy( p_intf );
Interpreter::destroy( p_intf );
AsyncQueue::destroy( p_intf );
......@@ -283,8 +302,6 @@ static void Run( intf_thread_t *p_intf )
if( p_intf->p_sys->p_theme )
{
p_intf->p_sys->p_theme->saveConfig();
delete p_intf->p_sys->p_theme;
p_intf->p_sys->p_theme = NULL;
}
// cannot be called in "Close", because it refcounts skins2
......@@ -304,15 +321,14 @@ static int WindowOpen( vlc_object_t *p_this )
if( pIntf == NULL )
return VLC_EGENERIC;
/* FIXME: most probably not thread-safe,
* albeit no worse than ever before */
pWnd->handle.hwnd = VlcProc::getWindow( pIntf, pWnd->vout,
&pWnd->pos_x, &pWnd->pos_y,
&pWnd->width, &pWnd->height );
vlc_object_release( pIntf );
pWnd->handle.hwnd = VoutManager::getWindow( pIntf, pWnd );
if( pWnd->handle.hwnd )
{
pWnd->p_private = pIntf;
pWnd->control = &VlcProc::controlWindow;
pWnd->control = &VoutManager::controlWindow;
return VLC_SUCCESS;
}
else
......@@ -326,7 +342,7 @@ static void WindowClose( vlc_object_t *p_this )
vout_window_t *pWnd = (vout_window_t *)p_this;
intf_thread_t *pIntf = (intf_thread_t *)p_this->p_private;
VlcProc::releaseWindow( pIntf, pWnd->handle.hwnd );
VoutManager::releaseWindow( pIntf, pWnd );
}
//---------------------------------------------------------------------------
......
......@@ -116,9 +116,6 @@ bool ThemeLoader::load( const string &fileName )
}
free( skin_last );
// The new theme cannot embed a video output yet
VlcProc::instance( getIntf() )->dropVout();
return true;
}
......
......@@ -177,6 +177,7 @@ VlcProc::~VlcProc()
if( getIntf()->p_sys->p_input )
{
vlc_object_release( getIntf()->p_sys->p_input );
getIntf()->p_sys->p_input = NULL;
}
interaction_Unregister( getIntf() );
......@@ -196,27 +197,6 @@ VlcProc::~VlcProc()
var_DelCallback( getIntf(), "skin-to-load", onSkinToLoad, this );
}
#include <assert.h>
void VlcProc::registerVoutWindow( void *pVoutWindow )
{
m_handleSet.insert( pVoutWindow );
assert( !m_pVout );
}
void VlcProc::unregisterVoutWindow( void *pVoutWindow )
{
m_handleSet.erase( pVoutWindow );
}
void VlcProc::dropVout()
{
assert( !m_pVout );
}
void VlcProc::manage()
{
// Did the user request to quit vlc ?
......@@ -556,73 +536,6 @@ void VlcProc::updateStreamName()
pQueue->push( CmdGenericPtr( pCmdItem ) );
}
void *VlcProc::getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
int *pXHint, int *pYHint,
unsigned int *pWidthHint,
unsigned int *pHeightHint )
{
VlcProc *pThis = pIntf->p_sys->p_vlcProc;
if( pThis->m_handleSet.empty() )
{
return NULL;
}
else
{
pThis->m_pVout = pVout;
// Get the window handle
void *pWindow = *pThis->m_handleSet.begin();
// Post a resize vout command
CmdResizeVout *pCmd = new CmdResizeVout( pThis->getIntf(), pWindow,
*pWidthHint, *pHeightHint );
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
return pWindow;
}
}
void VlcProc::releaseWindow( intf_thread_t *pIntf, void *pWindow )
{
VlcProc *pThis = pIntf->p_sys->p_vlcProc;
pThis->m_pVout = NULL;
}
int VlcProc::controlWindow( struct vout_window_t *pWnd,
int query, va_list args )
{
intf_thread_t *pIntf = (intf_thread_t *)pWnd->p_private;
VlcProc *pThis = pIntf->p_sys->p_vlcProc;
switch( query )
{
case VOUT_SET_SIZE:
{
if( pThis->m_pVout )
{
unsigned int i_width = va_arg( args, unsigned int );
unsigned int i_height = va_arg( args, unsigned int );
if( !i_width ) i_width = pThis->m_pVout->i_window_width;
if( !i_height ) i_height = pThis->m_pVout->i_window_height;
// Post a resize vout command
CmdResizeVout *pCmd =
new CmdResizeVout( pThis->getIntf(), pWnd->handle.hwnd,
i_width, i_height );
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
}
}
default:
msg_Dbg( pWnd, "control query not supported" );
break;
}
return VLC_SUCCESS;
}
int VlcProc::onEqBandsChange( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam )
......
......@@ -27,6 +27,7 @@
#include <set>
#include <vlc_vout.h>
#include "../vars/equalizer.hpp"
#include "../vars/playtree.hpp"
#include "../vars/time.hpp"
......@@ -34,6 +35,7 @@
#include "../utils/position.hpp"
#include "../utils/var_text.hpp"
#include "../commands/cmd_generic.hpp"
#include "../controls/ctrl_video.hpp"
class OSTimer;
class VarBool;
......@@ -80,19 +82,9 @@ class VlcProc: public SkinObject
/// Getter for the vout size variable
VarBox &getVoutSizeVar() { return m_varVoutSize; }
/// Set the vout window handle
void registerVoutWindow( void *pVoutWindow );
/// Unset the vout window handle
void unregisterVoutWindow( void *pVoutWindow );
/// Indicate whether the embedded video output is currently used
bool isVoutUsed() const { return m_pVout != NULL; }
/// If an embedded video output is used, drop it (i.e. tell it to stop
/// using our window handle)
void dropVout();
protected:
// Protected because it is a singleton
VlcProc( intf_thread_t *pIntf );
......@@ -135,12 +127,6 @@ class VlcProc: public SkinObject
/// Variable for DVD detection
VariablePtr m_cVarDvdActive;
/// Set of handles of vout windows
/**
* When changing the skin, the handles of the 2 skins coexist in the
* set (but this is temporary, until the old theme is destroyed).
*/
set<void *> m_handleSet;
/// Vout thread
vout_thread_t *m_pVout;
/// Audio output
......@@ -209,21 +195,6 @@ class VlcProc: public SkinObject
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam );
public: /* FIXME: these used to be private for a reason */
/// Callback to request a vout window
static void *getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
int *pXHint, int *pYHint,
unsigned int *pWidthHint,
unsigned int *pHeightHint );
/// Callback to release a vout window
static void releaseWindow( intf_thread_t *pIntf, void *pWindow );
/// Callback to change a vout window
static int controlWindow( struct vout_window_t *pWnd,
int query, va_list args );
private: /* end of FIXME */
/// Callback for equalizer-bands variable
static int onEqBandsChange( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
......
/*****************************************************************************
* vout_manager.cpp
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* $Id$
*
* Authors: Erwan Tulou <brezhoneg1 at yahoo.fr>
*
* 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.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_vout.h>
#include <vlc_window.h>
#include "vout_manager.hpp"
#include "window_manager.hpp"
#include "vlcproc.hpp"
#include "../commands/async_queue.hpp"
#include "../commands/cmd_show_window.hpp"
#include "../commands/cmd_resize.hpp"
VoutManager *VoutManager::instance( intf_thread_t *pIntf )
{
if( pIntf->p_sys->p_voutManager == NULL )
{
pIntf->p_sys->p_voutManager = new VoutManager( pIntf );
}
return pIntf->p_sys->p_voutManager;
}
void VoutManager::destroy( intf_thread_t *pIntf )
{
if( pIntf->p_sys->p_voutManager )
{
delete pIntf->p_sys->p_voutManager;
pIntf->p_sys->p_voutManager = NULL;
}
}
VoutManager::VoutManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
m_pVoutMainWindow( NULL ), m_pCtrlVideoVec(),
m_pCtrlVideoVecBackup(), m_SavedVoutVec()
{
vlc_mutex_init( &vout_lock );
m_pVoutMainWindow = new VoutMainWindow( getIntf() );
}
VoutManager::~VoutManager( )
{
vlc_mutex_destroy( &vout_lock );
delete m_pVoutMainWindow;
}
void VoutManager::registerCtrlVideo( CtrlVideo* p_CtrlVideo )
{
m_pCtrlVideoVec.push_back( p_CtrlVideo );
}
void VoutManager::saveVoutConfig( )
{
// Save width/height to be consistent across themes
// and detach Video Controls
vector<SavedVout>::iterator it;
for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
{
if( (*it).pCtrlVideo )
{
// detach vout thread from VideoControl
(*it).pCtrlVideo->detachVoutWindow( );
// memorize width/height before VideoControl is destroyed
(*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
(*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
(*it).pCtrlVideo = NULL;
}
}
// Create a backup copy and reset original for new theme
m_pCtrlVideoVecBackup = m_pCtrlVideoVec;
m_pCtrlVideoVec.clear();
}
void VoutManager::restoreVoutConfig( bool b_success )
{
if( !b_success )
{
// loading new theme failed, restoring previous theme
m_pCtrlVideoVec = m_pCtrlVideoVecBackup;
}
// reattach vout(s) to Video Controls
vector<SavedVout>::iterator it;
for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
{
CtrlVideo* pCtrlVideo = getBestCtrlVideo();
if( pCtrlVideo )
{
pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
(*it).pCtrlVideo = pCtrlVideo;
}
}
}
void VoutManager::discardVout( CtrlVideo* pCtrlVideo )
{
vector<SavedVout>::iterator it;
for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
{
if( (*it).pCtrlVideo == pCtrlVideo )
{
// detach vout thread from VideoControl
(*it).pCtrlVideo->detachVoutWindow( );
(*it).width = (*it).pCtrlVideo->getPosition()->getWidth();
(*it).height = (*it).pCtrlVideo->getPosition()->getHeight();
(*it).pCtrlVideo = NULL;
break;
}
}
}
void VoutManager::requestVout( CtrlVideo* pCtrlVideo )
{
vector<SavedVout>::iterator it;
for( it = m_SavedVoutVec.begin(); it != m_SavedVoutVec.end(); it++ )
{
if( (*it).pCtrlVideo == NULL )
{
pCtrlVideo->attachVoutWindow( (*it).pVoutWindow );
(*it).pCtrlVideo = pCtrlVideo;
break;
}
}
}
CtrlVideo* VoutManager::getBestCtrlVideo( )
{
// try to find an unused useable VideoControl
vector<CtrlVideo*>::const_iterator it;
for( it = m_pCtrlVideoVec.begin(); it != m_pCtrlVideoVec.end(); it++ )
{
if( (*it)->isUseable() && !(*it)->isUsed() )
{
return (*it);
}
}
return NULL;
}
void* VoutManager::acceptVout( vout_thread_t* pVout, int width, int height )
{
// Creation of a dedicated Window per vout thread
VoutWindow* pVoutWindow = new VoutWindow( getIntf(), pVout, width, height,
(GenericWindow*) m_pVoutMainWindow );
void* handle = pVoutWindow->getOSHandle();
// try to find a video Control within the theme
CtrlVideo* pCtrlVideo = getBestCtrlVideo();
if( pCtrlVideo )
{
// A Video Control is available
// directly attach vout thread to it
pCtrlVideo->attachVoutWindow( pVoutWindow );
}
// save vout characteristics
m_SavedVoutVec.push_back( SavedVout( pVout, pVoutWindow, pCtrlVideo ) );
msg_Dbg( getIntf(), "New incoming vout=0x%x, handle=0x%x, VideoCtrl=0x%x",
pVout, handle, pCtrlVideo );
return handle;
}
// Functions called by window provider
// ///////////////////////////////////
void *VoutManager::getWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
{
// Theme may have been destroyed
if( !pIntf->p_sys->p_theme )
return NULL;
VoutManager *pThis = pIntf->p_sys->p_voutManager;
vout_thread_t* pVout = pWnd->vout;
int width = (int)pWnd->width;
int height = (int)pWnd->height;
pThis->lockVout();
void* handle = pThis->acceptVout( pVout, width, height );
pThis->unlockVout();
return handle;
}
void VoutManager::releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd )
{
VoutManager *pThis = pIntf->p_sys->p_voutManager;
// Theme may have been destroyed
if( !pIntf->p_sys->p_theme )
return;
vout_thread_t* pVout = pWnd->vout;
pThis->lockVout();
// remove vout thread from savedVec
vector<SavedVout>::iterator it;
for( it = pThis->m_SavedVoutVec.begin(); it != pThis->m_SavedVoutVec.end(); it++ )
{
if( (*it).pVout == pVout )
{
msg_Dbg( pIntf, "vout released vout=0x%x, VideoCtrl=0x%x",
pVout, (*it).pCtrlVideo );
// if a video control was being used, detach from it
if( (*it).pCtrlVideo )
{
(*it).pCtrlVideo->detachVoutWindow( );
}
// remove resources
delete (*it).pVoutWindow;
pThis->m_SavedVoutVec.erase( it );
break;
}
}
pThis->unlockVout();
}
int VoutManager::controlWindow( struct vout_window_t *pWnd,
int query, va_list args )
{
intf_thread_t *pIntf = (intf_thread_t *)pWnd->p_private;
VoutManager *pThis = pIntf->p_sys->p_voutManager;
switch( query )
{
case VOUT_SET_SIZE:
{
unsigned int i_width = va_arg( args, unsigned int );
unsigned int i_height = va_arg( args, unsigned int );
if( i_width && i_height )
{
// Post a resize vout command
CmdResizeVout *pCmd =
new CmdResizeVout( pThis->getIntf(), pWnd->handle.hwnd,
i_width, i_height );
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
}
}
default:
msg_Dbg( pWnd, "control query not supported" );
break;
}
return VLC_SUCCESS;
}
/*****************************************************************************
* vout_manager.hpp
*****************************************************************************
* Copyright (C) 2009 the VideoLAN team
* $Id$
*
* Authors: Erwan Tulou < brezhoneg1 at yahoo.fr r>
*
* 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 VOUTMANAGER_HPP
#define VOUTMANAGER_HPP
#include <vector>
#include <vlc_vout.h>
#include <vlc_window.h>
#include "../utils/position.hpp"
#include "../commands/cmd_generic.hpp"
#include "../controls/ctrl_video.hpp"
class VarBool;
class GenericWindow;
#include <stdio.h>
class SavedVout
{
public:
SavedVout( vout_thread_t* pVout, VoutWindow* pVoutWindow = NULL,
CtrlVideo* pCtrlVideo = NULL, int height = 0, int width = 0 ) :
pVout( pVout ), pVoutWindow( pVoutWindow ), pCtrlVideo( pCtrlVideo ),
height( height ), width( width ) {}
~SavedVout() {}
vout_thread_t* pVout;
VoutWindow *pVoutWindow;
CtrlVideo *pCtrlVideo;
int height;
int width;
};
class VoutMainWindow: public GenericWindow
{
public:
VoutMainWindow( intf_thread_t *pIntf, int left = 0, int top = 0 ) :
GenericWindow( pIntf, left, top, false, false, NULL )
{
resize( 10, 10 );
move( -50, -50 );
}
virtual ~VoutMainWindow() {}
};
/// Singleton object handling VLC internal state and playlist
class VoutManager: public SkinObject
{
public:
/// Get the instance of VoutManager
/// Returns NULL if the initialization of the object failed
static VoutManager *instance( intf_thread_t *pIntf );
/// Delete the instance of VoutManager
static void destroy( intf_thread_t *pIntf );
/// Callback to request a vout window
static void *getWindow( intf_thread_t *pIntf, vout_window_t *pWnd );
/// Accept Vout
void* acceptVout( vout_thread_t* pVout, int width, int height );
// Window provider (release)
static void releaseWindow( intf_thread_t *pIntf, vout_window_t *pWnd );
/// Callback to change a vout window
static int controlWindow( struct vout_window_t *pWnd,
int query, va_list args );
// Register Video Controls (when building theme)
void registerCtrlVideo( CtrlVideo* p_CtrlVideo );
// save and restore vouts (when changing theme)
void saveVoutConfig( );
void restoreVoutConfig( bool b_success );
// save and restore vouts (when swapping Layout)
void discardVout( CtrlVideo* pCtrlVideo );
void requestVout( CtrlVideo* pCtrlVideo );
// get a VoutWindow
void* getHandle( vout_thread_t* pVout, int width, int height );
// get a useable video Control
CtrlVideo* getBestCtrlVideo( );
// get the VoutMainWindow
VoutMainWindow* getVoutMainWindow() { return m_pVoutMainWindow; }
// (un)lock functions to protect vout sets
void lockVout( ) { vlc_mutex_lock( &vout_lock ); }
void unlockVout( ) { vlc_mutex_unlock( &vout_lock ); }
protected:
// Protected because it is a singleton
VoutManager( intf_thread_t *pIntf );
virtual ~VoutManager();
private:
vector<CtrlVideo *> m_pCtrlVideoVec;
vector<CtrlVideo *> m_pCtrlVideoVecBackup;
vector<SavedVout> m_SavedVoutVec;
VoutMainWindow* m_pVoutMainWindow;
vlc_mutex_t vout_lock;
};
#endif
......@@ -22,38 +22,49 @@
*****************************************************************************/
#include "vout_window.hpp"
#include "vout_manager.hpp"
#include "vlcproc.hpp"
#include "theme.hpp"
#include "os_factory.hpp"
#include "os_graphics.hpp"
#include "os_window.hpp"
int VoutWindow::count = 0;
VoutWindow::VoutWindow( intf_thread_t *pIntf, int left, int top,
bool dragDrop, bool playOnDrop,
GenericWindow &rParent ):
GenericWindow( pIntf, left, top, dragDrop, playOnDrop,
&rParent ), m_pImage( NULL )
VoutWindow::VoutWindow( intf_thread_t *pIntf, vout_thread_t* pVout,
int width, int height, GenericWindow* pParent ) :
GenericWindow( pIntf, 0, 0, false, false, pParent ),
m_pVout( pVout ), original_width( width ), original_height( height ),
m_pParentWindow( pParent ), m_pImage( NULL )
{
// counter for debug
count++;
if( m_pVout )
vlc_object_hold( m_pVout );
// needed on MS-Windows to prevent vlc hanging
show();
}
VoutWindow::~VoutWindow()
{
delete m_pImage;
if( m_pVout )
vlc_object_release( m_pVout );
// Get the VlcProc
VlcProc *pVlcProc = getIntf()->p_sys->p_vlcProc;
// Reparent the video output
if( pVlcProc && pVlcProc->isVoutUsed() )
{
pVlcProc->dropVout();
}
count--;
msg_Dbg( getIntf(), "VoutWindow count = %d", count );
}
void VoutWindow::resize( int width, int height )
{
// don't try to resize with zero value
if( !width || !height )
return;
// Get the OSFactory
OSFactory *pOsFactory = OSFactory::instance( getIntf() );
......@@ -72,11 +83,7 @@ void VoutWindow::refresh( int left, int top, int width, int height )
{
if( m_pImage )
{
// Get the VlcProc
VlcProc *pVlcProc = getIntf()->p_sys->p_vlcProc;
// Refresh only when there is no video!
if( pVlcProc && !pVlcProc->isVoutUsed() )
if( !m_pCtrlVideo )
{
m_pImage->copyToWindow( *getOSWindow(), left, top,
width, height, left, top );
......@@ -84,3 +91,27 @@ void VoutWindow::refresh( int left, int top, int width, int height )
}
}
void VoutWindow::setCtrlVideo( CtrlVideo* pCtrlVideo )
{
if( pCtrlVideo )
{
const Position *pPos = pCtrlVideo->getPosition();
int x = pPos->getLeft();
int y = pPos->getTop();
int w = pPos->getWidth();
int h = pPos->getHeight();
setParent( pCtrlVideo->getWindow(), x, y, w, h );
m_pParentWindow = pCtrlVideo->getWindow();
}
else
{
setParent( VoutManager::instance( getIntf() )->getVoutMainWindow(),
0, 0, 0, 0 );
m_pParentWindow =
VoutManager::instance( getIntf() )->getVoutMainWindow();
}
m_pCtrlVideo = pCtrlVideo;
}
......@@ -27,34 +27,64 @@
#include "generic_window.hpp"
class OSGraphics;
class CtrlVideo;
/// Class to handle a video output window
class VoutWindow: private GenericWindow
{
public:
VoutWindow( intf_thread_t *pIntf, int xPos, int yPos,
bool dragDrop, bool playOnDrop, GenericWindow &rParent );
VoutWindow( intf_thread_t *pIntf, vout_thread_t* pVout,
int width, int height, GenericWindow* pParent = NULL );
virtual ~VoutWindow();
// counter used for debugging purpose
static int count;
/// Make some functions public
//@{
using GenericWindow::show;
using GenericWindow::hide;
using GenericWindow::move;
using GenericWindow::getOSHandle;
//@}
/// Resize the window
virtual void resize( int width, int height );
/// get the parent window
virtual GenericWindow* getWindow( ) { return m_pParentWindow; }
/// Refresh an area of the window
virtual void refresh( int left, int top, int width, int height );
/// set Video Control for VoutWindow
virtual void setCtrlVideo( CtrlVideo* pCtrlVideo );
/// get original size of vout
virtual int getOriginalWidth( ) { return original_width; }
virtual int getOriginalHeight( ) { return original_height; }
virtual string getType() const { return "Vout"; }
private:
/// Image when there is no video
OSGraphics *m_pImage;
/// vout thread
vout_thread_t* m_pVout;
/// original width and height
int original_width;
int original_height;
/// VideoControl attached to it
CtrlVideo* m_pCtrlVideo;
/// Parent Window
GenericWindow* m_pParentWindow;
};
typedef CountedPtr<VoutWindow> VoutWindowPtr;
......
......@@ -639,3 +639,4 @@ void WindowManager::setActiveLayout( TopWindow &rWindow,
// Rebuild the dependencies
stopMove();
}
......@@ -54,18 +54,19 @@ Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
if( pParentWindow )
{
// Child window (for vout)
HWND hParent = pParentWindow->getHandle();
m_hWnd_parent = pParentWindow->getHandle();
m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW, "SkinWindowClass",
"default name", WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, hParent, 0, hInst, NULL );
CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd_parent, 0, hInst, NULL );
}
else
{
// Normal window
m_hWnd_parent = hParentWindow;
m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW, "SkinWindowClass",
"default name", WS_POPUP | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, hParentWindow, 0, hInst, NULL );
CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd_parent, 0, hInst, NULL );
}
if( !m_hWnd )
......@@ -86,22 +87,11 @@ Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
// Register the window as a drop target
RegisterDragDrop( m_hWnd, m_pDropTarget );
}
// Set this window as a vout
if( m_pParent )
{
VlcProc::instance( getIntf() )->registerVoutWindow( (void*)m_hWnd );
}
}
Win32Window::~Win32Window()
{
if( m_pParent )
{
VlcProc::instance( getIntf() )->unregisterVoutWindow( (void*)m_hWnd );
}
Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() );
pFactory->m_windowMap[m_hWnd] = NULL;
......@@ -119,6 +109,14 @@ Win32Window::~Win32Window()
}
void Win32Window::reparent( void* OSHandle, int x, int y, int w, int h )
{
// Reparent the window
SetParent( m_hWnd, (HWND)OSHandle );
MoveWindow( m_hWnd, x, y, w, h, true );
}
void Win32Window::show( int left, int top ) const
{
ShowWindow( m_hWnd, SW_SHOW );
......
......@@ -62,9 +62,17 @@ class Win32Window: public OSWindow
/// Getter for the window handle
HWND getHandle() const { return m_hWnd; }
/// Getter for the window handle
void* getOSHandle() const { return (void*) m_hWnd; }
/// reparent the window
void reparent( void* OSHandle, int x, int y, int w, int h );
private:
/// Window handle
HWND m_hWnd;
/// Window parent's handle
HWND m_hWnd_parent;
/// Indicates whether the window handles drag&drop events
bool m_dragDrop;
/// Drop target
......
......@@ -55,6 +55,10 @@ X11Factory::~X11Factory()
bool X11Factory::init()
{
// make sure xlib is safe-thread
if( !XInitThreads() )
msg_Err( getIntf(), "initializing xlib for multi-threading failed" );
// Create the X11 display
m_pDisplay = new X11Display( getIntf() );
......
......@@ -175,7 +175,6 @@ void X11Loop::handleX11Event()
if( !pWin )
{
msg_Warn( getIntf(), "no associated generic window" );
return;
}
......
......@@ -41,20 +41,36 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
OSWindow( pIntf ), m_rDisplay( rDisplay ), m_pParent( pParentWindow ),
m_dragDrop( dragDrop )
{
Window parent;
if (pParentWindow)
{
parent = pParentWindow->m_wnd;
m_wnd_parent = pParentWindow->m_wnd;
}
else
{
parent = DefaultRootWindow( XDISPLAY );
m_wnd_parent = DefaultRootWindow( XDISPLAY );
}
XSetWindowAttributes attr;
attr.event_mask = ExposureMask | StructureNotifyMask;
// Create the window
m_wnd = XCreateWindow( XDISPLAY, parent, 0, 0, 1, 1, 0, 0,
InputOutput, CopyFromParent, 0, &attr );
m_wnd = XCreateWindow( XDISPLAY, m_wnd_parent, -10, 0, 1, 1, 0, 0,
InputOutput, CopyFromParent, CWEventMask, &attr );
// Make sure window is created before returning
XMapWindow( XDISPLAY, m_wnd );
bool b_map_notify = false;
do
{
XEvent xevent;
XWindowEvent( XDISPLAY, m_wnd, SubstructureNotifyMask |
StructureNotifyMask, &xevent);
if( (xevent.type == MapNotify)
&& (xevent.xmap.window == m_wnd ) )
{
b_map_notify = true;
}
} while( ! b_map_notify );
XUnmapWindow( XDISPLAY, m_wnd );
// Set the colormap for 8bpp mode
if( XPIXELSIZE == 1 )
......@@ -109,22 +125,11 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
// Associate the window to the main "parent" window
XSetTransientForHint( XDISPLAY, m_wnd, m_rDisplay.getMainWindow() );
// Set this window as a vout
if( m_pParent )
{
VlcProc::instance( getIntf() )->registerVoutWindow( (void*)m_wnd );
}
}
X11Window::~X11Window()
{
if( m_pParent )
{
VlcProc::instance( getIntf() )->unregisterVoutWindow( (void*)m_wnd );
}
X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() );
pFactory->m_windowMap[m_wnd] = NULL;
pFactory->m_dndMap[m_wnd] = NULL;
......@@ -137,6 +142,19 @@ X11Window::~X11Window()
XSync( XDISPLAY, False );
}
void X11Window::reparent( void* OSHandle, int x, int y, int w, int h )
{
// Reparent the window
Window new_parent =
OSHandle ? (Window) OSHandle : DefaultRootWindow( XDISPLAY );
if( w && h )
XResizeWindow( XDISPLAY, m_wnd, w, h );
XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
m_wnd_parent = new_parent;
}
void X11Window::show( int left, int top ) const
{
......@@ -155,7 +173,10 @@ void X11Window::hide() const
void X11Window::moveResize( int left, int top, int width, int height ) const
{
XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
if( width && height )
XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
else
XMoveWindow( XDISPLAY, m_wnd, left, top );
}
......
......@@ -65,11 +65,22 @@ class X11Window: public OSWindow
/// Get the window ID
Window getDrawable() const { return m_wnd; }
/// Getter for the handler
void* getOSHandle() const { return (void*) m_wnd; }
/// Getter for the handler
void* getParentOSHandle() const { return (void*) m_wnd_parent; }
/// reparent the window
void reparent( void* OSHandle, int x, int y, int w, int h );
private:
/// X11 display
X11Display &m_rDisplay;
/// Window ID
Window m_wnd;
/// Window ID
Window m_wnd_parent;
/// Parent window
X11Window *m_pParent;
/// Indicates whether the window handles drag&drop events
......
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