From d7197187805fe5ef3634135bd7c2328821376615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 4 Aug 2008 14:23:22 +0000 Subject: [PATCH] Twin view support for cube. Cube is painted on one screen and scaled so that both screens fit on it. Projection matrix has unfortunatelly to be changed in twin view mode. svn path=/trunk/KDE/kdebase/workspace/; revision=842026 --- effects/cube.cpp | 166 +++++++++++++++++++++++++++++++++++++++-------- effects/cube.h | 3 +- 2 files changed, 140 insertions(+), 29 deletions(-) diff --git a/effects/cube.cpp b/effects/cube.cpp index c3f73b34a3..99c49e9389 100644 --- a/effects/cube.cpp +++ b/effects/cube.cpp @@ -69,6 +69,7 @@ CubeEffect::CubeEffect() , reflectionPainting( false ) , slide( false ) , oldDesktop( 0 ) + , activeScreen( 0 ) { KConfigGroup conf = effects->effectConfig( "Cube" ); borderActivate = (ElectricBorder)conf.readEntry( "BorderActivate", (int)ElectricNone ); @@ -155,7 +156,8 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) if( activated ) { //kDebug(); - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop()); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); // background float clearColor[4]; @@ -165,7 +167,7 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] ); // wallpaper - if( wallpaper ) + if( wallpaper && !slide ) { wallpaper->bind(); wallpaper->render( region, rect ); @@ -176,11 +178,66 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + if( effects->numScreens() > 1 ) + { + windowsOnOtherScreens.clear(); + // unfortunatelly we have to change the projection matrix in dual screen mode + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + float fovy = 60.0f; + float aspect = 1.0f; + float zNear = 0.1f; + float zFar = 100.0f; + float ymax = zNear * tan( fovy * M_PI / 360.0f ); + float ymin = -ymax; + float xmin = ymin * aspect; + float xmax = ymax * aspect; + float xTranslate = 0.0; + float yTranslate = 0.0; + bool projectionSet = false; + if( rect.x() == 0 && rect.width() != fullRect.width() ) + { + // horizontal layout: left screen + glFrustum( xmin*0.5, xmax*1.5, ymin, ymax, zNear, zFar ); + xTranslate = rect.width()*0.5; + projectionSet = true; + } + if( rect.x() != 0 && rect.width() != fullRect.width() ) + { + // horizontal layout: right screen + glFrustum( xmin*1.5, xmax*0.5, ymin, ymax, zNear, zFar ); + xTranslate = rect.width()*0.5; + projectionSet = true; + } + if( rect.y() == 0 && rect.height() != fullRect.height() ) + { + glFrustum( xmin, xmax, ymin*1.5, ymax*0.5, zNear, zFar ); + yTranslate = rect.height()*0.5; + projectionSet = true; + } + if( rect.y() != 0 && rect.height() != fullRect.height() ) + { + glFrustum( xmin, xmax, ymin*0.5, ymax*1.5, zNear, zFar ); + yTranslate = rect.height()*0.5; + projectionSet = true; + } + if( !projectionSet ) + { + // this should never happen; nevertheless reset the projection to the default + glPopMatrix(); + glPushMatrix(); + } + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glTranslatef( xTranslate, yTranslate, 0.0 ); + } + // reflection if( reflection && (!slide) ) { glPushMatrix(); - float scaleFactor = 6100 * tan( 60.0 * M_PI / 360.0f )/rect.height(); + float scaleFactor = 10000 * tan( 60.0 * M_PI / 360.0f )/rect.height(); glScalef( 1.0, -1.0, 1.0 ); glTranslatef( 0.0, -rect.height()*2, 0.0 ); @@ -193,11 +250,16 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) glPopMatrix(); glPushMatrix(); glTranslatef( 0.0, rect.height(), 0.0 ); + if( effects->numScreens() > 1 && rect.width() != fullRect.width() ) + { + // have to change the reflection area in horizontal layout and right screen + glTranslatef( -rect.width(), 0.0, 0.0 ); + } float vertices[] = { - 0.0, 0.0, 0.0, - rect.width(), 0.0, 0.0, - rect.width()*scaleFactor, 0.0, -5000, - -rect.width()*scaleFactor, 0.0, -5000 }; + rect.x(), 0.0, 0.0, + rect.x()+rect.width(), 0.0, 0.0, + (rect.x()+rect.width())*scaleFactor, 0.0, -5000, + (-rect.x()-rect.width())*scaleFactor, 0.0, -5000 }; // foreground float alpha = 0.7; if( start ) @@ -220,6 +282,15 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) paintScene( mask, region, data ); glPopMatrix(); + if( effects->numScreens() > 1 ) + { + glPopMatrix(); + // revert change of projection matrix + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + } + glDisable( GL_BLEND ); glPopAttrib(); @@ -262,6 +333,18 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) { effects->paintScreen( mask, region, data ); } + if( effects->numScreens() > 1 ) + { + foreach( EffectWindow* w, windowsOnOtherScreens ) + { + WindowPaintData wData( w ); + if( start && !w->isDesktop() && !w->isDock() ) + wData.opacity *= (1.0 - timeLine.value()); + if( stop && !w->isDesktop() && !w->isDock() ) + wData.opacity *= timeLine.value(); + effects->paintWindow( w, 0, QRegion( w->x(), w->y(), w->width(), w->height() ), wData ); + } + } } else { @@ -271,7 +354,35 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) void CubeEffect::paintScene( int mask, QRegion region, ScreenPaintData& data ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop()); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + float xScale = 1.0; + float yScale = 1.0; + if( effects->numScreens() > 1 ) + { + QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + xScale = (float)rect.width()/(float)fullRect.width(); + yScale = (float)rect.height()/(float)fullRect.height(); + if( start ) + { + xScale = xScale + (1.0 - xScale) * (1.0 - timeLine.value()); + yScale = yScale + (1.0 - yScale) * (1.0 - timeLine.value()); + if( rect.x() > 0 ) + glTranslatef( -rect.x()*(1.0 - timeLine.value()), 0.0, 0.0 ); + if( rect.y() > 0 ) + glTranslatef( 0.0, -rect.y()*(1.0 - timeLine.value()), 0.0 ); + } + if( stop ) + { + xScale = xScale + (1.0 - xScale) * timeLine.value(); + yScale = yScale + (1.0 - yScale) * timeLine.value(); + if( rect.x() > 0 ) + glTranslatef( -rect.x()*timeLine.value(), 0.0, 0.0 ); + if( rect.y() > 0 ) + glTranslatef( 0.0, -rect.y()*timeLine.value(), 0.0 ); + } + glScalef( xScale, yScale, 1.0 ); + rect = fullRect; + } int rightSteps = effects->numberOfDesktops()/2; int leftSteps = rightSteps+1; int rightSideCounter = 0; @@ -576,7 +687,7 @@ void CubeEffect::paintScene( int mask, QRegion region, ScreenPaintData& data ) void CubeEffect::paintCap( float z, float zTexture ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop()); + QRect rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop()); if( ( !paintCaps ) || effects->numberOfDesktops() <= 2 ) return; float opacity = cubeOpacity; @@ -795,9 +906,18 @@ void CubeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int //kDebug(); if( cube_painting ) { + if( ( w->isDesktop() || w->isDock() ) && w->screen() != activeScreen && w->isOnDesktop( effects->currentDesktop() ) ) + { + windowsOnOtherScreens.append( w ); + } + if( (start || stop) && w->screen() != activeScreen && w->isOnDesktop( effects->currentDesktop() ) + && !w->isDesktop() && !w->isDock() ) + { + windowsOnOtherScreens.append( w ); + } if( w->isOnDesktop( painting_desktop )) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), painting_desktop ); + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); if( w->x() < rect.x() ) { data.quads = data.quads.splitAtX( -w->x() ); @@ -824,7 +944,7 @@ void CubeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int prev_desktop = effects->numberOfDesktops(); if( w->isOnDesktop( prev_desktop ) ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), prev_desktop); + QRect rect = effects->clientArea( FullArea, activeScreen, prev_desktop); if( w->x()+w->width() > rect.x() + rect.width() ) { w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); @@ -848,7 +968,7 @@ void CubeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int next_desktop = 1; if( w->isOnDesktop( next_desktop ) ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), next_desktop); + QRect rect = effects->clientArea( FullArea, activeScreen, next_desktop); if( w->x() < rect.x() ) { w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); @@ -919,7 +1039,7 @@ void CubeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowP next_desktop = 1; if( w->isOnDesktop( prev_desktop ) && ( mask & PAINT_WINDOW_TRANSFORMED ) ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), prev_desktop); + QRect rect = effects->clientArea( FullArea, activeScreen, prev_desktop); data.xTranslate = -rect.width(); WindowQuadList new_quads; foreach( WindowQuad quad, data.quads ) @@ -933,7 +1053,7 @@ void CubeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowP } if( w->isOnDesktop( next_desktop ) && ( mask & PAINT_WINDOW_TRANSFORMED ) ) { - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), next_desktop); + QRect rect = effects->clientArea( FullArea, activeScreen, next_desktop); data.xTranslate = rect.width(); WindowQuadList new_quads; foreach( WindowQuad quad, data.quads ) @@ -945,7 +1065,7 @@ void CubeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowP } data.quads = new_quads; } - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), painting_desktop ); + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); if( start || stop ) { @@ -1020,17 +1140,6 @@ void CubeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowP effects->paintWindow( w, mask, region, data ); } -void CubeEffect::postPaintWindow( EffectWindow* w ) - { - if( activated && !cube_painting ) - { - // a window was updated which has not been handled by cube_painting. - // trigger full repaint, so that this window will be updated - //effects->addRepaintFull(); - } - effects->postPaintWindow( w ); - } - bool CubeEffect::borderActivated( ElectricBorder border ) { if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) @@ -1246,6 +1355,7 @@ void CubeEffect::setActive( bool active ) if( active ) { activated = true; + activeScreen = effects->activeScreen(); if( !slide ) { keyboard_grab = effects->grabKeyboard( this ); @@ -1265,7 +1375,7 @@ void CubeEffect::setActive( bool active ) // clip parts above the reflection area double eqn[4] = {0.0, 1.0, 0.0, 0.0}; glPushMatrix(); - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop()); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); glTranslatef( 0.0, rect.height(), 0.0 ); glClipPlane( GL_CLIP_PLANE0, eqn ); glPopMatrix(); @@ -1287,7 +1397,7 @@ void CubeEffect::mouseChanged( const QPoint& pos, const QPoint& oldpos, Qt::Mous return; if( stop || slide ) return; - QRect rect = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop()); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); if( buttons.testFlag( Qt::LeftButton ) ) { bool repaint = false; diff --git a/effects/cube.h b/effects/cube.h index 1f3a987482..42ccb7b931 100644 --- a/effects/cube.h +++ b/effects/cube.h @@ -41,7 +41,6 @@ class CubeEffect virtual void postPaintScreen(); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); - virtual void postPaintWindow( EffectWindow* w); virtual bool borderActivated( ElectricBorder border ); virtual void grabbedKeyboardEvent( QKeyEvent* e ); virtual void mouseChanged( const QPoint& pos, const QPoint& oldpos, Qt::MouseButtons buttons, @@ -103,6 +102,8 @@ class CubeEffect bool slide; int oldDesktop; int rotationDuration; + QList windowsOnOtherScreens; + int activeScreen; }; } // namespace