diff --git a/effects/boxswitch/boxswitch.cpp b/effects/boxswitch/boxswitch.cpp index e0ead1e905..1c46385db5 100644 --- a/effects/boxswitch/boxswitch.cpp +++ b/effects/boxswitch/boxswitch.cpp @@ -41,14 +41,14 @@ KWIN_EFFECT( boxswitch, BoxSwitchEffect ) BoxSwitchEffect::BoxSwitchEffect() : mActivated( 0 ) , mMode( 0 ) + , thumbnailFrame( true ) , selected_window( 0 ) , painting_desktop( 0 ) , animation( false ) , highlight_is_set( false ) { - frame_margin = 10; - highlight_margin = 5; + highlight_margin = 10; reconfigure( ReconfigureAll ); } @@ -62,7 +62,6 @@ void BoxSwitchEffect::reconfigure( ReconfigureFlags ) color_frame.setAlphaF( 0.9 ); color_highlight = KColorScheme( QPalette::Active, KColorScheme::Selection ).background().color(); color_highlight.setAlphaF( 0.9 ); - color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color(); activeTimeLine.setDuration( animationTime( 250 )); activeTimeLine.setCurveShape( TimeLine::EaseInOutCurve ); timeLine.setDuration( animationTime( 150 )); @@ -122,19 +121,19 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da { if( mMode == TabBoxWindowsMode ) { - paintFrame(); + thumbnailFrame.render( region ); if( mAnimateSwitch ) { // HACK: PaintClipper is used because window split is somehow wrong if the height is greater than width - PaintClipper::push( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin )); + PaintClipper::push( frame_area ); paintHighlight( highlight_area ); foreach( EffectWindow* w, windows.keys()) { paintWindowThumbnail( w ); paintWindowIcon( w ); } - PaintClipper::pop( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin ) ); + PaintClipper::pop( frame_area ); } else { @@ -154,7 +153,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da { if( !painting_desktop ) { - paintFrame(); + thumbnailFrame.render( region ); foreach( painting_desktop, desktops.keys()) { @@ -236,8 +235,7 @@ void BoxSwitchEffect::windowInputMouseEvent( Window w, QEvent* e ) // special handling for second half of window in case of animation and even number of windows if( mAnimateSwitch && ( windows.size() % 2 == 0 ) ) { - QRect additionalRect = QRect( frame_area.x() + frame_margin, - frame_area.y() + frame_margin, + QRect additionalRect = QRect( frame_area.x(), frame_area.y(), item_max_size.width()*0.5, item_max_size.height()); if( additionalRect.contains( pos )) { @@ -481,6 +479,7 @@ void BoxSwitchEffect::setInactive() qDeleteAll( windows ); desktops.clear(); } + thumbnailFrame.free(); effects->addRepaint( frame_area ); frame_area = QRect(); } @@ -535,21 +534,23 @@ void BoxSwitchEffect::calculateFrameSize() // Separator space between items and text const int separator_height = 6; // Shrink the size until all windows/desktops can fit onscreen - frame_area.setWidth( frame_margin * 2 + itemcount * item_max_size.width()); + frame_area.setWidth( itemcount * item_max_size.width()); QRect screenr = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop()); while( frame_area.width() > screenr.width()) { item_max_size /= 2; - frame_area.setWidth( frame_margin * 2 + itemcount * item_max_size.width()); + frame_area.setWidth( itemcount * item_max_size.width()); } - frame_area.setHeight( frame_margin * 2 + item_max_size.height() + + frame_area.setHeight( item_max_size.height() + separator_height + text_area.height()); - text_area.setWidth( frame_area.width() - frame_margin * 2 ); + text_area.setWidth( frame_area.width() ); frame_area.moveTo( screenr.x() + ( screenr.width() - frame_area.width()) / 2, screenr.y() + ( screenr.height() - frame_area.height()) / 2 ); - text_area.moveTo( frame_area.x() + frame_margin, - frame_area.y() + frame_margin + item_max_size.height() + separator_height); + text_area.moveTo( frame_area.x(), + frame_area.y() + item_max_size.height() + separator_height); + + thumbnailFrame.setGeometry( frame_area ); } void BoxSwitchEffect::calculateItemSizes() @@ -642,9 +643,8 @@ void BoxSwitchEffect::calculateItemSizes() } if( ordered_windows.count()%2 == 0 ) moveIndex += 0.5; - windows[ w ]->area = QRect( frame_area.x() + frame_margin - + moveIndex * item_max_size.width() + offset, - frame_area.y() + frame_margin, + windows[ w ]->area = QRect( frame_area.x() + moveIndex * item_max_size.width() + offset, + frame_area.y(), item_max_size.width(), item_max_size.height()); windows[ w ]->clickable = windows[ w ]->area; } @@ -665,9 +665,8 @@ void BoxSwitchEffect::calculateItemSizes() EffectWindow* w = original_windows.at( i ); windows[ w ] = new ItemInfo(); - windows[ w ]->area = QRect( frame_area.x() + frame_margin - + i * item_max_size.width(), - frame_area.y() + frame_margin, + windows[ w ]->area = QRect( frame_area.x() + i * item_max_size.width(), + frame_area.y(), item_max_size.width(), item_max_size.height()); windows[ w ]->clickable = windows[ w ]->area; } @@ -681,47 +680,14 @@ void BoxSwitchEffect::calculateItemSizes() int it = original_desktops.at( i ); desktops[ it ] = new ItemInfo(); - desktops[ it ]->area = QRect( frame_area.x() + frame_margin - + i * item_max_size.width(), - frame_area.y() + frame_margin, + desktops[ it ]->area = QRect( frame_area.x() + i * item_max_size.width(), + frame_area.y(), item_max_size.width(), item_max_size.height()); desktops[ it ]->clickable = desktops[ it ]->area; } } } -void BoxSwitchEffect::paintFrame() - { -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - if( effects->compositingType() == OpenGLCompositing ) - { - glPushAttrib( GL_CURRENT_BIT ); - glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF()); - renderRoundBoxWithEdge( frame_area ); - glPopAttrib(); - } -#endif -#ifdef KWIN_HAVE_XRENDER_COMPOSITING - if( effects->compositingType() == XRenderCompositing ) - { - Pixmap pixmap = XCreatePixmap( display(), rootWindow(), - frame_area.width(), frame_area.height(), 32 ); - XRenderPicture pic( pixmap, 32 ); - XFreePixmap( display(), pixmap ); - XRenderColor col; - col.alpha = int( color_frame.alphaF() * 0xffff ); - col.red = int( color_frame.redF() * color_frame.alphaF() * 0xffff ); - col.green = int( color_frame.greenF() * color_frame.alphaF() * 0xffff ); - col.blue = int( color_frame.blueF() * color_frame.alphaF() * 0xffff ); - XRenderFillRectangle( display(), PictOpSrc, pic, &col, 0, 0, - frame_area.width(), frame_area.height()); - XRenderComposite( display(), color_frame.alphaF() != 1.0 ? PictOpOver : PictOpSrc, - pic, None, effects->xrenderBufferPicture(), - 0, 0, 0, 0, frame_area.x(), frame_area.y(), frame_area.width(), frame_area.height()); - } -#endif - } - void BoxSwitchEffect::paintHighlight( QRect area ) { #ifdef KWIN_HAVE_OPENGL_COMPOSITING @@ -818,19 +784,19 @@ void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) if( timeLine.value() < 0.5 ) { data.quads = right_quads; - secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin - - (float)item_max_size.width()*timeLine.value(), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() + frame_area.width() - + (float)item_max_size.width()*timeLine.value(), + frame_area.y(), item_max_size.width(), item_max_size.height()); } else { data.quads = left_quads; - secondThumbnail = QRect( frame_area.x() + frame_margin - (float)item_max_size.width()*timeLine.value(), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*timeLine.value(), + frame_area.y(), item_max_size.width(), item_max_size.height()); if( right_window ) - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*(timeLine.value()-0.5), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); } } else @@ -838,16 +804,16 @@ void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) if( timeLine.value() < 0.5 ) { data.quads = left_quads; - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*(1.0 - timeLine.value()), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); } else { data.quads = right_quads; - secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin - - (float)item_max_size.width()*(1.0 - timeLine.value()), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() + frame_area.width() - + (float)item_max_size.width()*(1.0 - timeLine.value()), + frame_area.y(), item_max_size.width(), item_max_size.height()); } } setPositionTransformations( data, @@ -913,9 +879,9 @@ void BoxSwitchEffect::paintWindowThumbnail( EffectWindow* w ) // right quads are painted on left side of frame data.quads = rightQuads; QRect secondThumbnail; - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*0.5 + animationOffset, - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); setPositionTransformations( data, windows[ w ]->thumbnail, w, secondThumbnail.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ), @@ -1011,7 +977,7 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) if( direction == Left ) { x -= windows[ w ]->area.width()*timeLine.value(); - x = qMax( x, frame_area.x() + frame_margin ); + x = qMax( x, frame_area.x() ); } else x += windows[ w ]->area.width()*timeLine.value(); @@ -1023,7 +989,7 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) else { x -= windows[ w ]->area.width()*(1.0-timeLine.value()); - x = qMax( x, frame_area.x() + frame_margin ); + x = qMax( x, frame_area.x() ); } } } @@ -1090,7 +1056,7 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w ) void BoxSwitchEffect::paintText( const QString& text ) { int maxwidth = text_area.width(); - effects->paintText( text, text_area.center(), maxwidth, color_text, text_font ); + effects->paintText( text, text_area.center(), maxwidth, EffectFrame::textColor(), text_font ); } } // namespace diff --git a/effects/boxswitch/boxswitch.h b/effects/boxswitch/boxswitch.h index 667a482c1a..b479fc17fe 100644 --- a/effects/boxswitch/boxswitch.h +++ b/effects/boxswitch/boxswitch.h @@ -66,7 +66,6 @@ class BoxSwitchEffect void calculateItemSizes(); void setSelectedWindow( EffectWindow* w ); - void paintFrame(); void paintHighlight( QRect area ); void paintWindowThumbnail( EffectWindow* w ); void paintDesktopThumbnail( int iDesktop ); @@ -77,15 +76,15 @@ class BoxSwitchEffect Window mInput; int mMode; + EffectFrame thumbnailFrame; + QRect frame_area; - int frame_margin; // TODO graphical background - int highlight_margin; // TODO graphical background + int highlight_margin; QSize item_max_size; // maximum item display size (including highlight) QRect text_area; QFont text_font; QColor color_frame; QColor color_highlight; - QColor color_text; float bg_opacity; bool elevate_window; diff --git a/effects/coverswitch/coverswitch.cpp b/effects/coverswitch/coverswitch.cpp index de232cc4a5..bf59158538 100644 --- a/effects/coverswitch/coverswitch.cpp +++ b/effects/coverswitch/coverswitch.cpp @@ -52,8 +52,15 @@ CoverSwitchEffect::CoverSwitchEffect() , scaleFactor( 0.0 ) , direction( Left ) , selected_window( 0 ) + , captionFrame( true ) + , thumbnailFrame( true ) { reconfigure( ReconfigureAll ); + + // Caption frame + captionFont.setBold( true ); + captionFont.setPointSize( captionFont.pointSize() * 2 ); + captionFrame.setFont( captionFont ); } CoverSwitchEffect::~CoverSwitchEffect() @@ -85,8 +92,7 @@ void CoverSwitchEffect::reconfigure( ReconfigureFlags ) color_frame.setAlphaF( 0.9 ); color_highlight = KColorScheme( QPalette::Active, KColorScheme::Selection ).background().color(); color_highlight.setAlphaF( 0.9 ); - frame_margin = 10; - highlight_margin = 5; + highlight_margin = 10; } void CoverSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time ) @@ -308,82 +314,40 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& glMatrixMode( GL_MODELVIEW ); } - // caption of selected window - QColor color_frame; - QColor color_text; - color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color(); - color_frame.setAlphaF( 0.9 ); - color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color(); + // Render the caption frame + double opacity = 1.0; if( start ) - { - color_frame.setAlphaF( 0.9 * timeLine.value() ); - color_text.setAlphaF( timeLine.value() ); - } + opacity = timeLine.value(); else if( stop ) - { - color_frame.setAlphaF( 0.9 - 0.9 * timeLine.value() ); - color_text.setAlphaF( 1.0 - timeLine.value() ); - } - QFont text_font; - text_font.setBold( true ); - text_font.setPointSize( 20 ); - glPushAttrib( GL_CURRENT_BIT ); - glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF()); - QRect frameRect = QRect( area.width()*0.25f + area.x(), - area.height()*0.9f + area.y(), - area.width()*0.5f, - QFontMetrics( text_font ).height() * 1.2f ); - renderRoundBoxWithEdge( frameRect ); - effects->paintText( effects->currentTabBoxWindow()->caption(), - frameRect.center(), - frameRect.width() - 100, - color_text, - text_font ); - glPopAttrib(); - // icon of selected window + opacity = 1.0 - timeLine.value(); QPixmap iconPixmap = effects->currentTabBoxWindow()->icon(); if( start || stop ) { int alpha = 255.0f * timeLine.value(); if( stop ) - { alpha = 255.0f - alpha; - } QPixmap transparency = iconPixmap.copy( iconPixmap.rect() ); - transparency.fill( QColor( 255, 255, 255, alpha ) ); - iconPixmap.setAlphaChannel( transparency.alphaChannel() ); + transparency.fill( QColor( 255, 255, 255, alpha )); + iconPixmap.setAlphaChannel( transparency.alphaChannel() ); } - GLTexture* icon = new GLTexture( iconPixmap ); - icon->bind(); - glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); - icon->bind(); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - // icon takes 80 % of the height of the frame. So each 10 % space left on the top and bottom - QRect iconRect = QRect( frameRect.x() + frameRect.height()*0.1f, - frameRect.y() + frameRect.height()*0.1f, - frameRect.height()*0.8f, - frameRect.height()*0.8f ); - icon->render( region, iconRect); - icon->unbind(); - delete icon; - glDisable( GL_BLEND ); - glPopAttrib(); + captionFrame.setText( effects->currentTabBoxWindow()->caption() ); + captionFrame.setIcon( iconPixmap ); + captionFrame.render( region, opacity ); if( ( thumbnails && (!dynamicThumbnails || (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) ) && !( start || stop ) ) { - paintFrame(); + thumbnailFrame.render( region ); // HACK: PaintClipper is used because window split is somehow wrong if the height is greater than width - PaintClipper::push( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin )); + PaintClipper::push( frame_area ); paintHighlight( highlight_area ); foreach( EffectWindow* w, windows.keys()) { paintWindowThumbnail( w ); paintWindowIcon( w ); } - PaintClipper::pop( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin ) ); + PaintClipper::pop( frame_area ); } } } @@ -580,6 +544,14 @@ void CoverSwitchEffect::tabBoxAdded( int mode ) } } + // Setup caption frame geometry + QRect frameRect = QRect( area.width() * 0.25f + area.x(), + area.height() * 0.9f + area.y(), + area.width() * 0.5f, + QFontMetrics( captionFont ).height() ); + captionFrame.setGeometry( frameRect ); + captionFrame.setIconSize( QSize( frameRect.height(), frameRect.height() )); + effects->addRepaintFull(); } else @@ -982,16 +954,18 @@ void CoverSwitchEffect::calculateFrameSize() QRect screenr = effects->clientArea( PlacementArea, activeScreen, effects->currentDesktop()); itemcount = effects->currentTabBoxWindowList().count(); - item_max_size.setWidth( (screenr.width()*0.95f - frame_margin * 2)/itemcount ); + item_max_size.setWidth( (screenr.width()*0.95f * 2)/itemcount ); if( item_max_size.width() > 250 ) item_max_size.setWidth( 250 ); item_max_size.setHeight( item_max_size.width() * ((float)screenr.height()/(float)screenr.width()) ); // Shrink the size until all windows/desktops can fit onscreen - frame_area.setWidth( frame_margin * 2 + itemcount * item_max_size.width()); - frame_area.setHeight( frame_margin * 2 + item_max_size.height() ); + frame_area.setWidth( itemcount * item_max_size.width()); + frame_area.setHeight( item_max_size.height() ); frame_area.moveTo( screenr.x() + ( screenr.width() - frame_area.width()) / 2, screenr.y() + screenr.height()*0.05f ); + + thumbnailFrame.setGeometry( frame_area ); } void CoverSwitchEffect::calculateItemSizes() @@ -1081,9 +1055,8 @@ void CoverSwitchEffect::calculateItemSizes() } if( ordered_windows.count()%2 == 0 ) moveIndex += 0.5; - windows[ w ]->area = QRect( frame_area.x() + frame_margin - + moveIndex * item_max_size.width() + offset, - frame_area.y() + frame_margin, + windows[ w ]->area = QRect( frame_area.x() + moveIndex * item_max_size.width() + offset, + frame_area.y(), item_max_size.width(), item_max_size.height()); windows[ w ]->clickable = windows[ w ]->area; } @@ -1098,14 +1071,6 @@ void CoverSwitchEffect::calculateItemSizes() } } -void CoverSwitchEffect::paintFrame() - { - glPushAttrib( GL_CURRENT_BIT ); - glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF()); - renderRoundBoxWithEdge( frame_area ); - glPopAttrib(); - } - void CoverSwitchEffect::paintHighlight( QRect area ) { glPushAttrib( GL_CURRENT_BIT ); @@ -1178,19 +1143,19 @@ void CoverSwitchEffect::paintWindowThumbnail( EffectWindow* w ) if( timeLine.value() < 0.5 ) { data.quads = right_quads; - secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin - - (float)item_max_size.width()*timeLine.value(), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() + frame_area.width() - + (float)item_max_size.width()*timeLine.value(), + frame_area.y(), item_max_size.width(), item_max_size.height()); } else { data.quads = left_quads; - secondThumbnail = QRect( frame_area.x() + frame_margin - (float)item_max_size.width()*timeLine.value(), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*timeLine.value(), + frame_area.y(), item_max_size.width(), item_max_size.height()); if( right_window ) - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*(timeLine.value()-0.5), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); } } else @@ -1198,16 +1163,16 @@ void CoverSwitchEffect::paintWindowThumbnail( EffectWindow* w ) if( timeLine.value() < 0.5 ) { data.quads = left_quads; - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*(1.0 - timeLine.value()), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); } else { data.quads = right_quads; - secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin - - (float)item_max_size.width()*(1.0 - timeLine.value()), - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + secondThumbnail = QRect( frame_area.x() + frame_area.width() - + (float)item_max_size.width()*(1.0 - timeLine.value()), + frame_area.y(), item_max_size.width(), item_max_size.height()); } } setPositionTransformations( data, @@ -1273,9 +1238,9 @@ void CoverSwitchEffect::paintWindowThumbnail( EffectWindow* w ) // right quads are painted on left side of frame data.quads = rightQuads; QRect secondThumbnail; - secondThumbnail = QRect( frame_area.x() + frame_margin - + secondThumbnail = QRect( frame_area.x() - (float)item_max_size.width()*0.5 + animationOffset, - frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height()); + frame_area.y(), item_max_size.width(), item_max_size.height()); setPositionTransformations( data, windows[ w ]->thumbnail, w, secondThumbnail.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ), @@ -1336,7 +1301,7 @@ void CoverSwitchEffect::paintWindowIcon( EffectWindow* w ) if( direction == Left ) { x -= windows[ w ]->area.width()*timeLine.value(); - x = qMax( x, frame_area.x() + frame_margin ); + x = qMax( x, frame_area.x() ); } else x += windows[ w ]->area.width()*timeLine.value(); @@ -1348,7 +1313,7 @@ void CoverSwitchEffect::paintWindowIcon( EffectWindow* w ) else { x -= windows[ w ]->area.width()*(1.0-timeLine.value()); - x = qMax( x, frame_area.x() + frame_margin ); + x = qMax( x, frame_area.x() ); } } } @@ -1423,8 +1388,7 @@ void CoverSwitchEffect::windowInputMouseEvent( Window w, QEvent* e ) // special handling for second half of window in case of animation and even number of windows if( windows.size() % 2 == 0 ) { - QRect additionalRect = QRect( frame_area.x() + frame_margin, - frame_area.y() + frame_margin, + QRect additionalRect = QRect( frame_area.x(), frame_area.y(), item_max_size.width()*0.5, item_max_size.height()); if( additionalRect.contains( pos )) { @@ -1493,6 +1457,8 @@ void CoverSwitchEffect::abort() qDeleteAll( windows ); windows.clear(); } + captionFrame.free(); + thumbnailFrame.free(); } diff --git a/effects/coverswitch/coverswitch.h b/effects/coverswitch/coverswitch.h index 3014ed386f..ac49df9454 100644 --- a/effects/coverswitch/coverswitch.h +++ b/effects/coverswitch/coverswitch.h @@ -97,7 +97,11 @@ class CoverSwitchEffect QList< EffectWindow* > leftWindows; QList< EffectWindow* > rightWindows; + EffectFrame captionFrame; + QFont captionFont; + // thumbnail bar + EffectFrame thumbnailFrame; bool thumbnails; bool dynamicThumbnails; int thumbnailWindows; diff --git a/effects/cube/cube.cpp b/effects/cube/cube.cpp index 505398216d..0142d06e3c 100644 --- a/effects/cube/cube.cpp +++ b/effects/cube/cube.cpp @@ -57,6 +57,7 @@ CubeEffect::CubeEffect() , cubeOpacity( 1.0 ) , opacityDesktopOnly( true ) , displayDesktopName( false ) + , desktopNameFrame( true ) , reflection( true ) , rotating( false ) , desktopChangedWhileRotating( false ) @@ -91,6 +92,10 @@ CubeEffect::CubeEffect() , recompileList( true ) , glList( 0 ) { + desktopNameFont.setBold( true ); + desktopNameFont.setPointSize( 14 ); + desktopNameFrame.setFont( desktopNameFont ); + reconfigure( ReconfigureAll ); } @@ -610,37 +615,16 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) // desktop name box - inspired from coverswitch if( displayDesktopName ) { - QColor color_frame; - QColor color_text; - color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color(); - color_frame.setAlphaF( 0.5 ); - color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color(); + double opacity = 1.0; if( start ) - { - color_frame.setAlphaF( 0.5 * timeLine.value() ); - color_text.setAlphaF( timeLine.value() ); - } + opacity = timeLine.value(); if( stop ) - { - color_frame.setAlphaF( 0.5 - 0.5 * timeLine.value() ); - color_text.setAlphaF( 1.0 - timeLine.value() ); - } - QFont text_font; - text_font.setBold( true ); - text_font.setPointSize( 14 ); - glPushAttrib( GL_CURRENT_BIT ); - glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF()); - QRect frameRect = QRect( rect.width()*0.33f + rect.x(), - rect.height() + rect.y() - QFontMetrics( text_font ).height() * 1.2f, - rect.width()*0.33f, - QFontMetrics( text_font ).height() * 1.2f ); - renderRoundBoxWithEdge( frameRect ); - effects->paintText( effects->desktopName( frontDesktop ), - frameRect.center(), - frameRect.width(), - color_text, - text_font ); - glPopAttrib(); + opacity = 1.0 - timeLine.value(); + QRect frameRect = QRect( rect.width() * 0.33f + rect.x(), rect.height() * 0.95f + rect.y(), + rect.width() * 0.34f, QFontMetrics( desktopNameFont ).height() ); + desktopNameFrame.setGeometry( frameRect ); + desktopNameFrame.setText( effects->desktopName( frontDesktop ) ); + desktopNameFrame.render( region, opacity ); } if( effects->numScreens() > 1 && !bigCube ) { @@ -1982,6 +1966,7 @@ void CubeEffect::setActive( bool active ) mousePolling = false; } schedule_close = true; + desktopNameFrame.free(); // we have to add a repaint, to start the deactivating effects->addRepaintFull(); } diff --git a/effects/cube/cube.h b/effects/cube/cube.h index e8da508f9b..0056506462 100644 --- a/effects/cube/cube.h +++ b/effects/cube/cube.h @@ -102,6 +102,8 @@ class CubeEffect float cubeOpacity; bool opacityDesktopOnly; bool displayDesktopName; + EffectFrame desktopNameFrame; + QFont desktopNameFont; bool reflection; bool rotating; bool verticalRotating; diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index b7d0d7988b..88bc36ef6d 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -44,24 +44,20 @@ PresentWindowsEffect::PresentWindowsEffect() : m_proxy( this ) , m_borderActivate( ElectricNone ) , m_borderActivateAll( ElectricNone ) - , m_activated( false ) - , m_allDesktops( false ) - , m_ignoreMinimized( false ) - , m_decalOpacity( 0.0 ) - //, m_input() - , m_hasKeyboardGrab( false ) - , m_tabBoxEnabled( false ) - //, m_motionManager() - //, m_windowData() - , m_highlightedWindow( NULL ) - //, m_gridSizes() - //, m_windowFilter() -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - , m_filterTexture( NULL ) - //, m_filterTextureRect() - //, m_filterFrameRect() -#endif + , m_activated( false ) + , m_allDesktops( false ) + , m_ignoreMinimized( false ) + , m_decalOpacity( 0.0 ) + , m_hasKeyboardGrab( false ) + , m_tabBoxEnabled( false ) + , m_highlightedWindow( NULL ) + , m_filterFrame( false ) { + QFont font; + font.setPointSize( font.pointSize() * 2 ); + font.setBold( true ); + m_filterFrame.setFont( font ); + KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = ( KAction* )actionCollection->addAction( "Expose" ); a->setText( i18n( "Toggle Present Windows (Current desktop)" )); @@ -78,7 +74,6 @@ PresentWindowsEffect::~PresentWindowsEffect() { effects->unreserveElectricBorder( m_borderActivate ); effects->unreserveElectricBorder( m_borderActivateAll ); - discardFilterTexture(); } void PresentWindowsEffect::reconfigure( ReconfigureFlags ) @@ -130,25 +125,8 @@ void PresentWindowsEffect::paintScreen( int mask, QRegion region, ScreenPaintDat effects->paintScreen( mask, region, data ); // Display the filter box -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - if( m_filterTexture && region.intersects( m_filterFrameRect )) - { - glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - - // First render the frame - QColor color = QPalette().color( QPalette::Active, QPalette::Highlight ); - glColor4f( color.redF(), color.greenF(), color.blueF(), 0.75f ); - renderRoundBoxWithEdge( m_filterFrameRect ); - - // Then the text on top of it - m_filterTexture->bind(); - m_filterTexture->render( region, m_filterTextureRect ); - m_filterTexture->unbind(); - glPopAttrib(); - } -#endif + if( !m_windowFilter.isEmpty() ) + m_filterFrame.render( region ); } void PresentWindowsEffect::postPaintScreen() @@ -366,7 +344,7 @@ void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent *e ) if( !m_windowFilter.isEmpty() ) { m_windowFilter.remove( m_windowFilter.length() - 1, 1 ); - updateFilterTexture(); + updateFilterFrame(); rearrangeWindows(); } return; @@ -385,7 +363,7 @@ void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent *e ) if( !m_windowFilter.isEmpty() ) { m_windowFilter.clear(); - updateFilterTexture(); + updateFilterFrame(); rearrangeWindows(); } break; @@ -395,7 +373,7 @@ void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent *e ) if( !e->text().isEmpty() ) { m_windowFilter.append( e->text() ); - updateFilterTexture(); + updateFilterFrame(); rearrangeWindows(); return; } @@ -1196,7 +1174,7 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab ) // Move all windows back to their original position foreach( EffectWindow *w, m_motionManager.managedWindows() ) m_motionManager.moveWindow( w, w->geometry() ); - discardFilterTexture(); + m_filterFrame.free(); m_windowFilter.clear(); effects->destroyInputWindow( m_input ); @@ -1210,53 +1188,11 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab ) //----------------------------------------------------------------------------- // Filter box -void PresentWindowsEffect::discardFilterTexture() +void PresentWindowsEffect::updateFilterFrame() { -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - delete m_filterTexture; - m_filterTexture = NULL; -#endif - } - -void PresentWindowsEffect::updateFilterTexture() - { -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - discardFilterTexture(); - if( m_windowFilter.isEmpty()) - { - effects->addRepaint( m_filterTextureRect ); - return; - } - // Create font for filter text - QFont font; - font.setPointSize( font.pointSize() * 2 ); - font.setBold( true ); - // Get size of the rect containing filter text - QFontMetrics fm( font ); - QRect rect; - QString translatedString = i18n( "Filter:\n%1", m_windowFilter ); - rect.setSize( fm.size( 0, translatedString )); - QRect area = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop() ); - // Create image - QImage im( rect.width(), rect.height(), QImage::Format_ARGB32 ); - im.fill( Qt::transparent ); - // Paint the filter text to it - QPainter p( &im ); - p.setFont( font ); - p.setPen( QPalette().color( QPalette::Active, QPalette::HighlightedText )); - p.drawText( rect, Qt::AlignCenter, translatedString ); - p.end(); - // Create GL texture - m_filterTexture = new GLTexture( im ); - // Get position for filter text and it's frame - m_filterTextureRect = QRect( - area.x() + ( area.width() - rect.width() ) / 2, - area.y() + ( area.height() - rect.height() ) / 2, - rect.width(), rect.height() ); - m_filterFrameRect = m_filterTextureRect.adjusted( -20, -10, 20, 10 ); - // Schedule repaint - effects->addRepaint( m_filterTextureRect ); -#endif + QRect area = effects->clientArea( ScreenArea, effects->activeScreen(), effects->currentDesktop() ); + m_filterFrame.setPosition( QPoint( area.x() + area.width() / 2, area.y() + area.height() / 2 )); + m_filterFrame.setText( i18n( "Filter:\n%1", m_windowFilter )); } //----------------------------------------------------------------------------- diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index 19a9db5eac..3abbc8f5e2 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -121,8 +121,7 @@ class PresentWindowsEffect bool isOverlappingAny( EffectWindow *w, const QHash &targets, const QRegion &border ); // Filter box - void updateFilterTexture(); - void discardFilterTexture(); + void updateFilterFrame(); // Helper functions bool isSelectableWindow( EffectWindow *w ); @@ -166,12 +165,8 @@ class PresentWindowsEffect QList m_gridSizes; // Filter box + EffectFrame m_filterFrame; QString m_windowFilter; -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - GLTexture *m_filterTexture; - QRect m_filterTextureRect; - QRect m_filterFrameRect; -#endif }; } // namespace diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index bac4105d8c..420c96bb45 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -40,7 +40,8 @@ set(kwin_EFFECTSLIB_SRCS ) kde4_add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS}) -target_link_libraries(kwineffects ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY} ${X11_LIBRARIES} kephal) +target_link_libraries(kwineffects ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTGUI_LIBRARY} + ${X11_LIBRARIES} kephal) set_target_properties(kwineffects PROPERTIES VERSION 1.0.0 SOVERSION 1 ) install(TARGETS kwineffects EXPORT kdeworkspaceLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index 72300adade..17d8ca4bc7 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2009 Lucas Murray 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 @@ -1308,4 +1309,397 @@ EffectWindow* WindowMotionManager::windowAtPoint( QPoint point, bool useStacking return NULL; } +/*************************************************************** + EffectFrame +***************************************************************/ + +EffectFrame::EffectFrame( bool staticSize, QPoint position, Qt::Alignment alignment ) + : QObject() + , m_static( staticSize ) + , m_point( position ) + , m_alignment( alignment ) + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + m_texture = NULL; + m_textTexture = NULL; +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + m_picture = NULL; + m_textPicture = NULL; +#endif + + m_frame.setImagePath( "widgets/background" ); + m_frame.setCacheAllRenderedFrames( true ); + + connect( Plasma::Theme::defaultTheme(), SIGNAL( themeChanged() ), this, SLOT( plasmaThemeChanged() )); + } + +EffectFrame::~EffectFrame() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete m_texture; + delete m_textTexture; +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete m_picture; + delete m_textPicture; +#endif + } + +void EffectFrame::free() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete m_texture; + m_texture = NULL; + delete m_textTexture; + m_textTexture = NULL; +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete m_picture; + m_picture = NULL; + delete m_textPicture; + m_textPicture = NULL; +#endif + } + +void EffectFrame::render( QRegion region, double opacity ) + { + region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + { + if( !m_texture ) // Lazy creation + updateTexture(); + if( !m_texture || m_geometry.isEmpty() ) + return; + + glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glColor4f( 1.0, 1.0, 1.0, opacity ); + + glPushMatrix(); + + // Render the actual frame + m_texture->bind(); + qreal left, top, right, bottom; + m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry + m_texture->render( region, m_geometry.adjusted( -left, -top, right, bottom )); + m_texture->unbind(); + + // Render icon + if( !m_icon.isNull() && !m_iconSize.isEmpty() ) + { + QPoint topLeft( m_geometry.x(), m_geometry.center().y() - m_iconSize.height() / 2 ); + + GLTexture* icon = new GLTexture( m_icon ); // TODO: Cache + icon->bind(); + icon->render( region, QRect( topLeft, m_iconSize )); + icon->unbind(); + delete icon; + } + + // Render text + if( !m_text.isEmpty() ) + { + if( !m_textTexture ) // Lazy creation + updateTextTexture(); + m_textTexture->bind(); + m_textTexture->render( region, m_geometry ); + m_textTexture->unbind(); + } + + glPopMatrix(); + glPopAttrib(); + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + { + if( !m_picture ) // Lazy creation + updatePicture(); + if( !m_picture || m_geometry.isEmpty() ) + return; + + // TODO: Opacity + + // Render the actual frame + qreal left, top, right, bottom; + m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry + QRect geom = m_geometry.adjusted( -left, -top, right, bottom ); + XRenderComposite( display(), PictOpOver, *m_picture, None, effects->xrenderBufferPicture(), + 0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() ); + + // Render icon + if( !m_icon.isNull() && !m_iconSize.isEmpty() ) + { + QPoint topLeft( m_geometry.x(), m_geometry.center().y() - m_iconSize.height() / 2 ); + + XRenderPicture* icon = new XRenderPicture( m_icon ); // TODO: Cache + geom = QRect( topLeft, m_iconSize ); + XRenderComposite( display(), PictOpOver, *icon, None, effects->xrenderBufferPicture(), + 0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() ); + delete icon; + } + + // Render text + if( !m_text.isEmpty() ) + { + if( !m_textPicture ) // Lazy creation + updateTextPicture(); + XRenderComposite( display(), PictOpOver, *m_textPicture, None, effects->xrenderBufferPicture(), + 0, 0, 0, 0, m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height() ); + } + } +#endif + } + +void EffectFrame::setPosition( const QPoint& point ) + { + m_point = point; + } + +void EffectFrame::setGeometry( const QRect& geometry, bool force ) + { + bool newSize = false; + if( geometry.size() != m_geometry.size() ) + newSize = true; + effects->addRepaint( m_geometry ); + m_geometry = geometry; + effects->addRepaint( m_geometry ); + if( !newSize && !force ) + return; + qreal left, top, right, bottom; + m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry + m_frame.resizeFrame( m_geometry.adjusted( -left, -top, right, bottom ).size() ); + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + { + delete m_texture; + m_texture = NULL; + delete m_textTexture; + m_textTexture = NULL; + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + { + delete m_picture; + m_picture = NULL; + delete m_textPicture; + m_textPicture = NULL; + } +#endif + } + +void EffectFrame::setText( const QString& text ) + { + m_text = text; + QRect oldGeom = m_geometry; + autoResize(); + if( oldGeom == m_geometry ) + { // Wasn't updated in autoResize() +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + { + delete m_textTexture; + m_textTexture = NULL; + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + { + delete m_textPicture; + m_textPicture = NULL; + } + } +#endif + } + +void EffectFrame::setFont( const QFont& font ) + { + m_font = font; + QRect oldGeom = m_geometry; + if( !m_text.isEmpty() ) + autoResize(); + if( oldGeom == m_geometry ) + { // Wasn't updated in autoResize() +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + { + delete m_textTexture; + m_textTexture = NULL; + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + { + delete m_textPicture; + m_textPicture = NULL; + } + } +#endif + } + +void EffectFrame::setIcon( const QPixmap& icon ) + { + m_icon = icon; + if( m_iconSize.isEmpty() ) // Set a size if we don't already have one + setIconSize( m_icon.size() ); + } + +void EffectFrame::setIconSize( const QSize& size ) + { + m_iconSize = size; + autoResize(); + } + +QColor EffectFrame::textColor() + { + return Plasma::Theme::defaultTheme()->color( Plasma::Theme::TextColor ); + } + +void EffectFrame::plasmaThemeChanged() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( effects->compositingType() == OpenGLCompositing ) + { + delete m_texture; + m_texture = NULL; + delete m_textTexture; + m_textTexture = NULL; + } +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if( effects->compositingType() == XRenderCompositing ) + { + delete m_picture; + m_picture = NULL; + delete m_textPicture; + m_textPicture = NULL; + } +#endif + } + +void EffectFrame::autoResize() + { + if( m_static ) + return; // Not automatically resizing + + QRect geometry; + + // Set size + if( !m_text.isEmpty() ) + { + QFontMetrics metrics( m_font ); + geometry.setSize( metrics.size( 0, m_text )); + } + if( !m_icon.isNull() && !m_iconSize.isEmpty() ) + { + geometry.setLeft( -m_iconSize.width() ); + if( m_iconSize.height() > geometry.height() ) + geometry.setHeight( m_iconSize.height() ); + } + + // Set position + if( m_alignment & Qt::AlignLeft ) + geometry.moveLeft( m_point.x() ); + else if( m_alignment & Qt::AlignRight ) + geometry.moveLeft( m_point.x() - geometry.width() ); + else + geometry.moveLeft( m_point.x() - geometry.width() / 2 ); + if( m_alignment & Qt::AlignTop ) + geometry.moveTop( m_point.y() ); + else if( m_alignment & Qt::AlignBottom ) + geometry.moveTop( m_point.y() - geometry.height() ); + else + geometry.moveTop( m_point.y() - geometry.height() / 2 ); + + setGeometry( geometry ); + } + +void EffectFrame::updateTexture() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete m_texture; + m_texture = new GLTexture( m_frame.framePixmap() ); +#endif + } + +void EffectFrame::updateTextTexture() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete m_textTexture; + + if( m_text.isEmpty() ) + return; + + // Determine position on texture to paint text + QRect rect( QPoint( 0, 0 ), m_geometry.size() ); + if( !m_icon.isNull() && !m_iconSize.isEmpty() ) + rect.setLeft( m_iconSize.width() ); + + // If static size elide text as required + QString text = m_text; + if( m_static ) + { + QFontMetrics metrics( m_font ); + text = metrics.elidedText( text, Qt::ElideRight, rect.width() ); + } + + // TODO: Use QPixmap for this once GLTexture has been converted to it + QImage pixmap( m_geometry.size(), QImage::Format_ARGB32 ); + pixmap.fill( Qt::transparent ); + QPainter p( &pixmap ); + p.setFont( m_font ); + p.setPen( textColor() ); + p.drawText( rect, Qt::AlignCenter, text ); + p.end(); + m_textTexture = new GLTexture( pixmap ); +#endif + } + +void EffectFrame::updatePicture() + { +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete m_picture; + m_picture = new XRenderPicture( m_frame.framePixmap() ); +#endif + } + +void EffectFrame::updateTextPicture() + { // Mostly copied from EffectFrame::updateTextTexture() above +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete m_textPicture; + + if( m_text.isEmpty() ) + return; + + // Determine position on texture to paint text + QRect rect( QPoint( 0, 0 ), m_geometry.size() ); + if( !m_icon.isNull() && !m_iconSize.isEmpty() ) + rect.setLeft( m_iconSize.width() ); + + // If static size elide text as required + QString text = m_text; + if( m_static ) + { + QFontMetrics metrics( m_font ); + text = metrics.elidedText( text, Qt::ElideRight, rect.width() ); + } + + QPixmap pixmap( m_geometry.size() ); + pixmap.fill( Qt::transparent ); + QPainter p( &pixmap ); + p.setFont( m_font ); + p.setPen( textColor() ); + p.drawText( rect, Qt::AlignCenter, text ); + p.end(); + m_textPicture = new XRenderPicture( pixmap ); +#endif + } + } // namespace diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 5f5411c531..ec489b4d27 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak +Copyright (C) 2009 Lucas Murray 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 @@ -23,6 +24,8 @@ along with this program. If not, see . #include #include +#include +#include #include "kdecoration.h" #include @@ -39,6 +42,9 @@ along with this program. If not, see . #include #include +#include +#include + #include #include @@ -57,6 +63,8 @@ class Effect; class WindowQuad; class GLRenderTarget; class GLShader; +class GLTexture; +class XRenderPicture; class RotationData; class WindowQuadList; class WindowPrePaintData; @@ -164,7 +172,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 80 +#define KWIN_EFFECT_API_VERSION_MINOR 81 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -1253,7 +1261,7 @@ class KWIN_EXPORT PaintClipper class KWIN_EXPORT TimeLine { - Q_ENUMS( CurveShape ) + //Q_ENUMS( CurveShape ) // Requires Q_OBJECT public: /** @@ -1585,6 +1593,86 @@ class KWIN_EXPORT WindowMotionManager uint m_movingWindows; }; +/** + * @short Helper class for painting themed boxes. + * + * Paints a box using the default Plasma theme. + */ +class KWIN_EXPORT EffectFrame : public QObject + { + Q_OBJECT + + public: + /** + * Creates a new frame object. If the frame does not have a static size + * then it will be located at @a position with @a alignment. A + * non-static frame will automatically adjust its size to fit the + * contents. + */ + EffectFrame( bool staticSize = false, QPoint position = QPoint( -1, -1 ), + Qt::Alignment alignment = Qt::AlignCenter ); + ~EffectFrame(); + + /** + * Delete any existing textures to free up graphics memory. They will + * be automatically recreated the next time they are required. + */ + void free(); + + /** + * Render the frame. + */ + void render( QRegion region = infiniteRegion(), double opacity = 1.0 ); + + void setPosition( const QPoint& point ); + inline void setAlignment( Qt::Alignment alignment ) + { m_alignment = alignment; }; // Doesn't change geometry + void setGeometry( const QRect& geometry, bool force = false ); + QRect geometry() const // Inner/contents geometry + { return m_geometry; }; + + void setText( const QString& text ); + void setFont( const QFont& font ); + /** + * Set the icon that will appear on the left-hand size of the frame. + */ + void setIcon( const QPixmap& icon ); + void setIconSize( const QSize& size ); + + /** + * The foreground text color as specified by the default Plasma theme. + */ + static QColor textColor(); + + private slots: + void plasmaThemeChanged(); + + private: + void autoResize(); // Auto-resize if not a static size + void updateTexture(); // Update OpenGL frame texture + void updateTextTexture(); // Update OpenGL text texture + void updatePicture(); // Update XRender frame picture + void updateTextPicture(); // Update XRender text picture + + Plasma::FrameSvg m_frame; + GLTexture* m_texture; + GLTexture* m_textTexture; + XRenderPicture* m_picture; + XRenderPicture* m_textPicture; + + // Position + bool m_static; + QPoint m_point; + Qt::Alignment m_alignment; + QRect m_geometry; + + // Contents + QString m_text; + QFont m_font; + QPixmap m_icon; + QSize m_iconSize; + }; + /** * Pointer to the global EffectsHandler object. **/ diff --git a/lib/kwinglutils.h b/lib/kwinglutils.h index e72f3f2817..3a7f6c8f40 100644 --- a/lib/kwinglutils.h +++ b/lib/kwinglutils.h @@ -102,6 +102,10 @@ KWIN_EXPORT void renderGLGeometryImmediate( int count, KWIN_EXPORT void renderRoundBox( const QRect& area, float roundness = 10.0f, GLTexture* texture = 0 ); +/** + * @deprecated + * @see EffectFrame + */ KWIN_EXPORT void renderRoundBoxWithEdge( const QRect& area, float roundness = 10.0f );