Added EffectFrame, a helper class that creates, manages and caches a

Plasma frame object. There are two ways to use this class: The first is
in "static" mode which gives the frame a set geometry and will not
change, the second is an automatic mode that creates the smallest
possible frame around the specified contents. Contents can either be
normal text and/or a QPixmap, useful for displaying the caption and icon
of the currently highlighed window.
Known bugs:
 - Does not detect Plasma theme changes, known to be in the Plasma
   library.
 - Slight graphical glitches, known to be in Qt 4.5.0 RC1.
Untested:
 - What happens when there is no Plasma theme installed.

svn path=/trunk/KDE/kdebase/workspace/; revision=929324
This commit is contained in:
Lucas Murray 2009-02-21 04:53:13 +00:00
parent 75346f126b
commit e03748fba7
12 changed files with 631 additions and 291 deletions

View file

@ -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

View file

@ -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;

View file

@ -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();
}

View file

@ -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;

View file

@ -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();
}

View file

@ -102,6 +102,8 @@ class CubeEffect
float cubeOpacity;
bool opacityDesktopOnly;
bool displayDesktopName;
EffectFrame desktopNameFrame;
QFont desktopNameFont;
bool reflection;
bool rotating;
bool verticalRotating;

View file

@ -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 ));
}
//-----------------------------------------------------------------------------

View file

@ -121,8 +121,7 @@ class PresentWindowsEffect
bool isOverlappingAny( EffectWindow *w, const QHash<EffectWindow*, QRect> &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<GridSize> 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

View file

@ -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})

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
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

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2009 Lucas Murray <lmurray@undefinedfire.com>
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 <http://www.gnu.org/licenses/>.
#include <kwinconfig.h>
#include <kwinglobals.h>
#include <kwinglutils.h>
#include <kwinxrenderutils.h>
#include "kdecoration.h"
#include <QtCore/QPair>
@ -39,6 +42,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KDE/KPluginFactory>
#include <KDE/KShortcutsEditor>
#include <Plasma/FrameSvg>
#include <Plasma/Theme>
#include <assert.h>
#include <limits.h>
@ -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.
**/

View file

@ -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 );