Support for transparency.
svn path=/branches/work/kwin_composite/; revision=558690
This commit is contained in:
parent
f400646a6d
commit
c7f515630d
13 changed files with 315 additions and 64 deletions
20
client.cpp
20
client.cpp
|
@ -28,6 +28,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#include "atoms.h"
|
||||
#include "notifications.h"
|
||||
#include "rules.h"
|
||||
#include "scene.h"
|
||||
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <QX11Info>
|
||||
|
@ -279,6 +280,8 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
|
|||
workarea_diff_x = save_workarea_diff_x;
|
||||
workarea_diff_y = save_workarea_diff_y;
|
||||
do_show = true;
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
}
|
||||
else
|
||||
destroyDecoration();
|
||||
|
@ -305,6 +308,8 @@ void Client::destroyDecoration()
|
|||
move( grav );
|
||||
workarea_diff_x = save_workarea_diff_x;
|
||||
workarea_diff_y = save_workarea_diff_y;
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,16 +428,14 @@ void Client::setUserNoBorder( bool set )
|
|||
void Client::updateShape()
|
||||
{
|
||||
if ( shape() )
|
||||
{
|
||||
XShapeCombineShape(display(), frameId(), ShapeBounding,
|
||||
clientPos().x(), clientPos().y(),
|
||||
window(), ShapeBounding, ShapeSet);
|
||||
}
|
||||
else
|
||||
{
|
||||
XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0,
|
||||
None, ShapeSet);
|
||||
}
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
// workaround for #19644 - shaped windows shouldn't have decoration
|
||||
if( shape() && !noBorder())
|
||||
{
|
||||
|
@ -467,6 +470,8 @@ void Client::setMask( const QRegion& reg, int mode )
|
|||
xrects, rects.count(), ShapeSet, mode );
|
||||
delete[] xrects;
|
||||
}
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
}
|
||||
|
||||
QRegion Client::mask() const
|
||||
|
@ -1788,6 +1793,13 @@ bool Client::hasShape( Window w )
|
|||
return boundingShaped != 0;
|
||||
}
|
||||
|
||||
float Client::opacity() const
|
||||
{
|
||||
if( info->opacity() == 0xffffffff )
|
||||
return 1.0;
|
||||
return info->opacity() * 1.0 / 0xffffffff;
|
||||
}
|
||||
|
||||
void Client::debug( kdbgstream& stream ) const
|
||||
{
|
||||
stream << "\'ID:" << window() << ";WMCLASS:" << resourceClass() << ":" << resourceName() << ";Caption:" << caption() << "\'";
|
||||
|
|
2
client.h
2
client.h
|
@ -191,6 +191,8 @@ class Client
|
|||
// shape extensions
|
||||
bool shape() const;
|
||||
void updateShape();
|
||||
|
||||
virtual float opacity() const;
|
||||
|
||||
void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet );
|
||||
void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet );
|
||||
|
|
|
@ -47,11 +47,21 @@ void Workspace::finishCompositing()
|
|||
// TODO stop tracking unmanaged windows
|
||||
delete scene;
|
||||
scene = NULL;
|
||||
for( ClientList::ConstIterator it = clients.begin();
|
||||
it != clients.end();
|
||||
++it )
|
||||
{ // forward all opacity values to the frame in case there'll be other CM running
|
||||
if( (*it)->opacity() != 1.0 )
|
||||
{
|
||||
NETWinInfo i( display(), (*it)->frameId(), rootWindow(), 0 );
|
||||
i.setOpacity( long((*it)->opacity() * 0xffffffff ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::addDamage( const QRect& r )
|
||||
{
|
||||
addDamage( r.x(), r.y(), r.height(), r.width());
|
||||
addDamage( r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
void Workspace::addDamage( int x, int y, int w, int h )
|
||||
|
@ -64,28 +74,6 @@ void Workspace::addDamage( int x, int y, int w, int h )
|
|||
addDamage( XFixesCreateRegion( display(), &r, 1 ), true );
|
||||
}
|
||||
|
||||
struct XXX
|
||||
{
|
||||
XXX( XserverRegion r ) : rr( r ) {}
|
||||
XserverRegion rr;
|
||||
};
|
||||
|
||||
kdbgstream& operator<<( kdbgstream& stream, XXX r )
|
||||
{
|
||||
if( r.rr == None )
|
||||
return stream << "NONE";
|
||||
int num;
|
||||
XRectangle* rects = XFixesFetchRegion( display(), r.rr, &num );
|
||||
if( rects == NULL || num == 0 )
|
||||
return stream << "NONE";
|
||||
for( int i = 0;
|
||||
i < num;
|
||||
++i )
|
||||
stream << "[" << rects[ i ].x << "+" << rects[ i ].y << " " << rects[ i ].width << "x" << rects[ i ].height << "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void Workspace::addDamage( XserverRegion r, bool destroy )
|
||||
{
|
||||
if( !compositing())
|
||||
|
|
21
events.cpp
21
events.cpp
|
@ -22,6 +22,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#include "group.h"
|
||||
#include "rules.h"
|
||||
#include "unmanaged.h"
|
||||
#include "scene.h"
|
||||
|
||||
#include <QWhatsThis>
|
||||
#include <QApplication>
|
||||
|
@ -572,6 +573,19 @@ bool Client::windowEvent( XEvent* e )
|
|||
if( demandAttentionKNotifyTimer != NULL )
|
||||
demandAttentionKNotify();
|
||||
}
|
||||
if( dirty[ WinInfo::PROTOCOLS2 ] & NET::WM2Opacity )
|
||||
{
|
||||
if( compositing())
|
||||
{
|
||||
workspace()->addDamage( geometry());
|
||||
scene->windowOpacityChanged( this );
|
||||
}
|
||||
else
|
||||
{ // forward to the frame if there's possibly another compositing manager running
|
||||
NETWinInfo i( display(), frameId(), rootWindow(), 0 );
|
||||
i.setOpacity( info->opacity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO move all focus handling stuff to separate file?
|
||||
|
@ -1594,6 +1608,13 @@ void Client::keyPressEvent( uint key_code )
|
|||
|
||||
bool Unmanaged::windowEvent( XEvent* e )
|
||||
{
|
||||
unsigned long dirty[ 2 ];
|
||||
info->event( e, dirty, 2 ); // pass through the NET stuff
|
||||
if( dirty[ NETWinInfo::PROTOCOLS2 ] & NET::WM2Opacity )
|
||||
{
|
||||
scene->windowOpacityChanged( this );
|
||||
workspace()->addDamage( geometry());
|
||||
}
|
||||
switch (e->type)
|
||||
{
|
||||
case UnmapNotify:
|
||||
|
|
|
@ -53,6 +53,8 @@ bool Client::manage( Window w, bool isMapped )
|
|||
|
||||
embedClient( w, attr );
|
||||
|
||||
vis = attr.visual;
|
||||
|
||||
setupCompositing();
|
||||
|
||||
// SELI order all these things in some sane manner
|
||||
|
@ -82,6 +84,7 @@ bool Client::manage( Window w, bool isMapped )
|
|||
NET::WM2UserTime |
|
||||
NET::WM2StartupId |
|
||||
NET::WM2ExtendedStrut |
|
||||
NET::WM2Opacity |
|
||||
0;
|
||||
|
||||
info = new WinInfo( this, display(), client, rootWindow(), properties, 2 );
|
||||
|
|
12
scene.cpp
12
scene.cpp
|
@ -31,6 +31,18 @@ void Scene::setWindows( const ToplevelList& list )
|
|||
windows = list;
|
||||
}
|
||||
|
||||
void Scene::windowGeometryShapeChanged( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
||||
void Scene::windowOpacityChanged( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
||||
void Scene::windowDeleted( Toplevel* )
|
||||
{
|
||||
}
|
||||
|
||||
Scene* scene;
|
||||
|
||||
} // namespace
|
||||
|
|
3
scene.h
3
scene.h
|
@ -25,6 +25,9 @@ class Scene
|
|||
virtual ~Scene();
|
||||
void setWindows( const ToplevelList& list );
|
||||
virtual void paint( XserverRegion damage ) = 0;
|
||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
virtual void windowOpacityChanged( Toplevel* );
|
||||
virtual void windowDeleted( Toplevel* );
|
||||
protected:
|
||||
Workspace* wspace;
|
||||
ToplevelList windows;
|
||||
|
|
|
@ -35,6 +35,178 @@ SceneXrender::~SceneXrender()
|
|||
{
|
||||
XRenderFreePicture( display(), front );
|
||||
XRenderFreePicture( display(), buffer );
|
||||
for( QMap< Toplevel*, WindowData >::Iterator it = window_data.begin();
|
||||
it != window_data.end();
|
||||
++it )
|
||||
(*it).free();
|
||||
}
|
||||
|
||||
void SceneXrender::paint( XserverRegion damage )
|
||||
{
|
||||
// Use the damage region as the clip region for the root window
|
||||
XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
|
||||
// Client list for clients that are either translucent or have a shadow
|
||||
ToplevelList translucents;
|
||||
// Draw each opaque window top to bottom, subtracting the bounding rect of
|
||||
// each window from the clip region after it's been drawn.
|
||||
for( int i = windows.count() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
Toplevel* c = windows[ i ];
|
||||
checkWindowData( c );
|
||||
if( isOpaque( c ))
|
||||
{
|
||||
Picture picture = windowPicture( c );
|
||||
Picture shape = windowShape( c );
|
||||
if( picture != None && shape != None )
|
||||
{
|
||||
// Set the clip region for the buffer to the damage region, and
|
||||
// subtract the clients shape from the damage region
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XFixesSubtractRegion( display(), damage, damage, shape );
|
||||
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
||||
c->x(), c->y(), c->width(), c->height());
|
||||
}
|
||||
}
|
||||
saveWindowClipRegion( c, damage );
|
||||
translucents.prepend( c );
|
||||
}
|
||||
// Fill any areas of the root window not covered by windows
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
||||
// Now walk the list bottom to top, drawing translucent windows and shadows.
|
||||
// That we draw bottom to top is important now since we're drawing translucent objects.
|
||||
for( int i = 0;
|
||||
i < translucents.count();
|
||||
++i )
|
||||
{
|
||||
Toplevel* c = translucents[ i ];
|
||||
// Restore the previously saved clip region
|
||||
XserverRegion r = savedWindowClipRegion( c );
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, r );
|
||||
if( !isOpaque( c ))
|
||||
{
|
||||
Picture picture = windowPicture( c );
|
||||
Picture alpha = windowAlphaMask( c );
|
||||
if( picture != None )
|
||||
// TODO clip also using shape? also above?
|
||||
XRenderComposite( display(), PictOpOver, picture, alpha, buffer, 0, 0, 0, 0,
|
||||
c->x(), c->y(), c->width(), c->height());
|
||||
}
|
||||
XFixesDestroyRegion( display(), r );
|
||||
}
|
||||
// copy composed buffer to the root window
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
|
||||
XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
|
||||
XFlush( display());
|
||||
}
|
||||
|
||||
void SceneXrender::checkWindowData( Toplevel* c )
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
{
|
||||
window_data[ c ] = WindowData();
|
||||
window_data[ c ].format = XRenderFindVisualFormat( display(), c->visual());
|
||||
}
|
||||
}
|
||||
|
||||
void SceneXrender::windowGeometryShapeChanged( Toplevel* c )
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
return;
|
||||
WindowData& data = window_data[ c ];
|
||||
if( data.picture != None )
|
||||
XRenderFreePicture( display(), data.picture );
|
||||
data.picture = None;
|
||||
if( data.alpha != None )
|
||||
XRenderFreePicture( display(), data.alpha );
|
||||
data.alpha = None;
|
||||
if( data.shape != None )
|
||||
XRenderFreePicture( display(), data.shape );
|
||||
data.shape = None;
|
||||
}
|
||||
|
||||
void SceneXrender::windowOpacityChanged( Toplevel* c )
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
return;
|
||||
WindowData& data = window_data[ c ];
|
||||
if( data.alpha != None )
|
||||
XRenderFreePicture( display(), data.alpha );
|
||||
data.alpha = None;
|
||||
}
|
||||
|
||||
void SceneXrender::windowDeleted( Toplevel* c )
|
||||
{
|
||||
if( !window_data.contains( c ))
|
||||
return;
|
||||
window_data[ c ].free();
|
||||
window_data.remove( c );
|
||||
}
|
||||
|
||||
Picture SceneXrender::windowPicture( Toplevel* c )
|
||||
{
|
||||
WindowData& data = window_data[ c ];
|
||||
if( data.picture == None && data.format != NULL )
|
||||
data.picture = XRenderCreatePicture( display(), c->windowPixmap(), data.format, 0, 0 );
|
||||
return data.picture;
|
||||
}
|
||||
|
||||
void SceneXrender::saveWindowClipRegion( Toplevel* c, XserverRegion r )
|
||||
{
|
||||
WindowData& data = window_data[ c ];
|
||||
data.saved_clip_region = XFixesCreateRegion( display(), NULL, 0 );
|
||||
XFixesCopyRegion( display(), data.saved_clip_region, r );
|
||||
}
|
||||
|
||||
XserverRegion SceneXrender::savedWindowClipRegion( Toplevel* c )
|
||||
{ // always called after saveWindowClipRegion(), also resets
|
||||
WindowData& data = window_data[ c ];
|
||||
XserverRegion r = data.saved_clip_region;
|
||||
data.saved_clip_region = None;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool SceneXrender::isOpaque( Toplevel* c ) const
|
||||
{
|
||||
const WindowData& data = window_data[ c ];
|
||||
if( data.format->type == PictTypeDirect && data.format->direct.alphaMask )
|
||||
return false;
|
||||
if( c->opacity() != 1.0 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Picture SceneXrender::windowAlphaMask( Toplevel* c )
|
||||
{
|
||||
if( isOpaque( c ))
|
||||
return None;
|
||||
WindowData& data = window_data[ c ];
|
||||
if( data.alpha != None )
|
||||
return data.alpha;
|
||||
Pixmap pixmap = XCreatePixmap( display(), rootWindow(), 1, 1, 8 );
|
||||
XRenderPictFormat* format = XRenderFindStandardFormat( display(), PictStandardA8 );
|
||||
XRenderPictureAttributes pa;
|
||||
pa.repeat = True;
|
||||
data.alpha = XRenderCreatePicture( display(), pixmap, format, CPRepeat, &pa );
|
||||
XFreePixmap( display(), pixmap );
|
||||
XRenderColor col;
|
||||
col.alpha = int( c->opacity() * 0xffff );
|
||||
XRenderFillRectangle( display(), PictOpSrc, data.alpha, &col, 0, 0, 1, 1 );
|
||||
return data.alpha;
|
||||
}
|
||||
|
||||
Picture SceneXrender::windowShape( Toplevel* c )
|
||||
{
|
||||
WindowData& data = window_data[ c ];
|
||||
if( data.shape == None )
|
||||
{
|
||||
data.shape = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||
XFixesTranslateRegion( display(), data.shape, c->x(), c->y());
|
||||
}
|
||||
return data.shape;
|
||||
}
|
||||
|
||||
// TODO handle xrandr changes
|
||||
|
@ -48,43 +220,23 @@ void SceneXrender::createBuffer()
|
|||
XFreePixmap( display(), pixmap ); // The picture owns the pixmap now
|
||||
}
|
||||
|
||||
void SceneXrender::paint( XserverRegion damage )
|
||||
SceneXrender::WindowData::WindowData()
|
||||
: picture( None )
|
||||
, format( NULL )
|
||||
, saved_clip_region( None )
|
||||
, alpha( None )
|
||||
, shape( None )
|
||||
{
|
||||
// Use the damage region as the clip region for the root window
|
||||
XFixesSetPictureClipRegion( display(), front, 0, 0, damage );
|
||||
// Draw each opaque window top to bottom, subtracting the bounding rect of
|
||||
// each window from the clip region after it's been drawn.
|
||||
for( int i = windows.count() - 1;
|
||||
i >= 0;
|
||||
--i )
|
||||
{
|
||||
Toplevel* c = windows[ i ];
|
||||
XWindowAttributes attrs;
|
||||
if( !XGetWindowAttributes( display(), c->handle(), &attrs ))
|
||||
continue;
|
||||
if( XRenderPictFormat* clientFormat = XRenderFindVisualFormat( display(), attrs.visual ))
|
||||
{
|
||||
Picture picture = XRenderCreatePicture( display(), c->windowPixmap(), clientFormat, 0, 0 );
|
||||
// Set the clip region for the buffer to the damage region, and
|
||||
// subtract the clients shape from the damage region
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XserverRegion cr = XFixesCreateRegionFromWindow( display(), c->handle(), WindowRegionBounding );
|
||||
XFixesTranslateRegion( display(), cr, c->x(), c->y());
|
||||
XFixesSubtractRegion( display(), damage, damage, cr );
|
||||
XFixesDestroyRegion( display(), cr );
|
||||
XRenderComposite( display(), PictOpSrc, picture, None, buffer, 0, 0, 0, 0,
|
||||
c->x(), c->y(), c->width(), c->height());
|
||||
XRenderFreePicture( display(), picture );
|
||||
}
|
||||
}
|
||||
// fill background
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, damage );
|
||||
XRenderColor col = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
|
||||
// copy composed buffer to the root window
|
||||
XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
|
||||
XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
|
||||
XFlush( display());
|
||||
}
|
||||
|
||||
void SceneXrender::WindowData::free()
|
||||
{
|
||||
if( picture != None )
|
||||
XRenderFreePicture( display(), picture );
|
||||
if( alpha != None )
|
||||
XRenderFreePicture( display(), alpha );
|
||||
if( shape != None )
|
||||
XRenderFreePicture( display(), shape );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -28,11 +28,32 @@ class SceneXrender
|
|||
SceneXrender( Workspace* ws );
|
||||
virtual ~SceneXrender();
|
||||
virtual void paint( XserverRegion damage );
|
||||
virtual void windowGeometryShapeChanged( Toplevel* );
|
||||
virtual void windowOpacityChanged( Toplevel* );
|
||||
virtual void windowDeleted( Toplevel* );
|
||||
private:
|
||||
void createBuffer();
|
||||
void checkWindowData( Toplevel* c );
|
||||
Picture windowPicture( Toplevel* c );
|
||||
void saveWindowClipRegion( Toplevel* c, XserverRegion r );
|
||||
XserverRegion savedWindowClipRegion( Toplevel* c );
|
||||
bool isOpaque( Toplevel* c ) const;
|
||||
Picture windowAlphaMask( Toplevel* c );
|
||||
Picture windowShape( Toplevel* c );
|
||||
XRenderPictFormat* format;
|
||||
Picture front;
|
||||
Picture buffer;
|
||||
struct WindowData
|
||||
{
|
||||
WindowData();
|
||||
void free();
|
||||
Picture picture;
|
||||
XRenderPictFormat* format;
|
||||
XserverRegion saved_clip_region;
|
||||
Picture alpha;
|
||||
XserverRegion shape;
|
||||
};
|
||||
QMap< Toplevel*, WindowData > window_data;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -10,6 +10,8 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
|
||||
#include "toplevel.h"
|
||||
|
||||
#include "scene.h"
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
||||
|
@ -18,13 +20,16 @@ Toplevel::Toplevel( Workspace* ws )
|
|||
, wspace( ws )
|
||||
, damage_handle( None )
|
||||
, window_pixmap( None )
|
||||
, vis( None )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Toplevel::~Toplevel()
|
||||
{
|
||||
if( window_pixmap != None )
|
||||
XFreePixmap( display(), window_pixmap );
|
||||
if( scene != NULL )
|
||||
scene->windowDeleted( this );
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -40,6 +40,8 @@ class Toplevel
|
|||
int width() const;
|
||||
int height() const;
|
||||
Pixmap windowPixmap() const;
|
||||
Visual* visual() const;
|
||||
virtual float opacity() const = 0;
|
||||
protected:
|
||||
void setupCompositing();
|
||||
void finishCompositing();
|
||||
|
@ -47,6 +49,7 @@ class Toplevel
|
|||
void resetWindowPixmap();
|
||||
void damageNotifyEvent( XDamageNotifyEvent* e );
|
||||
QRect geom;
|
||||
Visual* vis;
|
||||
virtual void debug( kdbgstream& stream ) const = 0;
|
||||
friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* );
|
||||
private:
|
||||
|
@ -112,6 +115,11 @@ inline QRect Toplevel::rect() const
|
|||
return QRect( 0, 0, width(), height());
|
||||
}
|
||||
|
||||
inline Visual* Toplevel::visual() const
|
||||
{
|
||||
return vis;
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
inline
|
||||
kndbgstream& operator<<( kndbgstream& stream, const Toplevel* ) { return stream; }
|
||||
|
|
|
@ -17,11 +17,13 @@ namespace KWinInternal
|
|||
|
||||
Unmanaged::Unmanaged( Workspace* ws )
|
||||
: Toplevel( ws )
|
||||
, info( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
Unmanaged::~Unmanaged()
|
||||
{
|
||||
delete info;
|
||||
}
|
||||
|
||||
bool Unmanaged::track( Window w )
|
||||
|
@ -32,6 +34,17 @@ bool Unmanaged::track( Window w )
|
|||
return false;
|
||||
setHandle( w );
|
||||
geom = QRect( attr.x, attr.y, attr.width, attr.height );
|
||||
vis = attr.visual;
|
||||
unsigned long properties[ 2 ];
|
||||
properties[ NETWinInfo::PROTOCOLS ] =
|
||||
NET::WMWindowType |
|
||||
NET::WMPid |
|
||||
0;
|
||||
properties[ NETWinInfo::PROTOCOLS2 ] =
|
||||
NET::WM2Opacity |
|
||||
0;
|
||||
info = new NETWinInfo( display(), w, rootWindow(), properties, 2 );
|
||||
|
||||
setupCompositing();
|
||||
resetWindowPixmap();
|
||||
workspace()->addDamage( geometry());
|
||||
|
@ -50,6 +63,13 @@ void Unmanaged::deleteUnmanaged( Unmanaged* c, allowed_t )
|
|||
delete c;
|
||||
}
|
||||
|
||||
float Unmanaged::opacity() const
|
||||
{
|
||||
if( info->opacity() == 0xffffffff )
|
||||
return 1.0;
|
||||
return info->opacity() * 1.0 / 0xffffffff;
|
||||
}
|
||||
|
||||
void Unmanaged::debug( kdbgstream& stream ) const
|
||||
{
|
||||
stream << "\'ID:" << handle() << "\'";
|
||||
|
|
|
@ -11,6 +11,8 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#ifndef KWIN_UNMANAGED_H
|
||||
#define KWIN_UNMANAGED_H
|
||||
|
||||
#include <netwm.h>
|
||||
|
||||
#include "toplevel.h"
|
||||
|
||||
namespace KWinInternal
|
||||
|
@ -27,6 +29,7 @@ class Unmanaged
|
|||
void release();
|
||||
bool track( Window w );
|
||||
static void deleteUnmanaged( Unmanaged* c, allowed_t );
|
||||
virtual float opacity() const;
|
||||
protected:
|
||||
virtual void debug( kdbgstream& stream ) const;
|
||||
private:
|
||||
|
@ -34,6 +37,7 @@ class Unmanaged
|
|||
void mapNotifyEvent( XMapEvent* e );
|
||||
void unmapNotifyEvent( XUnmapEvent*e );
|
||||
void configureNotifyEvent( XConfigureEvent* e );
|
||||
NETWinInfo* info;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in a new issue