], [
PKG_CHECK_MODULES([XPM], [xpm])
+ PKG_CHECK_MODULES([XINERAMA], [xinerama])
PKG_CHECK_MODULES([XEXT], [xext])
VLC_ADD_CPPFLAGS([skins2],[-Imodules/gui/skins2 ${X_CFLAGS} ${XEXT_CFLAGS} ${XPM_CFLAGS} -DX11_SKINS])
VLC_ADD_CXXFLAGS([skins2],[-O2 -fno-rtti])
- VLC_ADD_LIBS([skins2],[${X_LIBS} ${X_PRE_LIBS} ${XEXT_LIBS} ${XPM_LIBS} -lX11])
+ VLC_ADD_LIBS([skins2],[${X_LIBS} ${X_PRE_LIBS} ${XEXT_LIBS} ${XPM_LIBS} ${XINERAMA_LIBS} -lX11])
])
VLC_ADD_PLUGIN([skins2])
}
+void FscWindow::moveTo( int x, int y, int width, int height )
+{
+ // relocate the fs controller
+ // (centered horizontally and lowered vertically with a 3% margin)
+ int x_fsc = x + ( width - getWidth() ) / 2;
+ int y_fsc = y + height - getHeight() - height * 3 / 100;
+ move( x_fsc, y_fsc );
+}
+
+
void FscWindow::CmdFscHide::execute()
{
m_pParent->onTimerExpired();
/// Action for each transition of fading out
virtual void onTimerExpired();
+ /// Relocate fsc into new area
+ virtual void moveTo( int x, int y, int width, int height );
+
private:
/// Timer for fsc fading-out
OSTimer *m_pTimer;
refresh( left, top, width, height );
}
}
+
+
+void GenericWindow::getMonitorInfo( int* x, int* y, int* width, int* height ) const
+{
+ OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+ pOsFactory->getMonitorInfo( *this, x, y, width, height );
+}
int getTop() const { return m_top; }
int getWidth() const { return m_width; }
int getHeight() const { return m_height; }
+ void getMonitorInfo( int* x, int* y, int* width, int* height ) const;
/// Give access to the visibility variable
VarBool &getVisibleVar() { return *m_pVarVisible; }
virtual int getScreenWidth() const = 0;
virtual int getScreenHeight() const = 0;
+ /// Get Monitor Information for a given Window
+ virtual void getMonitorInfo( const GenericWindow &rWindow,
+ int* x, int* y,
+ int* width, int* height ) const = 0;
+
+ /// Get Monitor Information (screens numbered from 0 upwards.)
+ virtual void getMonitorInfo( int num, int* x, int* y,
+ int* width, int* height ) const = 0;
+
/// Get the work area (screen area without taskbars)
virtual SkinsRect getWorkArea() const = 0;
msg_Dbg( pWnd, "setFullscreen (%i) received from vout thread",
b_fullscreen );
+ // reconfigure the fullscreen window (multiple screens)
+ if( b_fullscreen )
+ {
+ vector<SavedWnd>::iterator it;
+ for( it = m_SavedWndVec.begin(); it != m_SavedWndVec.end(); ++it )
+ {
+ if( (*it).pWnd == pWnd )
+ {
+ VoutWindow* pVoutWindow = it->pVoutWindow;
+ configureFullscreen( *pVoutWindow );
+ }
+ break;
+ }
+ }
+
+ // set fullscreen
VlcProc::instance( getIntf() )->setFullscreenVar( b_fullscreen );
}
}
}
+
+void VoutManager::configureFullscreen( VoutWindow& rWindow )
+{
+ int numScr = var_InheritInteger( getIntf(), "qt-fullscreen-screennumber" );
+ int x0 = m_pVoutMainWindow->getTop();
+ int y0 = m_pVoutMainWindow->getLeft();
+
+ int x, y, w, h;
+ if( numScr >= 0 )
+ {
+ // select screen requested by user
+ OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+ pOsFactory->getMonitorInfo( numScr, &x, &y, &w, &h );
+ }
+ else
+ {
+ // select screen where display is already occurring
+ rWindow.getMonitorInfo( &x, &y, &w, &h );
+ }
+
+ if( x != x0 || y != y0 )
+ {
+ // move and resize fullscreen
+ m_pVoutMainWindow->move( x, y );
+ m_pVoutMainWindow->resize( w, h );
+
+ // ensure the fs controller is also moved
+ if( m_pFscWindow )
+ {
+ m_pFscWindow->moveTo( x, y, w, h );
+ }
+ }
+}
#include "../controls/ctrl_video.hpp"
#include "../events/evt_key.hpp"
#include "../events/evt_scroll.hpp"
+#include "../src/fsc_window.hpp"
class VarBool;
class GenericWindow;
/// called when fullscreen variable changed
virtual void onUpdate( Subject<VarBool> &rVariable , void* );
+ /// reconfigure fullscreen (multiple screens)
+ virtual void configureFullscreen( VoutWindow& rWindow );
+
protected:
// Protected because it is a singleton
VoutManager( intf_thread_t *pIntf );
using GenericWindow::move;
using GenericWindow::resize;
using GenericWindow::getOSHandle;
+ using GenericWindow::getMonitorInfo;
//@}
/// get the parent window
}
+BOOL CALLBACK Win32Factory::MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor,
+ LPRECT lprcMonitor, LPARAM dwData )
+{
+ (void)hdcMonitor; (void)lprcMonitor;
+ list<HMONITOR>* pList = (list<HMONITOR>*)dwData;
+ pList->push_back( hMonitor );
+
+ return TRUE;
+}
+
Win32Factory::Win32Factory( intf_thread_t *pIntf ):
OSFactory( pIntf ), m_hParentWindow( NULL ),
m_dirSep( "\\" )
m_resourcePath.push_back( (string)datadir + "\\share\\skins2" );
free( datadir );
+ // Enumerate all monitors available
+ EnumDisplayMonitors( NULL, NULL, MonitorEnumProc, (LPARAM)&m_monitorList );
+ int num = 0;
+ for( list<HMONITOR>::iterator it = m_monitorList.begin();
+ it != m_monitorList.end(); ++it, num++ )
+ {
+ MONITORINFO mi;
+ mi.cbSize = sizeof( MONITORINFO );
+ if( GetMonitorInfo( *it, &mi ) )
+ {
+ msg_Dbg( getIntf(), "monitor #%i, %ldx%ld at +%ld+%ld", num,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ mi.rcMonitor.left,
+ mi.rcMonitor.top );
+ }
+ }
+
// All went well
return true;
}
}
+void Win32Factory::getMonitorInfo( const GenericWindow &rWindow,
+ int* p_x, int* p_y,
+ int* p_width, int* p_height ) const
+{
+ HWND wnd = (HWND)rWindow.getOSHandle();
+ HMONITOR hmon = MonitorFromWindow( wnd, MONITOR_DEFAULTTONEAREST );
+ MONITORINFO mi;
+ mi.cbSize = sizeof( MONITORINFO );
+ if( hmon && GetMonitorInfo( hmon, &mi ) )
+ {
+ *p_x = mi.rcMonitor.left;
+ *p_y = mi.rcMonitor.top;
+ *p_width = mi.rcMonitor.right - mi.rcMonitor.left;
+ *p_height = mi.rcMonitor.bottom - mi.rcMonitor.top;
+ }
+ else
+ {
+ *p_x = 0;
+ *p_y = 0;
+ *p_width = getScreenWidth();
+ *p_height = getScreenHeight();
+ }
+}
+
+
+void Win32Factory::getMonitorInfo( int numScreen, int* p_x, int* p_y,
+ int* p_width, int* p_height ) const
+{
+ HMONITOR hmon = NULL;
+ list<HMONITOR>::const_iterator it = m_monitorList.begin();
+ for( int i = 0; it != m_monitorList.end(); ++it, i++ )
+ {
+ if( i == numScreen )
+ {
+ hmon = *it;
+ break;
+ }
+ }
+ MONITORINFO mi;
+ mi.cbSize = sizeof( MONITORINFO );
+ if( hmon && GetMonitorInfo( hmon, &mi ) )
+ {
+ *p_x = mi.rcMonitor.left;
+ *p_y = mi.rcMonitor.top;
+ *p_width = mi.rcMonitor.right - mi.rcMonitor.left;
+ *p_height = mi.rcMonitor.bottom - mi.rcMonitor.top;
+ }
+ else
+ {
+ *p_x = 0;
+ *p_y = 0;
+ *p_width = getScreenWidth();
+ *p_height = getScreenHeight();
+ }
+}
+
+
SkinsRect Win32Factory::getWorkArea() const
{
RECT r;
virtual int getScreenWidth() const;
virtual int getScreenHeight() const;
+ /// Get Monitor Information
+ virtual void getMonitorInfo( const GenericWindow &rWindow,
+ int* x, int* y,
+ int* width, int* height ) const;
+ virtual void getMonitorInfo( int numScreen,
+ int* x, int* y,
+ int* width, int* height ) const;
+
/// Get the work area (screen area without taskbars)
virtual SkinsRect getWorkArea() const;
static LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam );
+ /// Callback (enumerate multiple screens)
+ static BOOL CALLBACK MonitorEnumProc( HMONITOR hMonitor, HDC hdcMonitor,
+ LPRECT lprcMonitor, LPARAM dwData );
private:
/// Handle of the instance
HINSTANCE m_hInst;
const string m_dirSep;
/// Resource path
list<string> m_resourcePath;
+ /// Monitors detected
+ list<HMONITOR> m_monitorList;
};
#include <dirent.h>
#include <sys/stat.h>
#include <X11/Xlib.h>
+#include <X11/extensions/Xinerama.h>
#include "x11_factory.hpp"
#include "x11_display.hpp"
m_resourcePath.push_back( (string)datadir + "/skins2" );
free( datadir );
+ // Determine the monitor geometry
+ getDefaultGeometry( &m_screenWidth, &m_screenHeight );
+
return true;
}
int X11Factory::getScreenWidth() const
{
- Display *pDisplay = m_pDisplay->getDisplay();
- int screen = DefaultScreen( pDisplay );
- return DisplayWidth( pDisplay, screen );
+ return m_screenWidth;
}
int X11Factory::getScreenHeight() const
{
+ return m_screenHeight;
+}
+
+
+void X11Factory::getMonitorInfo( const GenericWindow &rWindow,
+ int* p_x, int* p_y,
+ int* p_width, int* p_height ) const
+{
+ // initialize to default geometry
+ *p_x = 0;
+ *p_y = 0;
+ *p_width = getScreenWidth();
+ *p_height = getScreenHeight();
+
+ // Use Xinerama to determine the monitor where the video
+ // mostly resides (biggest surface)
Display *pDisplay = m_pDisplay->getDisplay();
+ Window wnd = (Window)rWindow.getOSHandle();
+ Window root = DefaultRootWindow( pDisplay );
+ Window child_wnd;
+
+ int x, y;
+ unsigned int w, h, border, depth;
+ XGetGeometry( pDisplay, wnd, &root, &x, &y, &w, &h, &border, &depth );
+ XTranslateCoordinates( pDisplay, wnd, root, 0, 0, &x, &y, &child_wnd );
+
+ int num;
+ XineramaScreenInfo* info = XineramaQueryScreens( pDisplay, &num );
+ if( info )
+ {
+ unsigned int surface = 0;
+ for( int i = 0; i < num; i++ )
+ {
+ Region reg1 = XCreateRegion();
+ XRectangle rect1 = { info[i].x_org, info[i].y_org,
+ info[i].width, info[i].height };
+ XUnionRectWithRegion( &rect1, reg1, reg1 );
+
+ Region reg2 = XCreateRegion();
+ XRectangle rect2 = { x, y, w, h };
+ XUnionRectWithRegion( &rect2, reg2, reg2 );
+
+ Region reg = XCreateRegion();
+ XIntersectRegion( reg1, reg2, reg );
+ XRectangle rect;
+ XClipBox( reg, &rect );
+ unsigned int surf = rect.width * rect.height;
+ if( surf > surface )
+ {
+ surface = surf;
+ *p_x = info[i].x_org;
+ *p_y = info[i].y_org;
+ *p_width = info[i].width;
+ *p_height = info[i].height;
+ }
+ }
+ XFree( info );
+ }
+}
+
+
+void X11Factory::getMonitorInfo( int numScreen,
+ int* p_x, int* p_y,
+ int* p_width, int* p_height ) const
+{
+ // initialize to default geometry
+ *p_x = 0;
+ *p_y = 0;
+ *p_width = getScreenWidth();
+ *p_height = getScreenHeight();
+
+ // try to detect the requested screen via Xinerama
+ if( numScreen >= 0 )
+ {
+ int num;
+ Display *pDisplay = m_pDisplay->getDisplay();
+ XineramaScreenInfo* info = XineramaQueryScreens( pDisplay, &num );
+ if( info )
+ {
+ if( numScreen < num )
+ {
+ *p_x = info[numScreen].x_org;
+ *p_y = info[numScreen].y_org;
+ *p_width = info[numScreen].width;
+ *p_height = info[numScreen].height;
+ }
+ XFree( info );
+ }
+ }
+}
+
+
+void X11Factory::getDefaultGeometry( int* p_width, int* p_height ) const
+{
+ Display *pDisplay = m_pDisplay->getDisplay();
+
+ // Initialize to defaults
int screen = DefaultScreen( pDisplay );
- return DisplayHeight( pDisplay, screen );
+ *p_width = DisplayWidth( pDisplay, screen );
+ *p_height = DisplayHeight( pDisplay, screen );
+
+ // Use Xinerama to restrain to the first monitor instead of the full
+ // virtual screen
+ int num;
+ XineramaScreenInfo* info = XineramaQueryScreens( pDisplay, &num );
+ if( info )
+ {
+ for( int i = 0; i < num; i++ )
+ {
+ if( info[i].x_org == 0 && info[i].y_org == 0 )
+ {
+ *p_width = info[i].width;
+ *p_height = info[i].height;
+ break;
+ }
+ }
+ XFree( info );
+ }
}
rmdir( rPath.c_str() );
}
-
#endif
virtual int getScreenWidth() const;
virtual int getScreenHeight() const;
+ /// Get Monitor Information
+ virtual void getMonitorInfo( const GenericWindow &rWindow,
+ int* x, int* y,
+ int* width, int* height ) const;
+ virtual void getMonitorInfo( int numScreen,
+ int* x, int* y,
+ int* width, int* height ) const;
+
+ virtual void getDefaultGeometry( int* width, int* height ) const;
+
/// Get the work area (screen area without taskbars)
virtual SkinsRect getWorkArea() const;
const string m_dirSep;
/// Resource path
list<string> m_resourcePath;
+ /// Monitor geometry
+ int m_screenWidth, m_screenHeight;
};
#endif