X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fskins2%2Fsrc%2Fwindow_manager.cpp;h=807fcb7c1ed095736fac6d0be49c63ffcb1b0318;hb=64c2daf417e2525f19ac608b9c02e2c1dab42757;hp=0ebb82468a6f54c76d0d3433e3cd6b4e6ed2aced;hpb=dccb47b82b469f118b6ced550c3cee3bc7ad202c;p=vlc diff --git a/modules/gui/skins2/src/window_manager.cpp b/modules/gui/skins2/src/window_manager.cpp index 0ebb82468a..807fcb7c1e 100644 --- a/modules/gui/skins2/src/window_manager.cpp +++ b/modules/gui/skins2/src/window_manager.cpp @@ -5,7 +5,7 @@ * $Id$ * * Authors: Cyril Deguet - * Olivier Teulière + * Olivier Teulière * * 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 @@ -19,7 +19,7 @@ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #include "window_manager.hpp" @@ -28,17 +28,20 @@ #include "os_factory.hpp" #include "anchor.hpp" #include "tooltip.hpp" -#include "../utils/position.hpp" -#include "../src/var_manager.hpp" +#include "var_manager.hpp" WindowManager::WindowManager( intf_thread_t *pIntf ): - SkinObject( pIntf ), m_magnet( 0 ), m_pTooltip( NULL ) + SkinObject( pIntf ), m_magnet( 0 ), m_direction( kNone ), + m_maximizeRect(0, 0, 50, 50), m_pTooltip( NULL ), m_pPopup( NULL ), + m_alpha( 255 ), m_moveAlpha( 255 ), m_OpacityEnabled( false ) { // Create and register a variable for the "on top" status VarManager *pVarManager = VarManager::instance( getIntf() ); m_cVarOnTop = VariablePtr( new VarBoolImpl( getIntf() ) ); pVarManager->registerVar( m_cVarOnTop, "vlc.isOnTop" ); + + m_OpacityEnabled = var_InheritBool( getIntf(), "skins2-transparency" ); } @@ -70,25 +73,15 @@ void WindowManager::startMove( TopWindow &rWindow ) m_movingWindows.clear(); buildDependSet( m_movingWindows, &rWindow ); -#ifdef WIN32 - if( config_GetInt( getIntf(), "skins2-transparency" ) ) + if( isOpacityNeeded() ) { // Change the opacity of the moving windows WinSet_t::const_iterator it; - for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ ) + for( it = m_movingWindows.begin(); it != m_movingWindows.end(); ++it ) { (*it)->setOpacity( m_moveAlpha ); } - - // FIXME: We need to refresh the windows, because if 2 windows overlap - // and one of them becomes transparent, the other one is not refreshed - // automatically. I don't know why... -- Ipkiss - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) - { - (*it)->refresh( 0, 0, (*it)->getWidth(), (*it)->getHeight() ); - } } -#endif } @@ -97,31 +90,29 @@ void WindowManager::stopMove() WinSet_t::const_iterator itWin1, itWin2; AncList_t::const_iterator itAnc1, itAnc2; -#ifdef WIN32 - if( config_GetInt( getIntf(), "skins2-transparency" ) ) + if( isOpacityNeeded() ) { // Restore the opacity of the moving windows WinSet_t::const_iterator it; - for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ ) + for( it = m_movingWindows.begin(); it != m_movingWindows.end(); ++it ) { (*it)->setOpacity( m_alpha ); } } -#endif // Delete the dependencies m_dependencies.clear(); // Now we rebuild the dependencies. // Iterate through all the windows - for( itWin1 = m_allWindows.begin(); itWin1 != m_allWindows.end(); itWin1++ ) + for( itWin1 = m_allWindows.begin(); itWin1 != m_allWindows.end(); ++itWin1 ) { // Get the anchors of the layout associated to the window const AncList_t &ancList1 = (*itWin1)->getActiveLayout().getAnchorList(); // Iterate through all the windows, starting with (*itWin1) - for( itWin2 = itWin1; itWin2 != m_allWindows.end(); itWin2++ ) + for( itWin2 = itWin1; itWin2 != m_allWindows.end(); ++itWin2 ) { // A window can't anchor itself... if( (*itWin2) == (*itWin1) ) @@ -130,10 +121,10 @@ void WindowManager::stopMove() // Now, check for anchoring between the 2 windows const AncList_t &ancList2 = (*itWin2)->getActiveLayout().getAnchorList(); - for( itAnc1 = ancList1.begin(); itAnc1 != ancList1.end(); itAnc1++ ) + for( itAnc1 = ancList1.begin(); itAnc1 != ancList1.end(); ++itAnc1 ) { for( itAnc2 = ancList2.begin(); - itAnc2 != ancList2.end(); itAnc2++ ) + itAnc2 != ancList2.end(); ++itAnc2 ) { if( (*itAnc1)->isHanging( **itAnc2 ) ) { @@ -163,17 +154,207 @@ void WindowManager::move( TopWindow &rWindow, int left, int top ) const // Move all the windows WinSet_t::const_iterator it; - for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ ) + for( it = m_movingWindows.begin(); it != m_movingWindows.end(); ++it ) { (*it)->move( (*it)->getLeft() + xOffset, (*it)->getTop() + yOffset ); } } +void WindowManager::startResize( GenericLayout &rLayout, Direction_t direction ) +{ + m_direction = direction; + + // Rebuild the set of moving windows. + // From the resized window, we only take into account the anchors which + // are mobile with the current type of resizing, and that are hanging a + // window. The hanged windows will come will all their dependencies. + + m_resizeMovingE.clear(); + m_resizeMovingS.clear(); + m_resizeMovingSE.clear(); + + WinSet_t::const_iterator itWin; + AncList_t::const_iterator itAnc1, itAnc2; + // Get the anchors of the layout + const AncList_t &ancList1 = rLayout.getAnchorList(); + + // Iterate through all the hanged windows + for( itWin = m_dependencies[rLayout.getWindow()].begin(); + itWin != m_dependencies[rLayout.getWindow()].end(); ++itWin ) + { + // Now, check for anchoring between the 2 windows + const AncList_t &ancList2 = + (*itWin)->getActiveLayout().getAnchorList(); + for( itAnc1 = ancList1.begin(); itAnc1 != ancList1.end(); ++itAnc1 ) + { + for( itAnc2 = ancList2.begin(); + itAnc2 != ancList2.end(); ++itAnc2 ) + { + if( (*itAnc1)->isHanging( **itAnc2 ) ) + { + // Add the dependencies of the hanged window to one of the + // lists of moving windows + Position::Ref_t aRefPos = + (*itAnc1)->getPosition().getRefLeftTop(); + if( aRefPos == Position::kRightTop ) + buildDependSet( m_resizeMovingE, *itWin ); + else if( aRefPos == Position::kLeftBottom ) + buildDependSet( m_resizeMovingS, *itWin ); + else if( aRefPos == Position::kRightBottom ) + buildDependSet( m_resizeMovingSE, *itWin ); + break; + } + } + } + } + + // The checkAnchors() method will need to have m_movingWindows properly set + // so let's insert in it the contents of the other sets + m_movingWindows.clear(); + m_movingWindows.insert( rLayout.getWindow() ); + m_movingWindows.insert( m_resizeMovingE.begin(), m_resizeMovingE.end() ); + m_movingWindows.insert( m_resizeMovingS.begin(), m_resizeMovingS.end() ); + m_movingWindows.insert( m_resizeMovingSE.begin(), m_resizeMovingSE.end() ); +} + + +void WindowManager::stopResize() +{ + // Nothing different from stopMove(), luckily + stopMove(); +} + + +void WindowManager::resize( GenericLayout &rLayout, + int width, int height ) const +{ + // TODO: handle anchored windows + // Compute the real resizing offset + int xOffset = width - rLayout.getWidth(); + int yOffset = height - rLayout.getHeight(); + + // Check anchoring; this can change the values of xOffset and yOffset + checkAnchors( rLayout.getWindow(), xOffset, yOffset ); + if( m_direction == kResizeS ) + xOffset = 0; + if( m_direction == kResizeE ) + yOffset = 0; + + int newWidth = rLayout.getWidth() + xOffset; + int newHeight = rLayout.getHeight() + yOffset; + + // Check boundaries + if( newWidth < rLayout.getMinWidth() ) + { + newWidth = rLayout.getMinWidth(); + } + if( newWidth > rLayout.getMaxWidth() ) + { + newWidth = rLayout.getMaxWidth(); + } + if( newHeight < rLayout.getMinHeight() ) + { + newHeight = rLayout.getMinHeight(); + } + if( newHeight > rLayout.getMaxHeight() ) + { + newHeight = rLayout.getMaxHeight(); + } + + if( newWidth == rLayout.getWidth() && newHeight == rLayout.getHeight() ) + { + return; + } + + // New offset, after the last corrections + int xNewOffset = newWidth - rLayout.getWidth(); + int yNewOffset = newHeight - rLayout.getHeight(); + + // Do the actual resizing + rLayout.resize( newWidth, newHeight ); + + // Move all the anchored windows + WinSet_t::const_iterator it; + if( m_direction == kResizeE || + m_direction == kResizeSE ) + { + for( it = m_resizeMovingE.begin(); it != m_resizeMovingE.end(); ++it ) + { + (*it)->move( (*it)->getLeft() + xNewOffset, + (*it)->getTop() ); + } + } + if( m_direction == kResizeE || + m_direction == kResizeSE ) + { + for( it = m_resizeMovingS.begin(); it != m_resizeMovingS.end(); ++it ) + { + (*it)->move( (*it)->getLeft(), + (*it)->getTop( )+ yNewOffset ); + } + } + if( m_direction == kResizeE || + m_direction == kResizeS || + m_direction == kResizeSE ) + { + for( it = m_resizeMovingSE.begin(); it != m_resizeMovingSE.end(); ++it ) + { + (*it)->move( (*it)->getLeft() + xNewOffset, + (*it)->getTop() + yNewOffset ); + } + } +} + + +void WindowManager::maximize( TopWindow &rWindow ) +{ + // Save the current position/size of the window, to be able to restore it + m_maximizeRect = SkinsRect( rWindow.getLeft(), rWindow.getTop(), + rWindow.getLeft() + rWindow.getWidth(), + rWindow.getTop() + rWindow.getHeight() ); + + SkinsRect workArea = OSFactory::instance( getIntf() )->getWorkArea(); + // Move the window + startMove( rWindow ); + move( rWindow, workArea.getLeft(), workArea.getTop() ); + stopMove(); + // Now resize it + // FIXME: Ugly const_cast + GenericLayout &rLayout = (GenericLayout&)rWindow.getActiveLayout(); + startResize( rLayout, kResizeSE ); + resize( rLayout, workArea.getWidth(), workArea.getHeight() ); + stopResize(); + rWindow.m_pVarMaximized->set( true ); + + // Make the window unmovable by unregistering it +// unregisterWindow( rWindow ); +} + + +void WindowManager::unmaximize( TopWindow &rWindow ) +{ + // Register the window to allow moving it +// registerWindow( rWindow ); + + // Resize the window + // FIXME: Ugly const_cast + GenericLayout &rLayout = (GenericLayout&)rWindow.getActiveLayout(); + startResize( rLayout, kResizeSE ); + resize( rLayout, m_maximizeRect.getWidth(), m_maximizeRect.getHeight() ); + stopResize(); + // Now move it + startMove( rWindow ); + move( rWindow, m_maximizeRect.getLeft(), m_maximizeRect.getTop() ); + stopMove(); + rWindow.m_pVarMaximized->set( false ); +} + + void WindowManager::synchVisibility() const { WinSet_t::const_iterator it; - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) { // Show the window if it has to be visible if( (*it)->getVisibleVar().get() ) @@ -184,11 +365,42 @@ void WindowManager::synchVisibility() const } +void WindowManager::saveVisibility() +{ + WinSet_t::const_iterator it; + m_savedWindows.clear(); + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) + { + // Remember the window if it is visible + if( (*it)->getVisibleVar().get() ) + { + m_savedWindows.insert( *it ); + } + } +} + + +void WindowManager::restoreVisibility() const +{ + // Warning in case we never called saveVisibility() + if( m_savedWindows.size() == 0 ) + { + msg_Warn( getIntf(), "restoring visibility for no window" ); + } + + WinSet_t::const_iterator it; + for( it = m_savedWindows.begin(); it != m_savedWindows.end(); ++it ) + { + (*it)->show(); + } +} + + void WindowManager::raiseAll() const { // Raise all the windows WinSet_t::const_iterator it; - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) { (*it)->raise(); } @@ -199,44 +411,60 @@ void WindowManager::showAll( bool firstTime ) const { // Show all the windows WinSet_t::const_iterator it; - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) { // When the theme is opened for the first time, // only show the window if set as visible in the XML - if ((*it)->isVisible() || !firstTime) + if( (*it)->isVisible() || !firstTime ) { (*it)->show(); } - (*it)->setOpacity( m_alpha ); } } +void WindowManager::show( TopWindow &rWindow ) const +{ + rWindow.show(); + + if( isOpacityNeeded() ) + rWindow.setOpacity( m_alpha ); +} + + void WindowManager::hideAll() const { WinSet_t::const_iterator it; - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) { (*it)->hide(); } } -void WindowManager::toggleOnTop() +void WindowManager::setOnTop( bool b_ontop ) { // Update the boolean variable VarBoolImpl *pVarOnTop = (VarBoolImpl*)m_cVarOnTop.get(); - pVarOnTop->set( !pVarOnTop->get() ); + pVarOnTop->set( b_ontop ); - // Toggle the "on top" status + // set/unset the "on top" status WinSet_t::const_iterator it; - for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ ) + for( it = m_allWindows.begin(); it != m_allWindows.end(); ++it ) { - (*it)->toggleOnTop( pVarOnTop->get() ); + (*it)->toggleOnTop( b_ontop ); } } +void WindowManager::toggleOnTop() +{ + VarBoolImpl *pVarOnTop = (VarBoolImpl*)m_cVarOnTop.get(); + + setOnTop( !pVarOnTop->get() ); +} + + void WindowManager::buildDependSet( WinSet_t &rWinSet, TopWindow *pWindow ) { @@ -246,7 +474,7 @@ void WindowManager::buildDependSet( WinSet_t &rWinSet, // Iterate through the anchored windows const WinSet_t &anchored = m_dependencies[pWindow]; WinSet_t::const_iterator iter; - for( iter = anchored.begin(); iter != anchored.end(); iter++ ) + for( iter = anchored.begin(); iter != anchored.end(); ++iter ) { // Check that the window isn't already in the set before adding it if( rWinSet.find( *iter ) == rWinSet.end() ) @@ -264,10 +492,10 @@ void WindowManager::checkAnchors( TopWindow *pWindow, AncList_t::const_iterator itAncMov, itAncSta; // Check magnetism with screen edges first (actually it is the work area) - Rect workArea = OSFactory::instance( getIntf() )->getWorkArea(); + SkinsRect workArea = OSFactory::instance( getIntf() )->getWorkArea(); // Iterate through the moving windows for( itMov = m_movingWindows.begin(); - itMov != m_movingWindows.end(); itMov++ ) + itMov != m_movingWindows.end(); ++itMov ) { // Skip the invisible windows if( ! (*itMov)->getVisibleVar().get() ) @@ -287,23 +515,23 @@ void WindowManager::checkAnchors( TopWindow *pWindow, { yOffset = workArea.getTop() - (*itMov)->getTop(); } - if( newLeft + (*itMov)->getWidth() > workArea.getRight() - m_magnet && - newLeft + (*itMov)->getWidth() < workArea.getRight() + m_magnet ) + int right = workArea.getLeft() + workArea.getWidth(); + if( newLeft + (*itMov)->getWidth() > right - m_magnet && + newLeft + (*itMov)->getWidth() < right + m_magnet ) { - xOffset = workArea.getRight() - (*itMov)->getLeft() - - (*itMov)->getWidth(); + xOffset = right - (*itMov)->getLeft() - (*itMov)->getWidth(); } - if( newTop + (*itMov)->getHeight() > workArea.getBottom() - m_magnet && - newTop + (*itMov)->getHeight() < workArea.getBottom() + m_magnet ) + int bottom = workArea.getTop() + workArea.getHeight(); + if( newTop + (*itMov)->getHeight() > bottom - m_magnet && + newTop + (*itMov)->getHeight() < bottom + m_magnet ) { - yOffset = workArea.getBottom() - (*itMov)->getTop() - - (*itMov)->getHeight(); + yOffset = bottom - (*itMov)->getTop() - (*itMov)->getHeight(); } } // Iterate through the moving windows for( itMov = m_movingWindows.begin(); - itMov != m_movingWindows.end(); itMov++ ) + itMov != m_movingWindows.end(); ++itMov ) { // Skip the invisible windows if( ! (*itMov)->getVisibleVar().get() ) @@ -317,7 +545,7 @@ void WindowManager::checkAnchors( TopWindow *pWindow, // Iterate through the static windows for( itSta = m_allWindows.begin(); - itSta != m_allWindows.end(); itSta++ ) + itSta != m_allWindows.end(); ++itSta ) { // Skip the moving windows and the invisible ones if( m_movingWindows.find( (*itSta) ) != m_movingWindows.end() || @@ -333,10 +561,10 @@ void WindowManager::checkAnchors( TopWindow *pWindow, // Check if there is an anchoring between one of the movAnchors // and one of the staAnchors for( itAncMov = movAnchors.begin(); - itAncMov != movAnchors.end(); itAncMov++ ) + itAncMov != movAnchors.end(); ++itAncMov ) { for( itAncSta = staAnchors.begin(); - itAncSta != staAnchors.end(); itAncSta++ ) + itAncSta != staAnchors.end(); ++itAncSta ) { if( (*itAncSta)->canHang( **itAncMov, xOffset, yOffset ) ) { @@ -381,7 +609,7 @@ void WindowManager::createTooltip( const GenericFont &rTipFont ) } else { - msg_Warn( getIntf(), "Tooltip already created!"); + msg_Warn( getIntf(), "tooltip already created!" ); } } @@ -417,3 +645,4 @@ void WindowManager::setActiveLayout( TopWindow &rWindow, // Rebuild the dependencies stopMove(); } +