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 \
\
#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()
pOldTheme->getWindowManager().hideAll();
}
+ VoutManager::instance( getIntf() )->lockVout();
+ VoutManager::instance( getIntf() )->saveVoutConfig();
+
ThemeLoader loader( getIntf() );
if( loader.load( m_file ) )
{
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() );
#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,
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();
+}
+
#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
};
+/// 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
/// 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;
#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"
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 );
}
VarBox &rVoutSize = VlcProc::instance( getIntf() )->getVoutSizeVar();
rVoutSize.delObserver( this );
- delete m_pVout;
+ //m_pLayout->getActiveVar().delObserver( this );
+
+ if( m_pVisible )
+ m_pVisible->delObserver( this );
}
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() );
}
}
}
-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
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();
}
#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>
/// 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
#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,
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
// Check if it is a video control
if( pControl->getType() == "video" )
{
- m_pVideoControl = (CtrlVideo*)pControl;
+ m_pVideoCtrlSet.insert( (CtrlVideo*)pControl );
}
}
else
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 );
}
}
}
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 );
- }
}
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 );
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
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;
}
}
+
+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 );
+}
{
private:
friend class WindowManager;
+ friend class VoutManager;
+ friend class CtrlVideo;
public:
GenericWindow( intf_thread_t *pIntf, int xPos, int yPos,
bool dragDrop, bool playOnDrop,
/// 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; }
/// 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 ) {}
};
class OSLoop;
class VarManager;
class VlcProc;
+class VoutManager;
class Theme;
class ThemeRepository;
VarManager *p_varManager;
/// VLC state handler
VlcProc *p_vlcProc;
+ /// Vout manager
+ VoutManager *p_voutManager;
/// Theme repository
ThemeRepository *p_repository;
#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"
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;
#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 );
{
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 );
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
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
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 );
}
//---------------------------------------------------------------------------
}
free( skin_last );
- // The new theme cannot embed a video output yet
- VlcProc::instance( getIntf() )->dropVout();
-
return true;
}
if( getIntf()->p_sys->p_input )
{
vlc_object_release( getIntf()->p_sys->p_input );
+ getIntf()->p_sys->p_input = NULL;
}
interaction_Unregister( getIntf() );
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 ?
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 )
#include <set>
+#include <vlc_vout.h>
#include "../vars/equalizer.hpp"
#include "../vars/playtree.hpp"
#include "../vars/time.hpp"
#include "../utils/position.hpp"
#include "../utils/var_text.hpp"
#include "../commands/cmd_generic.hpp"
+#include "../controls/ctrl_video.hpp"
class OSTimer;
class VarBool;
/// 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 );
/// 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
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,
--- /dev/null
+/*****************************************************************************
+ * 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;
+}
+
--- /dev/null
+/*****************************************************************************
+ * 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
*****************************************************************************/
#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() );
{
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 );
}
}
+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;
+}
+
#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;
// Rebuild the dependencies
stopMove();
}
+
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 )
// 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;
}
+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 );
/// 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
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() );
if( !pWin )
{
- msg_Warn( getIntf(), "no associated generic window" );
return;
}
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 )
// 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;
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
{
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 );
}
/// 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