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:
parent
75346f126b
commit
e03748fba7
12 changed files with 631 additions and 291 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -102,6 +102,8 @@ class CubeEffect
|
|||
float cubeOpacity;
|
||||
bool opacityDesktopOnly;
|
||||
bool displayDesktopName;
|
||||
EffectFrame desktopNameFrame;
|
||||
QFont desktopNameFont;
|
||||
bool reflection;
|
||||
bool rotating;
|
||||
bool verticalRotating;
|
||||
|
|
|
@ -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 ));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
**/
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue