Added support for unstyled and frameless EffectFrames. Converted all

effects that display text or boxes to use the class. Minor speed
increase in XRender mode for those effects and a massive increase in
OpenGL mode (Double framerate in present windows in my case).

svn path=/trunk/KDE/kdebase/workspace/; revision=929951
This commit is contained in:
Lucas Murray 2009-02-22 13:04:16 +00:00
parent d31dc9eb9b
commit 1e91a66fd2
11 changed files with 324 additions and 153 deletions

View file

@ -41,12 +41,16 @@ KWIN_EFFECT( boxswitch, BoxSwitchEffect )
BoxSwitchEffect::BoxSwitchEffect()
: mActivated( 0 )
, mMode( 0 )
, thumbnailFrame( true )
, thumbnailFrame( EffectFrame::Styled )
, selected_window( 0 )
, painting_desktop( 0 )
, animation( false )
, highlight_is_set( false )
{
text_font.setBold( true );
text_font.setPointSize( 12 );
thumbnailFrame.setFont( text_font );
thumbnailFrame.setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
highlight_margin = 10;
reconfigure( ReconfigureAll );
@ -147,7 +151,6 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
paintWindowIcon( w );
}
}
paintText( selected_window->caption() );
}
else
{
@ -164,7 +167,6 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
paintDesktopThumbnail( painting_desktop );
}
paintText( effects->desktopName( selected_desktop ));
painting_desktop = 0;
}
}
@ -401,11 +403,12 @@ void BoxSwitchEffect::tabBoxUpdated()
effects->addRepaint( text_area );
original_windows = effects->currentTabBoxWindowList();
}
else
else if( mMode != TabBoxWindowsMode )
{ // DesktopMode
if( desktops.contains( selected_desktop ))
effects->addRepaint( desktops.value( selected_desktop )->area );
selected_desktop = effects->currentTabBoxDesktop();
thumbnailFrame.setText( effects->desktopName( selected_desktop ));
if( desktops.contains( selected_desktop ))
effects->addRepaint( desktops.value( selected_desktop )->area );
effects->addRepaint( text_area );
@ -438,6 +441,7 @@ void BoxSwitchEffect::setActive()
{
original_desktops = effects->currentTabBoxDesktopList();
selected_desktop = effects->currentTabBoxDesktop();
thumbnailFrame.setText( effects->desktopName( selected_desktop ));
}
calculateFrameSize();
calculateItemSizes();
@ -491,6 +495,7 @@ void BoxSwitchEffect::setSelectedWindow( EffectWindow* w )
effects->setElevatedWindow( selected_window, false );
}
selected_window = w;
thumbnailFrame.setText( selected_window->caption() );
if( elevate_window && w )
{
effects->setElevatedWindow( selected_window, true );
@ -528,8 +533,6 @@ void BoxSwitchEffect::calculateFrameSize()
item_max_size.setHeight( 200 );
}
// How much height to reserve for a one-line text label
text_font.setBold( true );
text_font.setPointSize( 12 );
text_area.setHeight( QFontMetrics( text_font ).height() * 1.2 );
// Separator space between items and text
const int separator_height = 6;
@ -1053,10 +1056,4 @@ void BoxSwitchEffect::paintWindowIcon( EffectWindow* w )
#endif
}
void BoxSwitchEffect::paintText( const QString& text )
{
int maxwidth = text_area.width();
effects->paintText( text, text_area.center(), maxwidth, EffectFrame::textColor(), text_font );
}
} // namespace

View file

@ -70,7 +70,6 @@ class BoxSwitchEffect
void paintWindowThumbnail( EffectWindow* w );
void paintDesktopThumbnail( int iDesktop );
void paintWindowIcon( EffectWindow* w );
void paintText( const QString& text );
bool mActivated;
Window mInput;

View file

@ -52,8 +52,8 @@ CoverSwitchEffect::CoverSwitchEffect()
, scaleFactor( 0.0 )
, direction( Left )
, selected_window( 0 )
, captionFrame( true )
, thumbnailFrame( true )
, captionFrame( EffectFrame::Styled )
, thumbnailFrame( EffectFrame::Styled )
{
reconfigure( ReconfigureAll );

View file

@ -57,7 +57,7 @@ CubeEffect::CubeEffect()
, cubeOpacity( 1.0 )
, opacityDesktopOnly( true )
, displayDesktopName( false )
, desktopNameFrame( true )
, desktopNameFrame( EffectFrame::Styled )
, reflection( true )
, rotating( false )
, desktopChangedWhileRotating( false )

View file

@ -135,12 +135,6 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
if( desktopNameAlignment )
{
double progress = timeline.value();
QColor textColor( 255, 255, 255, 255 * progress );
QColor bgColor( 0, 0, 0, 178 * progress ); // 70%
QFont f;
f.setBold( true );
f.setPointSize( 12 );
for( int screen = 0; screen < effects->numScreens(); screen++ )
{
QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
@ -152,8 +146,21 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
QRect textArea( posTL.x(), posTL.y(), posBR.x() - posTL.x(), posBR.y() - posTL.y() );
textArea.adjust( textArea.width() / 10, textArea.height() / 10,
-textArea.width() / 10, -textArea.height() / 10 );
effects->paintTextWithBackground( effects->desktopName( desktop ),
textArea, textColor, bgColor, f, desktopNameAlignment );
int x, y;
if( desktopNameAlignment & Qt::AlignLeft )
x = textArea.x();
else if( desktopNameAlignment & Qt::AlignRight )
x = textArea.right();
else
x = textArea.center().x();
if( desktopNameAlignment & Qt::AlignTop )
y = textArea.y();
else if( desktopNameAlignment & Qt::AlignBottom )
y = textArea.bottom();
else
y = textArea.center().y();
desktopNames[desktop-1]->setPosition( QPoint( x, y ));
desktopNames[desktop-1]->render( region, timeline.value(), 0.7 );
}
}
}
@ -750,6 +757,22 @@ void DesktopGridEffect::setup()
}
hoverTimeline[effects->currentDesktop() - 1].setProgress( 1.0 );
// Create desktop name textures if enabled
if( desktopNameAlignment )
{
desktopNames = new EffectFrame*[effects->numberOfDesktops()];
QFont font;
font.setBold( true );
font.setPointSize( 12 );
for( int i = 0; i < effects->numberOfDesktops(); i++ )
{
desktopNames[i] = new EffectFrame( EffectFrame::Unstyled, false );
desktopNames[i]->setFont( font );
desktopNames[i]->setText( effects->desktopName( i+1 ));
desktopNames[i]->setAlignment( desktopNameAlignment );
}
}
// We need these variables for every paint so lets cache them
int x, y;
int numDesktops = effects->numberOfDesktops();
@ -806,6 +829,13 @@ void DesktopGridEffect::setup()
void DesktopGridEffect::finish()
{
if( desktopNameAlignment )
{
for( int i = 0; i < effects->numberOfDesktops(); i++ )
delete desktopNames[i];
delete[] desktopNames;
}
if( keyboardGrab )
effects->ungrabKeyboard();
keyboardGrab = false;

View file

@ -85,7 +85,9 @@ class DesktopGridEffect
// Soft highlighting
QList<TimeLine> hoverTimeline;
EffectFrame** desktopNames;
QSize gridSize;
Qt::Orientation orientation;
QPoint activeCell;

View file

@ -51,7 +51,7 @@ PresentWindowsEffect::PresentWindowsEffect()
, m_hasKeyboardGrab( false )
, m_tabBoxEnabled( false )
, m_highlightedWindow( NULL )
, m_filterFrame( false )
, m_filterFrame( EffectFrame::Styled, false )
{
QFont font;
font.setPointSize( font.pointSize() * 2 );
@ -136,7 +136,16 @@ void PresentWindowsEffect::postPaintScreen()
else if( !m_activated && m_motionManager.managingWindows() )
{ // We have finished moving them back, stop processing
m_motionManager.unmanageAll();
DataHash::iterator i = m_windowData.begin();
while( i != m_windowData.end() )
{
delete i.value().textFrame;
delete i.value().iconFrame;
i++;
}
m_windowData.clear();
effects->setActiveFullScreenEffect( NULL );
}
@ -211,23 +220,21 @@ void PresentWindowsEffect::paintWindow( EffectWindow *w, int mask, QRegion regio
m_motionManager.apply( w, data );
effects->paintWindow( w, mask, region, data );
const WindowData &wData = m_windowData[w];
QRect rect = m_motionManager.transformedGeometry( w ).toRect();
if( m_showIcons )
paintWindowIcon( w, data );
{
QPoint point( rect.x() + rect.width() * 0.95,
rect.y() + rect.height() * 0.95 );
m_windowData[w].iconFrame->setPosition( point );
m_windowData[w].iconFrame->render( region, 0.9 * data.opacity * m_decalOpacity, 0.75 );
}
if( m_showCaptions )
{
QString text = w->caption();
QRect textArea( w->x() + data.xTranslate, w->y() + data.yTranslate,
w->width() * data.xScale, w->height() * data.yScale );
textArea.adjust( 10, 10, -10, -10 );
double opacity = (0.7 + 0.2 * wData.highlight) * data.opacity * m_decalOpacity;
QColor textcolor( 255, 255, 255, int( 255 * opacity ));
QColor bgcolor( 0, 0, 0, int( 255 * opacity ));
QFont f;
f.setBold( true );
f.setPointSize( 12 );
effects->paintTextWithBackground( text, textArea, textcolor, bgcolor, f );
QPoint point( rect.x() + rect.width() / 2,
rect.y() + rect.height() / 2 );
m_windowData[w].textFrame->setPosition( point );
m_windowData[w].textFrame->render( region, 0.9 * data.opacity * m_decalOpacity, 0.75 );
}
}
else
@ -245,6 +252,14 @@ void PresentWindowsEffect::windowAdded( EffectWindow *w )
m_windowData[w].visible = isVisibleWindow( w );
m_windowData[w].opacity = 0.0;
m_windowData[w].highlight = 0.0;
m_windowData[w].textFrame = new EffectFrame( EffectFrame::Unstyled, false );
QFont font;
font.setBold( true );
font.setPointSize( 12 );
m_windowData[w].textFrame->setFont( font );
m_windowData[w].iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].iconFrame->setAlignment( Qt::AlignRight | Qt::AlignBottom );
m_windowData[w].iconFrame->setIcon( w->icon() );
if( isSelectableWindow( w ))
{
m_motionManager.manage( w );
@ -262,6 +277,8 @@ void PresentWindowsEffect::windowClosed( EffectWindow *w )
void PresentWindowsEffect::windowDeleted( EffectWindow *w )
{
delete m_windowData[w].textFrame;
delete m_windowData[w].iconFrame;
m_windowData.remove( w );
m_motionManager.unmanage( w );
}
@ -511,6 +528,19 @@ void PresentWindowsEffect::rearrangeWindows()
else
calculateWindowTransformationsNatural( windows, screen );
}
// Resize text frames if required
QFontMetrics* metrics = NULL; // All fonts are the same
foreach( EffectWindow *w, m_motionManager.managedWindows() )
{
if( !metrics )
metrics = new QFontMetrics( m_windowData[w].textFrame->font() );
QRect geom = m_motionManager.targetGeometry( w ).toRect();
QString string = metrics->elidedText( w->caption(), Qt::ElideRight, geom.width() * 0.9 );
if( string != m_windowData[w].textFrame->text() )
m_windowData[w].textFrame->setText( string );
}
delete metrics;
}
void PresentWindowsEffect::calculateWindowTransformationsClosest( EffectWindowList windowlist, int screen )
@ -1110,6 +1140,14 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab )
if( w->isOnCurrentDesktop() && !w->isMinimized() )
m_windowData[w].opacity = 1.0;
m_windowData[w].highlight = 1.0;
m_windowData[w].textFrame = new EffectFrame( EffectFrame::Unstyled, false );
QFont font;
font.setBold( true );
font.setPointSize( 12 );
m_windowData[w].textFrame->setFont( font );
m_windowData[w].iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].iconFrame->setAlignment( Qt::AlignRight | Qt::AlignBottom );
m_windowData[w].iconFrame->setIcon( w->icon() );
}
if( m_tabBoxEnabled )
@ -1135,7 +1173,16 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab )
(( m_motionManager.managedWindows().count() == 1 ) && m_motionManager.managedWindows().first()->isOnCurrentDesktop() ))
{ // No point triggering if there is nothing to do
m_activated = false;
DataHash::iterator i = m_windowData.begin();
while( i != m_windowData.end() )
{
delete i.value().textFrame;
delete i.value().iconFrame;
i++;
}
m_windowData.clear();
m_motionManager.unmanageAll();
return;
}
@ -1417,63 +1464,6 @@ EffectWindow* PresentWindowsEffect::findFirstWindow() const
return topLeft;
}
void PresentWindowsEffect::paintWindowIcon( EffectWindow *w, WindowPaintData &data )
{
// Don't bother if we don't even have an icon
if( w->icon().isNull() )
return;
WindowData &wData = m_windowData[w];
if( wData.icon.cacheKey() != w->icon().cacheKey())
{ // Make sure data.icon is the right QPixmap, and rebind
wData.icon = w->icon();
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
wData.iconTexture = new GLTexture( wData.icon );
wData.iconTexture->setFilter( GL_LINEAR );
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
wData.iconPicture = XRenderPicture( wData.icon );
#endif
}
int icon_margin = 8;
int width = wData.icon.width();
int height = wData.icon.height();
int x = w->x() + data.xTranslate + w->width() * data.xScale * 0.95 - width - icon_margin;
int y = w->y() + data.yTranslate + w->height() * data.yScale * 0.95 - height - icon_margin;
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
// Render some background
glColor4f( 0, 0, 0, 0.5 * wData.opacity * m_decalOpacity );
renderRoundBox( QRect( x-3, y-3, width+6, height+6 ), 3 );
// Render the icon
glColor4f( 1, 1, 1, 1 * wData.opacity * m_decalOpacity );
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
wData.iconTexture->bind();
wData.iconTexture->render( infiniteRegion(), QRect( x, y, width, height ));
wData.iconTexture->unbind();
glPopAttrib();
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
XRenderComposite( display(),
wData.icon.depth() == 32 ? PictOpOver : PictOpSrc,
wData.iconPicture, None,
effects->xrenderBufferPicture(),
0, 0, 0, 0, x, y, width, height );
}
#endif
}
} // namespace
#include "presentwindows.moc"

View file

@ -24,10 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "presentwindows_proxy.h"
// Include with base class for effects.
#include <kwineffects.h>
#include <kwinglutils.h>
#include <kwinxrenderutils.h>
#include <QPixmap>
@ -52,12 +49,8 @@ class PresentWindowsEffect
int slot;
int slot_distance;
QPixmap icon;
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
KSharedPtr< GLTexture > iconTexture;
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
XRenderPicture iconPicture;
#endif
EffectFrame* textFrame;
EffectFrame* iconFrame;
};
typedef QHash<EffectWindow*, WindowData> DataHash;
struct GridSize
@ -129,7 +122,6 @@ class PresentWindowsEffect
void setHighlightedWindow( EffectWindow *w );
EffectWindow* relativeWindow( EffectWindow *w, int xdiff, int ydiff, bool wrap ) const;
EffectWindow* findFirstWindow() const;
void paintWindowIcon( EffectWindow *w, WindowPaintData &data ); // TODO: Do we need this?
private:
PresentWindowsEffectProxy m_proxy;

View file

@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kdebug.h>
#include <ksharedconfig.h>
#include <kstandarddirs.h>
#include <kconfiggroup.h>
#include <assert.h>
@ -1297,6 +1298,18 @@ QRectF WindowMotionManager::transformedGeometry( EffectWindow *w ) const
return geometry;
}
QRectF WindowMotionManager::targetGeometry( EffectWindow *w ) const
{
QRectF geometry( w->geometry() );
// TODO: Take into account existing scale so that we can work with multiple managers (E.g. Present windows + grid)
geometry.moveTo( m_managedWindows[ w ].translation.target() );
geometry.setWidth( geometry.width() * m_managedWindows[ w ].scale.target().x() );
geometry.setHeight( geometry.height() * m_managedWindows[ w ].scale.target().y() );
return geometry;
}
EffectWindow* WindowMotionManager::windowAtPoint( QPoint point, bool useStackingOrder ) const
{
// TODO: Stacking order uses EffectsHandler::stackingOrder() then filters by m_managedWindows
@ -1313,8 +1326,11 @@ EffectWindow* WindowMotionManager::windowAtPoint( QPoint point, bool useStacking
EffectFrame
***************************************************************/
EffectFrame::EffectFrame( bool staticSize, QPoint position, Qt::Alignment alignment )
GLTexture* EffectFrame::m_unstyledTexture = NULL;
EffectFrame::EffectFrame( Style style, bool staticSize, QPoint position, Qt::Alignment alignment )
: QObject()
, m_style( style )
, m_static( staticSize )
, m_point( position )
, m_alignment( alignment )
@ -1328,10 +1344,19 @@ EffectFrame::EffectFrame( bool staticSize, QPoint position, Qt::Alignment alignm
m_textPicture = NULL;
#endif
m_frame.setImagePath( "widgets/background" );
m_frame.setCacheAllRenderedFrames( true );
connect( Plasma::Theme::defaultTheme(), SIGNAL( themeChanged() ), this, SLOT( plasmaThemeChanged() ));
if( m_style == Unstyled )
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing && !m_unstyledTexture )
updateUnstyledTexture();
#endif
}
else if( m_style == Styled )
{
m_frame.setImagePath( "widgets/background" );
m_frame.setCacheAllRenderedFrames( true );
connect( Plasma::Theme::defaultTheme(), SIGNAL( themeChanged() ), this, SLOT( plasmaThemeChanged() ));
}
}
EffectFrame::~EffectFrame()
@ -1362,32 +1387,94 @@ void EffectFrame::free()
#endif
}
void EffectFrame::render( QRegion region, double opacity )
void EffectFrame::render( QRegion region, double opacity, double frameOpacity )
{
if( m_geometry.isEmpty() )
return; // Nothing to display
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();
if( m_style == Unstyled )
{
const QRect& area = m_geometry.adjusted( -5, -5, 5, 5 );
const int roundness = 5;
QVector<float> verts, texCoords;
verts.reserve( 80 );
texCoords.reserve( 80 );
// Center
addQuadVertices( verts, area.left() + roundness, area.top() + roundness,
area.right() - roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 0.5 );
// Left
addQuadVertices( verts, area.left(), area.top() + roundness,
area.left() + roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 0.5 );
// Top
addQuadVertices( verts, area.left() + roundness, area.top(),
area.right() - roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 0.5, 0.5 );
// Right
addQuadVertices( verts, area.right() - roundness, area.top() + roundness,
area.right(), area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 0.5 );
// Bottom
addQuadVertices( verts, area.left() + roundness, area.bottom() - roundness,
area.right() - roundness, area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 1.0 );
// Top-left
addQuadVertices( verts, area.left(), area.top(),
area.left() + roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.0, 0.0, 0.5, 0.5 );
// Top-right
addQuadVertices( verts, area.right() - roundness, area.top(),
area.right(), area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 1.0, 0.5 );
// Bottom-left
addQuadVertices( verts, area.left(), area.bottom() - roundness,
area.left() + roundness, area.bottom() );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 1.0 );
// Bottom-right
addQuadVertices( verts, area.right() - roundness, area.bottom() - roundness,
area.right(), area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 1.0 );
glColor4f( 0.0, 0.0, 0.0, opacity * frameOpacity );
m_unstyledTexture->bind();
m_unstyledTexture->enableNormalizedTexCoords();
renderGLGeometry( verts.count() / 2, verts.data(), texCoords.data() );
m_unstyledTexture->disableNormalizedTexCoords();
m_unstyledTexture->unbind();
}
else if( m_style == Styled )
{
if( !m_texture ) // Lazy creation
updateTexture();
glColor4f( 1.0, 1.0, 1.0, opacity * frameOpacity );
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();
}
glColor4f( 1.0, 1.0, 1.0, opacity );
// Render icon
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
@ -1418,19 +1505,23 @@ void EffectFrame::render( QRegion region, double opacity )
#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() );
if( m_style == Unstyled )
xRenderRoundBox( effects->xrenderBufferPicture(), m_geometry.adjusted( -5, -5, 5, 5 ),
5, QColor( 0, 0, 0, int( opacity * frameOpacity * 255 )));
else if( m_style == Styled )
{
if( !m_picture ) // Lazy creation
updatePicture();
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() );
}
// Opacity, TODO: Can we further optimize this?
XRenderPicture fill = xRenderFill( QColor( 255, 255, 255, int( opacity * 255 )));
// Render icon
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
@ -1438,8 +1529,8 @@ void EffectFrame::render( QRegion region, double opacity )
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(),
QRect geom = QRect( topLeft, m_iconSize );
XRenderComposite( display(), PictOpOver, *icon, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() );
delete icon;
}
@ -1449,7 +1540,7 @@ void EffectFrame::render( QRegion region, double opacity )
{
if( !m_textPicture ) // Lazy creation
updateTextPicture();
XRenderComposite( display(), PictOpOver, *m_textPicture, None, effects->xrenderBufferPicture(),
XRenderComposite( display(), PictOpOver, *m_textPicture, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height() );
}
}
@ -1459,6 +1550,7 @@ void EffectFrame::render( QRegion region, double opacity )
void EffectFrame::setPosition( const QPoint& point )
{
m_point = point;
autoResize();
}
void EffectFrame::setGeometry( const QRect& geometry, bool force )
@ -1471,9 +1563,13 @@ void EffectFrame::setGeometry( const QRect& geometry, bool force )
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() );
if( m_style == Styled )
{
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 )
@ -1625,7 +1721,8 @@ void EffectFrame::updateTexture()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_texture;
m_texture = new GLTexture( m_frame.framePixmap() );
if( m_style == Styled )
m_texture = new GLTexture( m_frame.framePixmap() );
#endif
}
@ -1656,7 +1753,7 @@ void EffectFrame::updateTextTexture()
QPainter p( &pixmap );
p.setFont( m_font );
p.setPen( textColor() );
p.drawText( rect, Qt::AlignCenter, text );
p.drawText( rect, m_alignment, text );
p.end();
m_textTexture = new GLTexture( pixmap );
#endif
@ -1666,7 +1763,8 @@ void EffectFrame::updatePicture()
{
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
delete m_picture;
m_picture = new XRenderPicture( m_frame.framePixmap() );
if( m_style == Styled )
m_picture = new XRenderPicture( m_frame.framePixmap() );
#endif
}
@ -1696,10 +1794,19 @@ void EffectFrame::updateTextPicture()
QPainter p( &pixmap );
p.setFont( m_font );
p.setPen( textColor() );
p.drawText( rect, Qt::AlignCenter, text );
p.drawText( rect, m_alignment, text );
p.end();
m_textPicture = new XRenderPicture( pixmap );
#endif
}
void EffectFrame::updateUnstyledTexture()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_unstyledTexture;
QString filename = KGlobal::dirs()->findResource( "data", "kwin/circle.png" );
m_unstyledTexture = new GLTexture( filename );
#endif
}
} // namespace

View file

@ -714,6 +714,8 @@ class KWIN_EXPORT EffectsHandler
virtual int shadowTextureList( ShadowType type ) const = 0;
/**
* @deprecated
* @see EffectFrame
* Paints given text onto screen, possibly in elided form
* @param text
* @param center center point of the painted text
@ -723,11 +725,23 @@ class KWIN_EXPORT EffectsHandler
**/
bool paintText( const QString& text, const QPoint& center, int maxwidth,
const QColor& color, const QFont& font = QFont() );
/**
* @deprecated
* @see EffectFrame
*/
bool paintText( const QString& text, const QRect& rect, const QColor& color,
const QFont& font = QFont(), const Qt::Alignment& alignment = Qt::AlignCenter );
/**
* @deprecated
* @see EffectFrame
*/
bool paintTextWithBackground( const QString& text, const QPoint& center, int maxwidth,
const QColor& color, const QColor& bgcolor,
const QFont& font = QFont() );
/**
* @deprecated
* @see EffectFrame
*/
bool paintTextWithBackground( const QString& text, const QRect& rect, const QColor& color,
const QColor& bgcolor, const QFont& font = QFont(),
const Qt::Alignment& alignment = Qt::AlignCenter );
@ -1551,6 +1565,11 @@ class KWIN_EXPORT WindowMotionManager
* window.
*/
QRectF transformedGeometry( EffectWindow *w ) const;
/**
* Retrieve the current target geometry of a registered
* window.
*/
QRectF targetGeometry( EffectWindow *w ) const;
/**
* Return the window that has it's transformed geometry under
* the specified point. It is recommended to use the stacking
@ -1592,22 +1611,32 @@ class KWIN_EXPORT WindowMotionManager
};
/**
* @short Helper class for painting themed boxes.
* @short Helper class for displaying text and icons in frames.
*
* Paints a box using the default Plasma theme.
* Paints text and/or and icon with an optional frame around them. The
* available frames includes one that follows the default Plasma theme and
* another that doesn't.
* It is recommended to use this class whenever displaying text.
*/
class KWIN_EXPORT EffectFrame : public QObject
{
Q_OBJECT
public:
enum Style
{
None, ///< Displays no frame around the contents.
Unstyled, ///< Displays a basic box around the contents.
Styled ///< Displays a Plasma-styled frame around the contents.
};
/**
* 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 ),
EffectFrame( Style style, bool staticSize = true, QPoint position = QPoint( -1, -1 ),
Qt::Alignment alignment = Qt::AlignCenter );
~EffectFrame();
@ -1620,22 +1649,34 @@ class KWIN_EXPORT EffectFrame : public QObject
/**
* Render the frame.
*/
void render( QRegion region = infiniteRegion(), double opacity = 1.0 );
void render( QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0 );
void setPosition( const QPoint& point );
/**
* Set the text alignment for static frames and the position alignment
* for non-static.
*/
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
inline QRect geometry() const // Inner/contents geometry
{ return m_geometry; };
void setText( const QString& text );
inline QString text() const
{ return m_text; };
void setFont( const QFont& font );
inline QFont font() const
{ return m_font; };
/**
* Set the icon that will appear on the left-hand size of the frame.
*/
void setIcon( const QPixmap& icon );
inline QPixmap icon() const
{ return m_icon; };
void setIconSize( const QSize& size );
inline QSize iconSize() const
{ return m_iconSize; };
/**
* The foreground text color as specified by the default Plasma theme.
@ -1646,12 +1687,15 @@ class KWIN_EXPORT EffectFrame : public QObject
void plasmaThemeChanged();
private:
Q_DISABLE_COPY( EffectFrame ) // As we need to use Qt slots we cannot copy this class
void autoResize(); // Auto-resize if not a static size
void updateTexture(); // Update OpenGL frame texture
void updateTexture(); // Update OpenGL styled frame texture
void updateTextTexture(); // Update OpenGL text texture
void updatePicture(); // Update XRender frame picture
void updatePicture(); // Update XRender styled frame picture
void updateTextPicture(); // Update XRender text picture
Style m_style;
Plasma::FrameSvg m_frame;
GLTexture* m_texture;
GLTexture* m_textTexture;
@ -1669,6 +1713,9 @@ class KWIN_EXPORT EffectFrame : public QObject
QFont m_font;
QPixmap m_icon;
QSize m_iconSize;
static GLTexture* m_unstyledTexture;
static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
};
/**

View file

@ -101,6 +101,13 @@ KWIN_EXPORT void renderGLGeometryImmediate( int count,
int dim = 2, int stride = 0 );
KWIN_EXPORT void addQuadVertices( QVector<float>& verts, float x1, float y1, float x2, float y2 );
/**
* @deprecated
* @see EffectFrame
*/
KWIN_EXPORT void renderRoundBox( const QRect& area, float roundness = 10.0f, GLTexture* texture = 0 );
/**
* @deprecated