Make effects actual plugins, so it's possible to load them on runtime.

There's also a kwineffects library now, containing the effects API, which makes it possible to write
  third-party effects.
API isn't complete yet and for now just two effects have been converted but I'm working on it :-)

svn path=/branches/work/kwin_composite/; revision=652226
This commit is contained in:
Rivo Laks 2007-04-10 13:02:08 +00:00
parent 81f00aa8b8
commit 0353f3376e
30 changed files with 1891 additions and 1108 deletions

View file

@ -8,9 +8,25 @@ add_subdirectory( killer )
add_subdirectory( kcmkwin )
add_subdirectory( pics )
add_subdirectory( clients )
add_subdirectory( effects )
add_subdirectory( data )
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/lib ${CMAKE_CURRENT_SOURCE_DIR}/lib )
include_directories(
${CMAKE_CURRENT_BINARY_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/lib
${CMAKE_CURRENT_SOURCE_DIR}/effects
)
include(UsePkgConfig)
PKGCONFIG(libcaptury CAPTURY_INCLUDES CAPTURY_LINK_DIR CAPTURY_LDFLAGS CAPTURY_CFLAGS)
if( CAPTURY_LDFLAGS )
SET( CAPTURY_FOUND TRUE )
endif( CAPTURY_LDFLAGS )
macro_bool_to_01( CAPTURY_FOUND HAVE_CAPTURY )
configure_file(config-kwin.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kwin.h )
include_directories(${CMAKE_CURRENT_BINARY_DIR})
########### next target ###############
@ -37,28 +53,101 @@ set(kwin_KDEINIT_SRCS
activation.cpp
useractions.cpp
geometry.cpp
rules.cpp )
rules.cpp
composite.cpp
toplevel.cpp
unmanaged.cpp
scene.cpp
scene_basic.cpp
scene_xrender.cpp
scene_opengl.cpp
deleted.cpp
effects.cpp
)
qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml workspace.h KWin::Workspace )
kde4_automoc(${kwin_KDEINIT_SRCS})
kde4_automoc(kwin ${kwin_KDEINIT_SRCS})
kde4_add_kdeinit_executable( kwin ${kwin_KDEINIT_SRCS})
target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} kdecorations ${X11_LIBRARIES} ${QT_QT3SUPPORT_LIBRARY} )
target_link_libraries(kdeinit_kwin ${KDE4_KDEUI_LIBS} kdecorations kwineffects ${X11_LIBRARIES} ${QT_QT3SUPPORT_LIBRARY} )
if(OPENGL_FOUND)
target_link_libraries(kdeinit_kwin ${OPENGL_gl_LIBRARY})
# -ldl used by OpenGL code
target_link_libraries(kdeinit_kwin -ldl)
endif(OPENGL_FOUND)
if (X11_Xrandr_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xrandr_LIB})
endif (X11_Xrandr_FOUND)
if (X11_Xcomposite_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xcomposite_LIB})
endif (X11_Xcomposite_FOUND)
if (X11_Xdamage_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xdamage_LIB})
endif (X11_Xdamage_FOUND)
if (X11_Xrender_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xrender_LIB})
endif (X11_Xrender_FOUND)
if (X11_Xfixes_FOUND)
target_link_libraries(kdeinit_kwin ${X11_Xfixes_LIB})
endif (X11_Xfixes_FOUND)
if( HAVE_CAPTURY )
target_link_libraries(kdeinit_kwin ${CAPTURY_LDFLAGS})
endif( HAVE_CAPTURY )
install(TARGETS kdeinit_kwin DESTINATION ${LIB_INSTALL_DIR} )
target_link_libraries( kwin kdeinit_kwin )
install(TARGETS kwin DESTINATION ${BIN_INSTALL_DIR})
install(TARGETS kwin DESTINATION bin)
########### install files ###############
install( FILES kwin.kcfg DESTINATION ${KCFG_INSTALL_DIR} )
install( FILES kwin.notifyrc DESTINATION ${DATA_INSTALL_DIR}/kwin )
install( FILES org.kde.KWin.xml DESTINATION ${DBUS_INTERFACES_DIR} )
kde4_install_icons( ${ICON_INSTALL_DIR} )
install( FILES effects/data/explosion.frag effects/data/explosion.vert effects/data/explosion-start.png effects/data/explosion-end.png DESTINATION ${DATA_INSTALL_DIR}/kwin )
kde4_install_icons( ${ICON_INSTALL_DIR} crystalsvg )
#original Makefile.am contents follow:
#INCLUDES = -I$(srcdir)/lib $(all_includes)
#
#SUBDIRS = lib . killer kcmkwin pics clients oldheaders data
#
#bin_PROGRAMS =
#lib_LTLIBRARIES =
#kdeinit_LTLIBRARIES = kwin.la
#
#kwin_la_SOURCES = workspace.cpp client.cpp placement.cpp atoms.cpp \
# utils.cpp layers.cpp main.cpp popupinfo.cpp tabbox.cpp \
# options.cpp plugins.cpp events.cpp KWinInterface.skel \
# killwindow.cpp geometrytip.cpp sm.cpp group.cpp bridge.cpp \
# manage.cpp notifications.cpp activation.cpp useractions.cpp \
# geometry.cpp rules.cpp
#
#kwin_la_LIBADD = $(LIB_KDEUI) lib/libkdecorations.la
#kwin_la_LDFLAGS = $(all_libraries) -module -avoid-version
#
#include_HEADERS = KWinInterface.h
#
#KDE_ICON = kwin
#
#METASOURCES = AUTO
#
#messages: rc.cpp
# $(XGETTEXT) *.h *.cpp killer/*.cpp lib/*.cpp -o $(podir)/kwin.pot
#
#kwin_datadir = $(kde_datadir)/kwin
#
#kwin_data_DATA= eventsrc
#
#kde_kcfg_DATA = kwin.kcfg
#
#include ../../admin/Doxyfile.am

View file

@ -120,7 +120,7 @@ void Workspace::setupCompositing()
compositeTimer.start( compositeRate );
lastCompositePaint.start();
XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual );
new EffectsHandler(); // sets also the 'effects' pointer
new EffectsHandlerImpl( scene->compositingType() ); // sets also the 'effects' pointer
addRepaintFull();
foreach( Client* c, clients )
c->setupCompositing();
@ -338,7 +338,7 @@ void Toplevel::setupCompositing()
return;
damage_handle = XDamageCreate( display(), frameId(), XDamageReportRawRectangles );
damage_region = QRegion( 0, 0, width(), height());
effect_window = new EffectWindow();
effect_window = new EffectWindowImpl();
effect_window->setWindow( this );
#endif
}

View file

@ -10,336 +10,38 @@ License. See the file "COPYING" for the exact licensing terms.
#include "effects.h"
#include "toplevel.h"
#include "client.h"
#include "scene.h"
#include "options.h"
#include "deleted.h"
#include "client.h"
#include "workspace.h"
#include "effects/boxswitch.h"
#include "effects/demo_taskbarthumbnail.h"
#include "effects/desktopchangeslide.h"
#include "effects/dialogparent.h"
#include "effects/drunken.h"
#include "effects/explosioneffect.h"
#include "effects/fade.h"
#include "effects/howto.h"
#include "effects/maketransparent.h"
#include "effects/minimizeanimation.h"
#include "effects/presentwindows.h"
#include "effects/scalein.h"
#include "effects/shadow.h"
#include "effects/shakymove.h"
#include "effects/shiftworkspaceup.h"
#include "effects/showfps.h"
#ifdef HAVE_CAPTURY
#include "effects/videorecord.h"
#endif
#ifdef HAVE_OPENGL
#include "effects/flame.h"
#include "effects/fallapart.h"
#include "effects/wavywindows.h"
#endif
#include "effects/zoom.h"
#include "kdebug.h"
#include <assert.h>
#include "effects/test_input.h"
#include "effects/test_thumbnail.h"
namespace KWin
{
//****************************************
// Effect
//****************************************
Effect::~Effect()
EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type) : EffectsHandler(type)
{
foreach( const QString& effect, options->defaultEffects )
loadEffect( effect );
}
void Effect::windowUserMovedResized( EffectWindow* , bool, bool )
{
}
void Effect::windowOpacityChanged( EffectWindow*, double )
{
}
void Effect::windowAdded( EffectWindow* )
{
}
void Effect::windowClosed( EffectWindow* )
{
}
void Effect::windowDeleted( EffectWindow* )
{
}
void Effect::windowActivated( EffectWindow* )
{
}
void Effect::windowMinimized( EffectWindow* )
{
}
void Effect::windowUnminimized( EffectWindow* )
{
}
void Effect::windowInputMouseEvent( Window, QEvent* )
{
}
void Effect::desktopChanged( int )
{
}
void Effect::windowDamaged( EffectWindow*, const QRect& )
{
}
void Effect::windowGeometryShapeChanged( EffectWindow*, const QRect& )
{
}
void Effect::tabBoxAdded( int )
{
}
void Effect::tabBoxClosed()
{
}
void Effect::tabBoxUpdated()
{
}
bool Effect::borderActivated( ElectricBorder )
{
return false;
}
void Effect::prePaintScreen( int* mask, QRegion* region, int time )
{
effects->prePaintScreen( mask, region, time );
}
void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
effects->paintScreen( mask, region, data );
}
void Effect::postPaintScreen()
{
effects->postPaintScreen();
}
void Effect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
effects->prePaintWindow( w, mask, paint, clip, time );
}
void Effect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
effects->paintWindow( w, mask, region, data );
}
void Effect::postPaintWindow( EffectWindow* w )
{
effects->postPaintWindow( w );
}
void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
effects->drawWindow( w, mask, region, data );
}
QRect Effect::transformWindowDamage( EffectWindow* w, const QRect& r )
{
return effects->transformWindowDamage( w, r );
}
void Effect::setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
const QRect& r, Qt::AspectRatioMode aspect )
{
QSize size = w->size();
size.scale( r.size(), aspect );
data.xScale = size.width() / double( w->width());
data.yScale = size.height() / double( w->height());
int width = int( w->width() * data.xScale );
int height = int( w->height() * data.yScale );
int x = r.x() + ( r.width() - width ) / 2;
int y = r.y() + ( r.height() - height ) / 2;
region = QRect( x, y, width, height );
data.xTranslate = x - w->x();
data.yTranslate = y - w->y();
}
//****************************************
// EffectsHandler
//****************************************
EffectsHandler::EffectsHandler()
: current_paint_screen( 0 )
, current_paint_window( 0 )
, current_draw_window( 0 )
, current_transform( 0 )
{
if( !compositing())
return;
KWin::effects = this;
#ifdef HAVE_CAPTURY
registerEffect("VideoRecord", new GenericEffectFactory<VideoRecordEffect>);
#endif
registerEffect("ShowFps", new GenericEffectFactory<ShowFpsEffect>);
registerEffect("Zoom", new GenericEffectFactory<ZoomEffect>);
registerEffect("PresentWindows", new GenericEffectFactory<PresentWindowsEffect>);
#ifdef HAVE_OPENGL
registerEffect("WavyWindows", new GenericEffectFactory<WavyWindowsEffect>);
registerEffect("Explosion", new GenericEffectFactory<ExplosionEffect>);
#endif
registerEffect("MinimizeAnimation", new GenericEffectFactory<MinimizeAnimationEffect>);
registerEffect("Howto", new GenericEffectFactory<HowtoEffect>);
registerEffect("MakeTransparent", new GenericEffectFactory<MakeTransparentEffect>);
registerEffect("ShakyMove", new GenericEffectFactory<ShakyMoveEffect>);
registerEffect("ShiftWorkspaceUp", new GenericEffectFactory<ShiftWorkspaceUpEffect>);
registerEffect("Fade", new GenericEffectFactory<FadeEffect>);
registerEffect("ScaleIn", new GenericEffectFactory<ScaleInEffect>);
registerEffect("FallApart", new GenericEffectFactory<FallApartEffect>);
registerEffect("Flame", new GenericEffectFactory<FlameEffect>);
registerEffect("DialogParent", new GenericEffectFactory<DialogParentEffect>);
registerEffect("DesktopChangeSlide", new GenericEffectFactory<DesktopChangeSlideEffect>);
registerEffect("BoxSwitch", new GenericEffectFactory<BoxSwitchEffect>);
registerEffect("Drunken", new GenericEffectFactory<DrunkenEffect>);
registerEffect("TaskbarThumbnail", new GenericEffectFactory<TaskbarThumbnailEffect>);
registerEffect("Shadow", new GenericEffectFactory<ShadowEffect>);
registerEffect("TestInput", new GenericEffectFactory<TestInputEffect>);
registerEffect("TestThumbnail", new GenericEffectFactory<TestThumbnailEffect>);
QStringList::const_iterator effectsIterator;
for( effectsIterator = options->defaultEffects.constBegin();
effectsIterator != options->defaultEffects.constEnd();
++effectsIterator)
{
loadEffect(*effectsIterator);
}
}
EffectsHandler::~EffectsHandler()
EffectsHandlerImpl::~EffectsHandlerImpl()
{
// Can't be done in EffectsHandler since it would result in pure virtuals
// being called
foreach( EffectPair ep, loaded_effects )
delete ep.second;
foreach( EffectFactory* ef, effect_factories )
delete ef;
unloadEffect( ep.first );
foreach( InputWindowPair pos, input_windows )
XDestroyWindow( display(), pos.second );
}
void EffectsHandler::windowUserMovedResized( EffectWindow* c, bool first, bool last )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowUserMovedResized( c, first, last );
}
void EffectsHandler::windowOpacityChanged( EffectWindow* c, double old_opacity )
{
if( c->window()->opacity() == old_opacity )
return;
foreach( EffectPair ep, loaded_effects )
ep.second->windowOpacityChanged( c, old_opacity );
}
void EffectsHandler::windowAdded( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowAdded( c );
}
void EffectsHandler::windowDeleted( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowDeleted( c );
}
void EffectsHandler::windowClosed( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowClosed( c );
}
void EffectsHandler::windowActivated( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowActivated( c );
}
void EffectsHandler::windowMinimized( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowMinimized( c );
}
void EffectsHandler::windowUnminimized( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowUnminimized( c );
}
void EffectsHandler::desktopChanged( int old )
{
foreach( EffectPair ep, loaded_effects )
ep.second->desktopChanged( old );
}
void EffectsHandler::windowDamaged( EffectWindow* w, const QRect& r )
{
if( w == NULL )
return;
foreach( EffectPair ep, loaded_effects )
ep.second->windowDamaged( w, r );
}
void EffectsHandler::windowGeometryShapeChanged( EffectWindow* w, const QRect& old )
{
if( w == NULL ) // during late cleanup effectWindow() may be already NULL
return; // in some functions that may still call this
foreach( EffectPair ep, loaded_effects )
ep.second->windowGeometryShapeChanged( w, old );
}
void EffectsHandler::tabBoxAdded( int mode )
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxAdded( mode );
}
void EffectsHandler::tabBoxClosed()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxClosed();
}
void EffectsHandler::tabBoxUpdated()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxUpdated();
}
// start another painting pass
void EffectsHandler::startPaint()
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
}
// the idea is that effects call this function again which calls the next one
void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
void EffectsHandlerImpl::prePaintScreen( int* mask, QRegion* region, int time )
{
if( current_paint_screen < loaded_effects.size())
{
@ -349,7 +51,7 @@ void EffectsHandler::prePaintScreen( int* mask, QRegion* region, int time )
// no special final code
}
void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& data )
void EffectsHandlerImpl::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( current_paint_screen < loaded_effects.size())
{
@ -360,7 +62,7 @@ void EffectsHandler::paintScreen( int mask, QRegion region, ScreenPaintData& dat
scene->finalPaintScreen( mask, region, data );
}
void EffectsHandler::postPaintScreen()
void EffectsHandlerImpl::postPaintScreen()
{
if( current_paint_screen < loaded_effects.size())
{
@ -370,7 +72,7 @@ void EffectsHandler::postPaintScreen()
// no special final code
}
void EffectsHandler::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
void EffectsHandlerImpl::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( current_paint_window < loaded_effects.size())
{
@ -380,7 +82,7 @@ void EffectsHandler::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint,
// no special final code
}
void EffectsHandler::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
void EffectsHandlerImpl::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( current_paint_window < loaded_effects.size())
{
@ -388,10 +90,10 @@ void EffectsHandler::paintWindow( EffectWindow* w, int mask, QRegion region, Win
--current_paint_window;
}
else
scene->finalPaintWindow( w, mask, region, data );
scene->finalPaintWindow( static_cast<EffectWindowImpl*>( w ), mask, region, data );
}
void EffectsHandler::postPaintWindow( EffectWindow* w )
void EffectsHandlerImpl::postPaintWindow( EffectWindow* w )
{
if( current_paint_window < loaded_effects.size())
{
@ -401,7 +103,7 @@ void EffectsHandler::postPaintWindow( EffectWindow* w )
// no special final code
}
void EffectsHandler::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
void EffectsHandlerImpl::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( current_draw_window < loaded_effects.size())
{
@ -409,38 +111,69 @@ void EffectsHandler::drawWindow( EffectWindow* w, int mask, QRegion region, Wind
--current_draw_window;
}
else
scene->finalDrawWindow( w, mask, region, data );
scene->finalDrawWindow( static_cast<EffectWindowImpl*>( w ), mask, region, data );
}
QRect EffectsHandler::transformWindowDamage( EffectWindow* w, const QRect& r )
void EffectsHandlerImpl::windowOpacityChanged( EffectWindow* c, double old_opacity )
{
if( current_transform < loaded_effects.size())
{
QRect rr = loaded_effects[current_transform++].second->transformWindowDamage( w, r );
--current_transform;
return rr;
}
else
return r;
if( static_cast<EffectWindowImpl*>(c)->window()->opacity() == old_opacity )
return;
EffectsHandler::windowOpacityChanged( c, old_opacity );
}
bool EffectsHandler::borderActivated( ElectricBorder border )
void EffectsHandlerImpl::activateWindow( EffectWindow* c )
{
bool ret = false;
foreach( EffectPair ep, loaded_effects )
if( ep.second->borderActivated( border ))
ret = true; // bail out or tell all?
if( Client* cl = dynamic_cast< Client* >( static_cast<EffectWindowImpl*>(c)->window()))
Workspace::self()->activateClient( cl, true );
}
int EffectsHandlerImpl::currentDesktop() const
{
return Workspace::self()->currentDesktop();
}
int EffectsHandlerImpl::displayWidth() const
{
return KWin::displayWidth();
}
int EffectsHandlerImpl::displayHeight() const
{
return KWin::displayWidth();
}
QPoint EffectsHandlerImpl::cursorPos() const
{
return KWin::cursorPos();
}
EffectWindowList EffectsHandlerImpl::stackingOrder() const
{
ClientList list = Workspace::self()->stackingOrder();
EffectWindowList ret;
foreach( Client* c, list )
ret.append( effectWindow( c ));
return ret;
}
}
Window EffectsHandler::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor )
void EffectsHandlerImpl::addRepaintFull()
{
Workspace::self()->addRepaintFull();
}
QRect EffectsHandlerImpl::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
{
return Workspace::self()->clientArea( opt, p, desktop );
}
Window EffectsHandlerImpl::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor )
{
XSetWindowAttributes attrs;
attrs.override_redirect = True;
Window win = XCreateWindow( display(), rootWindow(), x, y, w, h, 0, 0, InputOnly, CopyFromParent,
CWOverrideRedirect, &attrs );
// TODO keeping on top?
// TODO enter/leave notify?
// TODO keeping on top?
// TODO enter/leave notify?
XSelectInput( display(), win, ButtonPressMask | ButtonReleaseMask | PointerMotionMask );
XDefineCursor( display(), win, cursor.handle());
XMapWindow( display(), win );
@ -448,12 +181,7 @@ Window EffectsHandler::createInputWindow( Effect* e, int x, int y, int w, int h,
return win;
}
Window EffectsHandler::createInputWindow( Effect* e, const QRect& r, const QCursor& cursor )
{
return createInputWindow( e, r.x(), r.y(), r.width(), r.height(), cursor );
}
void EffectsHandler::destroyInputWindow( Window w )
void EffectsHandlerImpl::destroyInputWindow( Window w )
{
foreach( InputWindowPair pos, input_windows )
{
@ -467,7 +195,7 @@ void EffectsHandler::destroyInputWindow( Window w )
assert( false );
}
bool EffectsHandler::checkInputWindowEvent( XEvent* e )
bool EffectsHandlerImpl::checkInputWindowEvent( XEvent* e )
{
if( e->type != ButtonPress && e->type != ButtonRelease && e->type != MotionNotify )
return false;
@ -501,8 +229,7 @@ bool EffectsHandler::checkInputWindowEvent( XEvent* e )
}
return false;
}
void EffectsHandler::checkInputWindowStacking()
void EffectsHandlerImpl::checkInputWindowStacking()
{
if( input_windows.count() == 0 )
return;
@ -515,130 +242,242 @@ void EffectsHandler::checkInputWindowStacking()
delete[] wins;
}
void EffectsHandler::activateWindow( EffectWindow* c )
{
if( Client* cl = dynamic_cast< Client* >( c->window()))
Workspace::self()->activateClient( cl, true );
}
void EffectsHandlerImpl::checkElectricBorder(const QPoint &pos, Time time)
{
Workspace::self()->checkElectricBorder( pos, time );
}
void EffectsHandler::registerEffect( const QString& name, EffectFactory* factory )
{
QHash<QString, EffectFactory*>::const_iterator factories_iterator = effect_factories.find(name);
if( factories_iterator != effect_factories.end() )
{
kDebug( 1212 ) << "EffectsHandler::registerEffect : Effect name already registered : " << name << endl;
}
else
{
kDebug( 1212 ) << "EffectsHandler::registerEffect : Register effect : " << name << endl;
effect_factories[name] = factory;
}
}
void EffectsHandlerImpl::reserveElectricBorder( ElectricBorder border )
{
Workspace::self()->reserveElectricBorder( border );
}
void EffectsHandler::loadEffect( const QString& name )
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); it++)
{
if( (*it).first == name )
{
kDebug( 1212 ) << "EffectsHandler::loadEffect : Effect already loaded : " << name << endl;
return;
}
}
QHash<QString, EffectFactory*>::const_iterator factories_iterator = effect_factories.find(name);
if( factories_iterator != effect_factories.end() )
{
kDebug( 1212 ) << "EffectsHandler::loadEffect : Loading effect : " << name << endl;
loaded_effects.append( EffectPair( name, factories_iterator.value()->create() ) );
}
else
{
kDebug( 1212 ) << "EffectsHandler::loadEffect : Unknown effect : " << name << endl;
}
}
void EffectsHandler::unloadEffect( const QString& name )
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); it++)
{
if ( (*it).first == name )
{
kDebug( 1212 ) << "EffectsHandler::unloadEffect : Unloading Effect : " << name << endl;
delete (*it).second;
loaded_effects.erase(it);
return;
}
}
kDebug( 1212 ) << "EffectsHandler::unloadEffect : Effect not loaded : " << name << endl;
}
EffectFactory::~EffectFactory()
{
}
int EffectsHandler::currentDesktop() const
{
return Workspace::self()->currentDesktop();
}
EffectsHandler* effects;
void EffectsHandlerImpl::unreserveElectricBorder( ElectricBorder border )
{
Workspace::self()->unreserveElectricBorder( border );
}
void EffectsHandlerImpl::reserveElectricBorderSwitching( bool reserve )
{
Workspace::self()->reserveElectricBorderSwitching( reserve );
}
//****************************************
// EffectWindow
// EffectWindowImpl
//****************************************
EffectWindow::EffectWindow()
: toplevel( NULL )
EffectWindowImpl::EffectWindowImpl() : EffectWindow()
, toplevel( NULL )
, sw( NULL )
{
}
void EffectWindow::enablePainting( int reason )
EffectWindowImpl::~EffectWindowImpl()
{
}
void EffectWindowImpl::enablePainting( int reason )
{
sceneWindow()->enablePainting( reason );
}
void EffectWindow::disablePainting( int reason )
void EffectWindowImpl::disablePainting( int reason )
{
sceneWindow()->disablePainting( reason );
}
int EffectWindow::desktop() const
int EffectWindowImpl::desktop() const
{
return toplevel->desktop();
}
bool EffectWindow::isOnCurrentDesktop() const
{
return isOnDesktop( effects->currentDesktop());
}
bool EffectWindow::isOnAllDesktops() const
bool EffectWindowImpl::isOnAllDesktops() const
{
return desktop() == NET::OnAllDesktops;
}
bool EffectWindow::isOnDesktop( int d ) const
QString EffectWindowImpl::caption() const
{
return desktop() == d || isOnAllDesktops();
if( Client* c = dynamic_cast<Client*>( toplevel ))
return c->caption();
else
return "";
}
bool EffectWindow::isDeleted() const
{
bool EffectWindowImpl::isMinimized() const
{
if( Client* c = dynamic_cast<Client*>( toplevel ))
return c->isMinimized();
else
return false;
}
bool EffectWindowImpl::isDeleted() const
{
return (dynamic_cast<Deleted*>( toplevel ) != 0);
}
}
const Toplevel* EffectWindowImpl::window() const
{
return toplevel;
}
Toplevel* EffectWindowImpl::window()
{
return toplevel;
}
void EffectWindowImpl::setWindow( Toplevel* w )
{
toplevel = w;
}
void EffectWindowImpl::setSceneWindow( Scene::Window* w )
{
sw = w;
}
Scene::Window* EffectWindowImpl::sceneWindow()
{
return sw;
}
int EffectWindowImpl::x() const
{
return toplevel->x();
}
int EffectWindowImpl::y() const
{
return toplevel->y();
}
int EffectWindowImpl::width() const
{
return toplevel->width();
}
int EffectWindowImpl::height() const
{
return toplevel->height();
}
QRect EffectWindowImpl::geometry() const
{
return toplevel->geometry();
}
QSize EffectWindowImpl::size() const
{
return toplevel->size();
}
QPoint EffectWindowImpl::pos() const
{
return toplevel->pos();
}
QRect EffectWindowImpl::rect() const
{
return toplevel->rect();
}
bool EffectWindowImpl::isDesktop() const
{
return toplevel->isDesktop();
}
bool EffectWindowImpl::isDock() const
{
return toplevel->isDock();
}
bool EffectWindowImpl::isToolbar() const
{
return toplevel->isToolbar();
}
bool EffectWindowImpl::isTopMenu() const
{
return toplevel->isTopMenu();
}
bool EffectWindowImpl::isMenu() const
{
return toplevel->isMenu();
}
bool EffectWindowImpl::isNormalWindow() const
{
return toplevel->isNormalWindow();
}
bool EffectWindowImpl::isSpecialWindow() const
{
if( Client* c = dynamic_cast<Client*>( toplevel ))
return c->isSpecialWindow();
else
return false;
}
bool EffectWindowImpl::isDialog() const
{
return toplevel->isDialog();
}
bool EffectWindowImpl::isSplash() const
{
return toplevel->isSplash();
}
bool EffectWindowImpl::isUtility() const
{
return toplevel->isUtility();
}
bool EffectWindowImpl::isDropdownMenu() const
{
return toplevel->isDropdownMenu();
}
bool EffectWindowImpl::isPopupMenu() const
{
return toplevel->isPopupMenu();
}
bool EffectWindowImpl::isTooltip() const
{
return toplevel->isTooltip();
}
bool EffectWindowImpl::isNotification() const
{
return toplevel->isNotification();
}
bool EffectWindowImpl::isComboBox() const
{
return toplevel->isComboBox();
}
bool EffectWindowImpl::isDNDIcon() const
{
return toplevel->isDNDIcon();
}
EffectWindow* effectWindow( Toplevel* w )
{
EffectWindowImpl* ret = w->effectWindow();
ret->setSceneWindow( NULL ); // just in case
return ret;
}
EffectWindow* effectWindow( Scene::Window* w )
{
EffectWindowImpl* ret = w->window()->effectWindow();
ret->setSceneWindow( w );
return ret;
}
} // namespace

473
effects.h
View file

@ -8,231 +8,98 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
// TODO MIT or some other licence, perhaps move to some lib
#ifndef KWIN_EFFECTSIMPL_H
#define KWIN_EFFECTSIMPL_H
#ifndef KWIN_EFFECTS_H
#define KWIN_EFFECTS_H
#include "kwineffects.h"
#include "scene.h"
#include <qpair.h>
namespace KWin
{
class Toplevel;
class Workspace;
class EffectWindow;
class WindowPaintData
{
class EffectsHandlerImpl : public EffectsHandler
{
public:
WindowPaintData();
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
*/
double opacity;
double xScale;
double yScale;
int xTranslate;
int yTranslate;
/**
* Saturation of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* unsaturated (greyscale). 0.5 would make the colors less intense,
* but not completely grey
**/
float saturation;
/**
* Brightness of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* black. 0.5 would make it 50% darker than usual
**/
float brightness;
};
class ScreenPaintData
{
public:
ScreenPaintData();
double xScale;
double yScale;
int xTranslate;
int yTranslate;
};
class Effect
: public KDecorationDefines
{
public:
virtual ~Effect();
EffectsHandlerImpl(CompositingType type);
virtual ~EffectsHandlerImpl();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
// paintWindow() can do various transformations
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// drawWindow() is used even for thumbnails etc. - it can alter the window itself where it
// makes sense (e.g.darkening out unresponsive windows), but it cannot do transformations
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
// This function is used e.g. by the shadow effect which adds area around windows
// that needs to be painted as well - e.g. when a window is hidden and the workspace needs
// to be repainted at that area, shadow's transformWindowDamage() adds the shadow area
// to it, so that it is repainted as well.
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// called when moved/resized or once after it's finished
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
virtual void windowAdded( EffectWindow* c );
virtual void windowClosed( EffectWindow* c );
virtual void windowDeleted( EffectWindow* c );
virtual void windowActivated( EffectWindow* c );
virtual void windowMinimized( EffectWindow* c );
virtual void windowUnminimized( EffectWindow* c );
virtual void windowInputMouseEvent( Window w, QEvent* e );
virtual void desktopChanged( int old );
virtual void windowDamaged( EffectWindow* w, const QRect& r );
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
virtual void tabBoxAdded( int mode );
virtual void tabBoxClosed();
virtual void tabBoxUpdated();
virtual bool borderActivated( ElectricBorder border );
virtual void activateWindow( EffectWindow* c );
// Interpolates between x and y
static float interpolate(float x, float y, float a)
{
return x * (1 - a) + y * a;
}
// helper to set WindowPaintData and QRegion to necessary transformations so that
// a following drawWindow() would put the window at the requested geometry (useful for thumbnails)
static void setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
const QRect& r, Qt::AspectRatioMode aspect );
virtual int currentDesktop() const;
virtual int displayWidth() const;
virtual int displayHeight() const;
virtual QPoint cursorPos() const;
virtual EffectWindowList stackingOrder() const;
virtual void addRepaintFull();
virtual QRect clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const;
protected:
Workspace* workspace() const;
};
virtual Window createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor );
virtual void destroyInputWindow( Window w );
virtual bool checkInputWindowEvent( XEvent* e );
virtual void checkInputWindowStacking();
class EffectFactory
{
virtual void checkElectricBorder(const QPoint &pos, Time time);
virtual void reserveElectricBorder( ElectricBorder border );
virtual void unreserveElectricBorder( ElectricBorder border );
virtual void reserveElectricBorderSwitching( bool reserve );
};
class EffectWindowImpl : public EffectWindow
{
public:
// only here to avoid warnings
virtual ~EffectFactory();
EffectWindowImpl();
virtual ~EffectWindowImpl();
virtual Effect* create() const = 0;
};
virtual void enablePainting( int reason );
virtual void disablePainting( int reason );
template <class EFFECT>
class GenericEffectFactory : public EffectFactory
{
virtual Effect* create() const
{
return new EFFECT();
}
};
virtual bool isDeleted() const;
virtual bool isOnAllDesktops() const;
virtual int desktop() const; // prefer isOnXXX()
virtual bool isMinimized() const;
virtual QString caption() const;
class EffectsHandler
: public KDecorationDefines
{
friend class Effect;
public:
EffectsHandler();
~EffectsHandler();
// for use by effects
void prePaintScreen( int* mask, QRegion* region, int time );
void paintScreen( int mask, QRegion region, ScreenPaintData& data );
void postPaintScreen();
void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
void postPaintWindow( EffectWindow* w );
void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// Functions for handling input - e.g. when an Expose-like effect is shown, an input window
// covering the whole screen is created and all mouse events will be intercepted by it.
// The effect's windowInputMouseEvent() will get called with such events.
Window createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor );
Window createInputWindow( Effect* e, const QRect& r, const QCursor& cursor );
void destroyInputWindow( Window w );
// functions that allow controlling windows/desktop
void activateWindow( EffectWindow* c );
//
int currentDesktop() const;
// internal (used by kwin core or compositing code)
void startPaint();
void windowUserMovedResized( EffectWindow* c, bool first, bool last );
void windowOpacityChanged( EffectWindow* c, double old_opacity );
void windowAdded( EffectWindow* c );
void windowClosed( EffectWindow* c );
void windowDeleted( EffectWindow* c );
void windowActivated( EffectWindow* c );
void windowMinimized( EffectWindow* c );
void windowUnminimized( EffectWindow* c );
bool checkInputWindowEvent( XEvent* e );
void checkInputWindowStacking();
void desktopChanged( int old );
void windowDamaged( EffectWindow* w, const QRect& r );
void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
void tabBoxAdded( int mode );
void tabBoxClosed();
void tabBoxUpdated();
bool borderActivated( ElectricBorder border );
virtual int x() const;
virtual int y() const;
virtual int width() const;
virtual int height() const;
virtual QRect geometry() const;
virtual QPoint pos() const;
virtual QSize size() const;
virtual QRect rect() const;
void registerEffect( const QString& name, EffectFactory* factory );
void loadEffect( const QString& name );
void unloadEffect( const QString& name );
virtual bool isDesktop() const;
virtual bool isDock() const;
virtual bool isToolbar() const;
virtual bool isTopMenu() const;
virtual bool isMenu() const;
virtual bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient'
virtual bool isSpecialWindow() const;
virtual bool isDialog() const;
virtual bool isSplash() const;
virtual bool isUtility() const;
virtual bool isDropdownMenu() const;
virtual bool isPopupMenu() const; // a context popup, not dropdown, not torn-off
virtual bool isTooltip() const;
virtual bool isNotification() const;
virtual bool isComboBox() const;
virtual bool isDNDIcon() const;
private:
typedef QPair< QString, Effect* > EffectPair;
QVector< EffectPair > loaded_effects;
typedef QPair< Effect*, Window > InputWindowPair;
QList< InputWindowPair > input_windows;
QHash< QString, EffectFactory* > effect_factories;
int current_paint_screen;
int current_paint_window;
int current_draw_window;
int current_transform;
};
// This class is a representation of a window used by/for Effect classes.
// The purpose is to hide internal data and also to serve as a single
// representation for the case when Client/Unmanaged becomes Deleted.
class EffectWindow
{
public:
EffectWindow();
const Toplevel* window() const;
Toplevel* window();
void enablePainting( int reason );
void disablePainting( int reason );
bool isDeleted() const;
bool isOnDesktop( int d ) const;
bool isOnCurrentDesktop() const;
bool isOnAllDesktops() const;
int desktop() const; // prefer isOnXXX()
int x() const;
int y() const;
int width() const;
int height() const;
QRect geometry() const;
QPoint pos() const;
QSize size() const;
QRect rect() const;
bool isDesktop() const;
bool isDock() const;
bool isToolbar() const;
bool isTopMenu() const;
bool isMenu() const;
bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient'
bool isDialog() const;
bool isSplash() const;
bool isUtility() const;
bool isDropdownMenu() const;
bool isPopupMenu() const; // a context popup, not dropdown, not torn-off
bool isTooltip() const;
bool isNotification() const;
bool isComboBox() const;
bool isDNDIcon() const;
void setWindow( Toplevel* w ); // internal
void setSceneWindow( Scene::Window* w ); // internal
@ -240,223 +107,11 @@ class EffectWindow
private:
Toplevel* toplevel;
Scene::Window* sw; // This one is used only during paint pass.
};
};
EffectWindow* effectWindow( Toplevel* w );
EffectWindow* effectWindow( Scene::Window* w );
extern EffectsHandler* effects;
inline
WindowPaintData::WindowPaintData()
: opacity( 1.0 )
, xScale( 1 )
, yScale( 1 )
, xTranslate( 0 )
, yTranslate( 0 )
, saturation( 1 )
, brightness( 1 )
{
}
inline
ScreenPaintData::ScreenPaintData()
: xScale( 1 )
, yScale( 1 )
, xTranslate( 0 )
, yTranslate( 0 )
{
}
inline
const Toplevel* EffectWindow::window() const
{
return toplevel;
}
inline
Toplevel* EffectWindow::window()
{
return toplevel;
}
inline
void EffectWindow::setWindow( Toplevel* w )
{
toplevel = w;
}
inline
void EffectWindow::setSceneWindow( Scene::Window* w )
{
sw = w;
}
inline
Scene::Window* EffectWindow::sceneWindow()
{
return sw;
}
inline
int EffectWindow::x() const
{
return toplevel->x();
}
inline
int EffectWindow::y() const
{
return toplevel->y();
}
inline
int EffectWindow::width() const
{
return toplevel->width();
}
inline
int EffectWindow::height() const
{
return toplevel->height();
}
inline
QRect EffectWindow::geometry() const
{
return toplevel->geometry();
}
inline
QSize EffectWindow::size() const
{
return toplevel->size();
}
inline
QPoint EffectWindow::pos() const
{
return toplevel->pos();
}
inline
QRect EffectWindow::rect() const
{
return toplevel->rect();
}
inline
bool EffectWindow::isDesktop() const
{
return toplevel->isDesktop();
}
inline
bool EffectWindow::isDock() const
{
return toplevel->isDock();
}
inline
bool EffectWindow::isToolbar() const
{
return toplevel->isToolbar();
}
inline
bool EffectWindow::isTopMenu() const
{
return toplevel->isTopMenu();
}
inline
bool EffectWindow::isMenu() const
{
return toplevel->isMenu();
}
inline
bool EffectWindow::isNormalWindow() const
{
return toplevel->isNormalWindow();
}
inline
bool EffectWindow::isDialog() const
{
return toplevel->isDialog();
}
inline
bool EffectWindow::isSplash() const
{
return toplevel->isSplash();
}
inline
bool EffectWindow::isUtility() const
{
return toplevel->isUtility();
}
inline
bool EffectWindow::isDropdownMenu() const
{
return toplevel->isDropdownMenu();
}
inline
bool EffectWindow::isPopupMenu() const
{
return toplevel->isPopupMenu();
}
inline
bool EffectWindow::isTooltip() const
{
return toplevel->isTooltip();
}
inline
bool EffectWindow::isNotification() const
{
return toplevel->isNotification();
}
inline
bool EffectWindow::isComboBox() const
{
return toplevel->isComboBox();
}
inline
bool EffectWindow::isDNDIcon() const
{
return toplevel->isDNDIcon();
}
inline
EffectWindow* effectWindow( Toplevel* w )
{
EffectWindow* ret = w->effectWindow();
ret->setSceneWindow( NULL ); // just in case
return ret;
}
inline
EffectWindow* effectWindow( Scene::Window* w )
{
EffectWindow* ret = w->window()->effectWindow();
ret->setSceneWindow( w );
return ret;
}
inline
Workspace* Effect::workspace() const
{
return Workspace::self();
}
} // namespace

17
effects/CMakeLists.txt Normal file
View file

@ -0,0 +1,17 @@
# Adds effect plugin with given name. Sources are given after the name
macro(KWIN4_ADD_EFFECT name)
kde4_automoc(kwin4_effect_${name} ${ARGN})
kde4_add_plugin(kwin4_effect_${name} ${ARGN})
target_link_libraries(kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS})
install(TARGETS kwin4_effect_${name} DESTINATION ${PLUGIN_INSTALL_DIR})
endmacro(KWIN4_ADD_EFFECT)
include_directories(
${CMAKE_SOURCE_DIR}/workspace/kwin/lib
)
KWIN4_ADD_EFFECT(builtins presentwindows.cpp shadow.cpp)
install( FILES presentwindows.desktop shadow.desktop
DESTINATION ${DATA_INSTALL_DIR}/kwin/effects )

View file

@ -11,14 +11,14 @@ License. See the file "COPYING" for the exact licensing terms.
#include "presentwindows.h"
#include <client.h>
#include <workspace.h>
#include <kactioncollection.h>
#include <kaction.h>
#include <klocale.h>
#include <QMouseEvent>
#include <math.h>
#include <assert.h>
@ -29,7 +29,7 @@ namespace KWin
{
PresentWindowsEffect::PresentWindowsEffect()
PresentWindowsEffect::PresentWindowsEffect() : QObject(), Effect()
{
mShowWindowsFromAllDesktops = false;
mActivated = false;
@ -48,14 +48,14 @@ PresentWindowsEffect::PresentWindowsEffect()
borderActivate = ElectricTopRight;
borderActivateAll = ElectricNone;
Workspace::self()->reserveElectricBorder( borderActivate );
Workspace::self()->reserveElectricBorder( borderActivateAll );
effects->reserveElectricBorder( borderActivate );
effects->reserveElectricBorder( borderActivateAll );
}
PresentWindowsEffect::~PresentWindowsEffect()
{
Workspace::self()->unreserveElectricBorder( borderActivate );
Workspace::self()->unreserveElectricBorder( borderActivateAll );
effects->unreserveElectricBorder( borderActivate );
effects->unreserveElectricBorder( borderActivateAll );
}
@ -75,26 +75,25 @@ void PresentWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time
// We need to mark the screen windows as transformed. Otherwise the whole
// screen won't be repainted, resulting in artefacts
if( mActiveness > 0.0f )
*mask |= Scene::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
*mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen(mask, region, time);
}
void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( mActiveness > 0.0f && mWindowData.contains(w->window()) )
if( mActiveness > 0.0f && mWindowData.contains(w) )
{
// This window will be transformed by the effect
*mask |= Scene::PAINT_WINDOW_TRANSFORMED;
w->enablePainting( Scene::Window::PAINT_DISABLED_BY_MINIMIZE );
w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DESKTOP );
*mask |= Effect::PAINT_WINDOW_TRANSFORMED;
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE );
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
// If it's minimized window or on another desktop and effect is not
// fully active, then apply some transparency
Client* c = static_cast< Client* >( w->window() );
if( mActiveness < 1.0f && (c->isMinimized() || !c->isOnCurrentDesktop() ))
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
if( mActiveness < 1.0f && (w->isMinimized() || !w->isOnCurrentDesktop() ))
*mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
// Change window's hover according to cursor pos
WindowData& windata = mWindowData[w->window()];
WindowData& windata = mWindowData[w];
const float hoverchangetime = 200;
if( windata.area.contains(cursorPos()) )
windata.hover = qMin(1.0f, windata.hover + time / hoverchangetime);
@ -107,20 +106,19 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion*
void PresentWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if(mActiveness > 0.0f && mWindowData.contains(w->window()))
if(mActiveness > 0.0f && mWindowData.contains(w))
{
// Change window's position and scale
const WindowData& windata = mWindowData[w->window()];
const WindowData& windata = mWindowData[w];
data.xScale = interpolate(data.xScale, windata.scale, mActiveness);
data.yScale = interpolate(data.xScale, windata.scale, mActiveness);
data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->window()->x(), mActiveness);
data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->window()->y(), mActiveness);
data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->x(), mActiveness);
data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->y(), mActiveness);
// Darken all windows except for the one under the cursor
data.brightness *= interpolate(1.0, 0.7, mActiveness * (1.0f - windata.hover));
// If it's minimized window or on another desktop and effect is not
// fully active, then apply some transparency
Client* c = static_cast< Client* >( w->window() );
if( mActiveness < 1.0f && (c->isMinimized() || !c->isOnCurrentDesktop() ))
if( mActiveness < 1.0f && (w->isMinimized() || !w->isOnCurrentDesktop() ))
data.opacity *= interpolate(0.0, 1.0, mActiveness);
}
@ -133,7 +131,7 @@ void PresentWindowsEffect::postPaintScreen()
// If mActiveness is between 0 and 1, the effect is still in progress and the
// workspace has to be repainted during the next pass
if( mActiveness > 0.0 && mActiveness < 1.0 )
workspace()->addRepaintFull(); // trigger next animation repaint
effects->addRepaintFull(); // trigger next animation repaint
// Call the next effect.
effects->postPaintScreen();
@ -147,12 +145,12 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent* e )
// Find out which window (if any) was clicked and activate it
QPoint pos = static_cast< QMouseEvent* >( e )->pos();
for( QHash<Toplevel*, WindowData>::iterator it = mWindowData.begin();
for( QHash<EffectWindow*, WindowData>::iterator it = mWindowData.begin();
it != mWindowData.end(); ++it )
{
if( it.value().area.contains(pos) )
{
effects->activateWindow( it.key()->effectWindow());
effects->activateWindow( it.key() );
// mWindowData gets cleared and rebuilt when a window is
// activated, so it's dangerous (and unnecessary) to continue
break;
@ -184,7 +182,7 @@ void PresentWindowsEffect::setActive(bool active)
void PresentWindowsEffect::effectActivated()
{
// Create temporary input window to catch mouse events
mInput = effects->createInputWindow( this, 0, 0, displayWidth(), displayHeight(), Qt::PointingHandCursor );
mInput = effects->createFullScreenInputWindow( this, Qt::PointingHandCursor );
// TODO: maybe also create a KAction so that ressing Esc would terminate the effect?
}
@ -201,78 +199,78 @@ void PresentWindowsEffect::rearrangeWindows()
mWindowData.clear();
const ClientList& originalclientlist = workspace()->stackingOrder();
const EffectWindowList& originalwindowlist = effects->stackingOrder();
// Filter out special windows such as panels and taskbars
ClientList clientlist;
foreach( Client* client, originalclientlist )
EffectWindowList windowlist;
foreach( EffectWindow* window, originalwindowlist )
{
if( client->isSpecialWindow() )
if( window->isSpecialWindow() )
continue;
if( !mShowWindowsFromAllDesktops && !client->effectWindow()->isOnCurrentDesktop() )
if( !mShowWindowsFromAllDesktops && !window->isOnCurrentDesktop() )
continue;
clientlist.append(client);
windowlist.append(window);
}
// Calculate new positions and scales for windows
calculateWindowTransformationsKompose( clientlist );
calculateWindowTransformationsKompose( windowlist );
// Schedule entire desktop to be repainted
workspace()->addRepaintFull();
effects->addRepaintFull();
}
void PresentWindowsEffect::calculateWindowTransformationsDumb(ClientList clientlist)
void PresentWindowsEffect::calculateWindowTransformationsDumb(EffectWindowList windowlist)
{
// Calculate number of rows/cols
int rows = clientlist.count() / 4 + 1;
int cols = clientlist.count() / rows + clientlist.count() % rows;
int rows = windowlist.count() / 4 + 1;
int cols = windowlist.count() / rows + windowlist.count() % rows;
// Get rect which we can use on current desktop. This excludes e.g. panels
QRect placementRect = workspace()->clientArea( PlacementArea, QPoint( 0, 0 ), 0 );
QRect placementRect = effects->clientArea( PlacementArea, QPoint( 0, 0 ), 0 );
// Size of one cell
int cellwidth = placementRect.width() / cols;
int cellheight = placementRect.height() / rows;
kDebug() << k_funcinfo << "Got " << clientlist.count() << " clients, using " << rows << "x" << cols << " grid" << endl;
kDebug() << k_funcinfo << "Got " << windowlist.count() << " clients, using " << rows << "x" << cols << " grid" << endl;
// Calculate position and scale factor for each window
int i = 0;
foreach( Client* client, clientlist )
foreach( EffectWindow* window, windowlist )
{
// Row/Col of this window
int r = i / cols;
int c = i % cols;
mWindowData[client].hover = 0.0f;
mWindowData[client].scale = qMin(cellwidth / (float)client->width(), cellheight / (float)client->height());
mWindowData[client].area.setLeft(placementRect.left() + cellwidth * c);
mWindowData[client].area.setTop(placementRect.top() + cellheight * r);
mWindowData[client].area.setWidth((int)(client->width() * mWindowData[client].scale));
mWindowData[client].area.setHeight((int)(client->height() * mWindowData[client].scale));
mWindowData[window].hover = 0.0f;
mWindowData[window].scale = qMin(cellwidth / (float)window->width(), cellheight / (float)window->height());
mWindowData[window].area.setLeft(placementRect.left() + cellwidth * c);
mWindowData[window].area.setTop(placementRect.top() + cellheight * r);
mWindowData[window].area.setWidth((int)(window->width() * mWindowData[window].scale));
mWindowData[window].area.setHeight((int)(window->height() * mWindowData[window].scale));
kDebug() << k_funcinfo << "Window '" << client->caption() << "' gets moved to (" <<
mWindowData[client].area.left() << "; " << mWindowData[client].area.right() <<
"), scale: " << mWindowData[client].scale << endl;
kDebug() << k_funcinfo << "Window '" << window->caption() << "' gets moved to (" <<
mWindowData[window].area.left() << "; " << mWindowData[window].area.right() <<
"), scale: " << mWindowData[window].scale << endl;
i++;
}
}
float PresentWindowsEffect::clientAspectRatio(Client* c)
float PresentWindowsEffect::windowAspectRatio(EffectWindow* c)
{
return c->width() / (float)c->height();
}
int PresentWindowsEffect::clientWidthForHeight(Client* c, int h)
int PresentWindowsEffect::windowWidthForHeight(EffectWindow* c, int h)
{
return (int)((h / (float)c->height()) * c->width());
}
int PresentWindowsEffect::clientHeightForWidth(Client* c, int w)
int PresentWindowsEffect::windowHeightForWidth(EffectWindow* c, int w)
{
return (int)((w / (float)c->width()) * c->height());
}
void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clientlist)
void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist)
{
// Get rect which we can use on current desktop. This excludes e.g. panels
QRect availRect = workspace()->clientArea( PlacementArea, QPoint( 0, 0 ), 0 );
QRect availRect = effects->clientArea( PlacementArea, QPoint( 0, 0 ), 0 );
// Following code is taken from Kompose 0.5.4, src/komposelayout.cpp
@ -282,21 +280,21 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie
// Use more columns than rows when parent's width > parent's height
if ( parentRatio > 1 )
{
columns = (int)ceil( sqrt(clientlist.count()) );
rows = (int)ceil( (double)clientlist.count() / (double)columns );
columns = (int)ceil( sqrt(windowlist.count()) );
rows = (int)ceil( (double)windowlist.count() / (double)columns );
}
else
{
rows = (int)ceil( sqrt(clientlist.count()) );
columns = (int)ceil( (double)clientlist.count() / (double)rows );
rows = (int)ceil( sqrt(windowlist.count()) );
columns = (int)ceil( (double)windowlist.count() / (double)rows );
}
kDebug() << k_funcinfo << "Using " << rows << " rows & " << columns << " columns for " << clientlist.count() << " clients" << endl;
kDebug() << k_funcinfo << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients" << endl;
// Calculate width & height
int w = (availRect.width() - (columns+1) * spacing ) / columns;
int h = (availRect.height() - (rows+1) * spacing ) / rows;
ClientList::iterator it( clientlist.begin() );
EffectWindowList::iterator it( windowlist.begin() );
QList<QRect> geometryRects;
QList<int> maxRowHeights;
// Process rows
@ -307,15 +305,15 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie
// Process columns
for ( int j=0; j<columns; ++j )
{
Client *client;
EffectWindow* window;
// Check for end of List
if ( it == clientlist.end() )
if ( it == windowlist.end() )
break;
client = *it;
window = *it;
// Calculate width and height of widget
float ratio = clientAspectRatio(client);
float ratio = windowAspectRatio(window);
int widgetw = 100;
int widgeth = 100;
@ -323,15 +321,15 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie
int usableH = h;
// use width of two boxes if there is no right neighbour
if (client == clientlist.last() && j != columns-1)
if (window == windowlist.last() && j != columns-1)
{
usableW = 2*w;
}
++it; // We need access to the neighbour in the following
// expand if right neighbour has ratio < 1
if (j != columns-1 && it != clientlist.end() && clientAspectRatio(*it) < 1)
if (j != columns-1 && it != windowlist.end() && windowAspectRatio(*it) < 1)
{
int addW = w - clientWidthForHeight(*it, h);
int addW = w - windowWidthForHeight(*it, h);
if ( addW > 0 )
{
usableW = w + addW;
@ -345,8 +343,8 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie
}
else
{
double widthForHeight = clientWidthForHeight(client, usableH);
double heightForWidth = clientHeightForWidth(client, usableW);
double widthForHeight = windowWidthForHeight(window, usableH);
double heightForWidth = windowHeightForWidth(window, usableW);
if ( (ratio >= 1.0 && heightForWidth <= usableH) ||
(ratio < 1.0 && widthForHeight > usableW) )
{
@ -389,19 +387,19 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie
for( int j = 0; j < columns; j++ )
{
int pos = i*columns + j;
if(pos >= clientlist.count())
if(pos >= windowlist.count())
break;
Client* client = clientlist[pos];
EffectWindow* window = windowlist[pos];
QRect geom = geometryRects[pos];
geom.setY( geom.y() + topOffset );
mWindowData[client].area = geom;
mWindowData[client].scale = geom.width() / (float)client->width();
mWindowData[client].hover = 0.0f;
mWindowData[window].area = geom;
mWindowData[window].scale = geom.width() / (float)window->width();
mWindowData[window].hover = 0.0f;
kDebug() << k_funcinfo << "Window '" << client->caption() << "' gets moved to (" <<
mWindowData[client].area.left() << "; " << mWindowData[client].area.right() <<
"), scale: " << mWindowData[client].scale << endl;
kDebug() << k_funcinfo << "Window '" << window->caption() << "' gets moved to (" <<
mWindowData[window].area.left() << "; " << mWindowData[window].area.right() <<
"), scale: " << mWindowData[window].scale << endl;
}
if ( maxRowHeights[i]-h > 0 )
topOffset += maxRowHeights[i]-h;

View file

@ -0,0 +1,4 @@
[Desktop Entry]
Encoding=UTF-8
Name=PresentWindows
X-KDE-Library=kwin4_effect_builtins

View file

@ -12,7 +12,7 @@ License. See the file "COPYING" for the exact licensing terms.
#define KWIN_PRESENTWINDOWS_H
// Include with base class for effects.
#include <effects.h>
#include <kwineffects.h>
namespace KWin
@ -48,13 +48,13 @@ class PresentWindowsEffect
protected:
// Updates window tranformations, i.e. destination pos and scale of the window
void rearrangeWindows();
void calculateWindowTransformationsDumb(ClientList clientlist);
void calculateWindowTransformationsKompose(ClientList clientlist);
void calculateWindowTransformationsDumb(EffectWindowList windowlist);
void calculateWindowTransformationsKompose(EffectWindowList windowlist);
// Helper methods for layout calculation
float clientAspectRatio(Client* c);
int clientWidthForHeight(Client* c, int h);
int clientHeightForWidth(Client* c, int w);
float windowAspectRatio(EffectWindow* c);
int windowWidthForHeight(EffectWindow* c, int h);
int windowHeightForWidth(EffectWindow* c, int w);
// Called once the effect is activated (and wasn't activated before)
void effectActivated();
@ -77,12 +77,14 @@ class PresentWindowsEffect
float scale;
float hover;
};
QHash<Toplevel*, WindowData> mWindowData;
QHash<EffectWindow*, WindowData> mWindowData;
ElectricBorder borderActivate;
ElectricBorder borderActivateAll;
};
KWIN_EFFECT( PresentWindows, PresentWindowsEffect );
} // namespace
#endif

View file

@ -10,9 +10,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "shadow.h"
#ifdef HAVE_OPENGL
#include <GL/gl.h>
#endif
#include <kwinglutils.h>
namespace KWin
{
@ -25,7 +23,7 @@ ShadowEffect::ShadowEffect()
void ShadowEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
*mask |= PAINT_WINDOW_TRANSLUCENT;
*paint |= ( QRegion( w->geometry()) & *paint ).translated( shadowXOffset, shadowYOffset );
effects->prePaintWindow( w, mask, paint, clip, time );
}
@ -50,7 +48,7 @@ QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r )
void ShadowEffect::drawShadow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if(( mask & Scene::PAINT_WINDOW_TRANSLUCENT ) == 0 )
if(( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
return;
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
glEnable( GL_BLEND );
@ -58,10 +56,10 @@ void ShadowEffect::drawShadow( EffectWindow* w, int mask, QRegion region, Window
glColor4f( 0, 0, 0, 0.2 * data.opacity ); // black
glPushMatrix();
if( mask & Scene::PAINT_WINDOW_TRANSFORMED )
if( mask & PAINT_WINDOW_TRANSFORMED )
glTranslatef( data.xTranslate, data.yTranslate, 0 );
glTranslatef( w->x() + shadowXOffset, w->y() + shadowYOffset, 0 );
if(( mask & Scene::PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
glScalef( data.xScale, data.yScale, 1 );
glEnableClientState( GL_VERTEX_ARRAY );
@ -73,7 +71,7 @@ void ShadowEffect::drawShadow( EffectWindow* w, int mask, QRegion region, Window
w->width(), 0
};
glVertexPointer( 2, GL_INT, 0, verts );
if( mask & ( Scene::PAINT_WINDOW_TRANSFORMED | Scene::PAINT_SCREEN_TRANSFORMED ))
if( mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED ))
glDrawArrays( GL_QUADS, 0, 4 );
else
{ // clip by region

4
effects/shadow.desktop Normal file
View file

@ -0,0 +1,4 @@
[Desktop Entry]
Encoding=UTF-8
Name=Shadow
X-KDE-Library=kwin4_effect_builtins

View file

@ -11,7 +11,7 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_SHADOW_H
#define KWIN_SHADOW_H
#include <effects.h>
#include <kwineffects.h>
namespace KWin
{
@ -30,6 +30,8 @@ class ShadowEffect
int shadowXOffset, shadowYOffset;
};
KWIN_EFFECT( Shadow, ShadowEffect )
} // namespace
#endif

View file

@ -10,16 +10,61 @@ set(kdecorations_LIB_SRCS
kdecorationfactory.cpp
kcommondecoration.cpp )
kde4_automoc(${kdecorations_LIB_SRCS})
kde4_automoc(kdecorations ${kdecorations_LIB_SRCS})
kde4_add_library(kdecorations SHARED ${kdecorations_LIB_SRCS})
target_link_libraries(kdecorations ${KDE4_KDEUI_LIBS} ${QT_QTGUI_LIBRARY})
set_target_properties(kdecorations PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} )
set_target_properties(kdecorations PROPERTIES VERSION 1.0.0 SOVERSION 1 )
install(TARGETS kdecorations DESTINATION ${LIB_INSTALL_DIR} )
########### install files ###############
install( FILES kdecoration.h kdecoration_p.h kdecoration_plugins_p.h kdecorationfactory.h kcommondecoration.h DESTINATION ${INCLUDE_INSTALL_DIR})
install_files( /include FILES kdecoration.h kdecoration_p.h kdecoration_plugins_p.h kdecorationfactory.h kcommondecoration.h )
### effects lib ###
set(kwin_EFFECTSLIB_SRCS
kwinglobals.cpp
kwineffects.cpp
kwinglutils.cpp
kwinglutils_funcs.cpp
)
kde4_automoc(${kwin_EFFECTSLIB_SRCS})
kde4_add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS})
target_link_libraries(kwineffects ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${X11_LIBRARIES})
set_target_properties(kdecorations PROPERTIES VERSION 1.0.0 SOVERSION 1 )
install(TARGETS kwineffects DESTINATION ${LIB_INSTALL_DIR})
if(OPENGL_FOUND)
target_link_libraries(kwineffects ${OPENGL_gl_LIBRARY})
# -ldl used by OpenGL code
target_link_libraries(kwineffects -ldl)
endif(OPENGL_FOUND)
install_files( /include FILES kwinglobals.h kwineffects.h kwinglutils.h kwinglutils_funcs.h )
#original Makefile.am contents follow:
## FRAME libkwin???
#lib_LTLIBRARIES = libkdecorations.la
#
#libkdecorations_la_SOURCES = kdecoration.cpp kdecoration_p.cpp kdecoration_plugins_p.cpp \
# kdecorationfactory.cpp kcommondecoration.cpp
#libkdecorations_la_LIBADD = $(LIB_KDECORE)
#libkdecorations_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined
#
## FRAME
#include_HEADERS = kdecoration.h kdecoration_p.h kdecoration_plugins_p.h \
# kdecorationfactory.h kcommondecoration.h
#
#INCLUDES = $(all_includes)
#METASOURCES = AUTO
#
#include ../../../admin/Doxyfile.am
#
#messages: rc.cpp
# $(XGETTEXT) `find . -name \*.cpp` -o $(podir)/kwin_lib.pot
# -rm rc.cpp

472
lib/kwineffects.cpp Normal file
View file

@ -0,0 +1,472 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "kwineffects.h"
#include <QStringList>
#include <QFile>
#include "kdebug.h"
#include "klibloader.h"
#include "kdesktopfile.h"
#include "kconfiggroup.h"
#include "kstandarddirs.h"
#include <assert.h>
namespace KWin
{
WindowPaintData::WindowPaintData()
: opacity( 1.0 )
, xScale( 1 )
, yScale( 1 )
, xTranslate( 0 )
, yTranslate( 0 )
, saturation( 1 )
, brightness( 1 )
{
}
ScreenPaintData::ScreenPaintData()
: xScale( 1 )
, yScale( 1 )
, xTranslate( 0 )
, yTranslate( 0 )
{
}
//****************************************
// Effect
//****************************************
Effect::Effect()
{
}
Effect::~Effect()
{
}
void Effect::windowUserMovedResized( EffectWindow* , bool, bool )
{
}
void Effect::windowOpacityChanged( EffectWindow*, double )
{
}
void Effect::windowAdded( EffectWindow* )
{
}
void Effect::windowClosed( EffectWindow* )
{
}
void Effect::windowDeleted( EffectWindow* )
{
}
void Effect::windowActivated( EffectWindow* )
{
}
void Effect::windowMinimized( EffectWindow* )
{
}
void Effect::windowUnminimized( EffectWindow* )
{
}
void Effect::windowInputMouseEvent( Window, QEvent* )
{
}
void Effect::desktopChanged( int )
{
}
void Effect::windowDamaged( EffectWindow*, const QRect& )
{
}
void Effect::windowGeometryShapeChanged( EffectWindow*, const QRect& )
{
}
void Effect::tabBoxAdded( int )
{
}
void Effect::tabBoxClosed()
{
}
void Effect::tabBoxUpdated()
{
}
bool Effect::borderActivated( ElectricBorder )
{
return false;
}
void Effect::prePaintScreen( int* mask, QRegion* region, int time )
{
effects->prePaintScreen( mask, region, time );
}
void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
effects->paintScreen( mask, region, data );
}
void Effect::postPaintScreen()
{
effects->postPaintScreen();
}
void Effect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
effects->prePaintWindow( w, mask, paint, clip, time );
}
void Effect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
effects->paintWindow( w, mask, region, data );
}
void Effect::postPaintWindow( EffectWindow* w )
{
effects->postPaintWindow( w );
}
void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
effects->drawWindow( w, mask, region, data );
}
QRect Effect::transformWindowDamage( EffectWindow* w, const QRect& r )
{
return effects->transformWindowDamage( w, r );
}
void Effect::setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
const QRect& r, Qt::AspectRatioMode aspect )
{
QSize size = w->size();
size.scale( r.size(), aspect );
data.xScale = size.width() / double( w->width());
data.yScale = size.height() / double( w->height());
int width = int( w->width() * data.xScale );
int height = int( w->height() * data.yScale );
int x = r.x() + ( r.width() - width ) / 2;
int y = r.y() + ( r.height() - height ) / 2;
region = QRect( x, y, width, height );
data.xTranslate = x - w->x();
data.yTranslate = y - w->y();
}
int Effect::displayWidth()
{
return KWin::displayWidth();
}
int Effect::displayHeight()
{
return KWin::displayHeight();
}
QPoint Effect::cursorPos()
{
return KWin::cursorPos();
}
//****************************************
// EffectsHandler
//****************************************
EffectsHandler::EffectsHandler(CompositingType type)
: current_paint_screen( 0 )
, current_paint_window( 0 )
, current_draw_window( 0 )
, current_transform( 0 )
, compositing_type( type )
{
if( compositing_type == NoCompositing )
return;
KWin::effects = this;
}
EffectsHandler::~EffectsHandler()
{
// All effects should already be unloaded by Impl dtor
assert( loaded_effects.count() == 0 );
}
void EffectsHandler::windowUserMovedResized( EffectWindow* c, bool first, bool last )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowUserMovedResized( c, first, last );
}
void EffectsHandler::windowOpacityChanged( EffectWindow* c, double old_opacity )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowOpacityChanged( c, old_opacity );
}
void EffectsHandler::windowAdded( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowAdded( c );
}
void EffectsHandler::windowDeleted( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowDeleted( c );
}
void EffectsHandler::windowClosed( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowClosed( c );
}
void EffectsHandler::windowActivated( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowActivated( c );
}
void EffectsHandler::windowMinimized( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowMinimized( c );
}
void EffectsHandler::windowUnminimized( EffectWindow* c )
{
foreach( EffectPair ep, loaded_effects )
ep.second->windowUnminimized( c );
}
void EffectsHandler::desktopChanged( int old )
{
foreach( EffectPair ep, loaded_effects )
ep.second->desktopChanged( old );
}
void EffectsHandler::windowDamaged( EffectWindow* w, const QRect& r )
{
if( w == NULL )
return;
foreach( EffectPair ep, loaded_effects )
ep.second->windowDamaged( w, r );
}
void EffectsHandler::windowGeometryShapeChanged( EffectWindow* w, const QRect& old )
{
if( w == NULL ) // during late cleanup effectWindow() may be already NULL
return; // in some functions that may still call this
foreach( EffectPair ep, loaded_effects )
ep.second->windowGeometryShapeChanged( w, old );
}
void EffectsHandler::tabBoxAdded( int mode )
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxAdded( mode );
}
void EffectsHandler::tabBoxClosed()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxClosed();
}
void EffectsHandler::tabBoxUpdated()
{
foreach( EffectPair ep, loaded_effects )
ep.second->tabBoxUpdated();
}
bool EffectsHandler::borderActivated( ElectricBorder border )
{
bool ret = false;
foreach( EffectPair ep, loaded_effects )
if( ep.second->borderActivated( border ))
ret = true; // bail out or tell all?
return ret;
}
// start another painting pass
void EffectsHandler::startPaint()
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
}
QRect EffectsHandler::transformWindowDamage( EffectWindow* w, const QRect& r )
{
if( current_transform < loaded_effects.size())
{
QRect rr = loaded_effects[current_transform++].second->transformWindowDamage( w, r );
--current_transform;
return rr;
}
else
return r;
}
Window EffectsHandler::createInputWindow( Effect* e, const QRect& r, const QCursor& cursor )
{
return createInputWindow( e, r.x(), r.y(), r.width(), r.height(), cursor );
}
Window EffectsHandler::createFullScreenInputWindow( Effect* e, const QCursor& cursor )
{
return createInputWindow( e, 0, 0, displayWidth(), displayHeight(), cursor );
}
KLibrary* EffectsHandler::findEffectLibrary( const QString& effectname )
{
QString libname = "kwin4_effect_" + effectname.toLower();
QString desktopfile = KStandardDirs::locate("appdata",
"effects/" + effectname.toLower() + ".desktop");
if( !desktopfile.isEmpty() )
{
KDesktopFile desktopconf( desktopfile );
KConfigGroup conf = desktopconf.desktopGroup();
libname = conf.readEntry( "X-KDE-Library", libname );
}
KLibrary* library = KLibLoader::self()->library(QFile::encodeName(libname));
if( !library )
{
kError( 1212 ) << k_funcinfo << "couldn't open library for effect '" <<
effectname << "'" << endl;
return 0;
}
return library;
}
void EffectsHandler::loadEffect( const QString& name )
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
// Make sure a single effect won't be loaded multiple times
for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); it++)
{
if( (*it).first == name )
{
kDebug( 1212 ) << "EffectsHandler::loadEffect : Effect already loaded : " << name << endl;
return;
}
}
kDebug( 1212 ) << k_funcinfo << "Trying to load " << name << endl;
KLibrary* library = findEffectLibrary( name );
if( !library )
{
return;
}
QString supported_symbol = "effect_supported_" + name;
KLibrary::void_function_ptr supported_func = library->resolveFunction(supported_symbol.toAscii().data());
QString create_symbol = "effect_create_" + name;
KLibrary::void_function_ptr create_func = library->resolveFunction(create_symbol.toAscii().data());
if( supported_func )
{
typedef bool (*t_supportedfunc)();
t_supportedfunc supported = reinterpret_cast<t_supportedfunc>(supported_func);
if(!supported())
{
kWarning( 1212 ) << "EffectsHandler::loadEffect : Effect " << name << " is not supported" << endl;
library->unload();
return;
}
}
if(!create_func)
{
kError( 1212 ) << "EffectsHandler::loadEffect : effect_create function not found" << endl;
library->unload();
return;
}
typedef Effect* (*t_createfunc)();
t_createfunc create = reinterpret_cast<t_createfunc>(create_func);
Effect* e = create();
loaded_effects.append( EffectPair( name, e ) );
effect_libraries[ name ] = library;
}
void EffectsHandler::unloadEffect( const QString& name )
{
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); it++)
{
if ( (*it).first == name )
{
kDebug( 1212 ) << "EffectsHandler::unloadEffect : Unloading Effect : " << name << endl;
delete (*it).second;
loaded_effects.erase(it);
effect_libraries[ name ]->unload();
return;
}
}
kDebug( 1212 ) << "EffectsHandler::unloadEffect : Effect not loaded : " << name << endl;
}
EffectsHandler* effects = 0;
//****************************************
// EffectWindow
//****************************************
EffectWindow::EffectWindow()
{
}
EffectWindow::~EffectWindow()
{
}
bool EffectWindow::isOnCurrentDesktop() const
{
return isOnDesktop( effects->currentDesktop());
}
bool EffectWindow::isOnDesktop( int d ) const
{
return desktop() == d || isOnAllDesktops();
}
} // namespace

300
lib/kwineffects.h Normal file
View file

@ -0,0 +1,300 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
// TODO MIT or some other licence, perhaps move to some lib
#ifndef KWIN_LIB_EFFECTS_H
#define KWIN_LIB_EFFECTS_H
#include <kwinglobals.h>
#include <qpair.h>
#include <QRect>
#include <QRegion>
#include <QString>
#include <QVector>
#include <QList>
#include <QHash>
#include <stdio.h>
class KLibrary;
namespace KWin
{
class EffectWindow;
class Effect;
typedef QPair< QString, Effect* > EffectPair;
typedef QPair< Effect*, Window > InputWindowPair;
typedef QList< EffectWindow* > EffectWindowList;
class KWIN_EXPORT Effect
{
public:
// Flags controlling how painting is done.
// TODO: is that ok here?
enum
{
// Window (or at least part of it) will be painted opaque.
PAINT_WINDOW_OPAQUE = 1 << 0,
// Window (or at least part of it) will be painted translucent.
PAINT_WINDOW_TRANSLUCENT = 1 << 1,
// Window will be painted with transformed geometry.
PAINT_WINDOW_TRANSFORMED = 1 << 2,
// Paint only a region of the screen (can be optimized, cannot
// be used together with TRANSFORMED flags).
PAINT_SCREEN_REGION = 1 << 3,
// Whole screen will be painted with transformed geometry.
PAINT_SCREEN_TRANSFORMED = 1 << 4,
// At least one window will be painted with transformed geometry.
PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS = 1 << 5,
// Clear whole background as the very first step, without optimizing it
PAINT_SCREEN_BACKGROUND_FIRST = 1 << 6
};
Effect();
virtual ~Effect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
// paintWindow() can do various transformations
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// drawWindow() is used even for thumbnails etc. - it can alter the window itself where it
// makes sense (e.g.darkening out unresponsive windows), but it cannot do transformations
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
// This function is used e.g. by the shadow effect which adds area around windows
// that needs to be painted as well - e.g. when a window is hidden and the workspace needs
// to be repainted at that area, shadow's transformWindowDamage() adds the shadow area
// to it, so that it is repainted as well.
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// called when moved/resized or once after it's finished
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
virtual void windowAdded( EffectWindow* c );
virtual void windowClosed( EffectWindow* c );
virtual void windowDeleted( EffectWindow* c );
virtual void windowActivated( EffectWindow* c );
virtual void windowMinimized( EffectWindow* c );
virtual void windowUnminimized( EffectWindow* c );
virtual void windowInputMouseEvent( Window w, QEvent* e );
virtual void desktopChanged( int old );
virtual void windowDamaged( EffectWindow* w, const QRect& r );
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
virtual void tabBoxAdded( int mode );
virtual void tabBoxClosed();
virtual void tabBoxUpdated();
virtual bool borderActivated( ElectricBorder border );
static int displayWidth();
static int displayHeight();
static QPoint cursorPos();
// Interpolates between x and y
static float interpolate(float x, float y, float a)
{
return x * (1 - a) + y * a;
}
// helper to set WindowPaintData and QRegion to necessary transformations so that
// a following drawWindow() would put the window at the requested geometry (useful for thumbnails)
static void setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
const QRect& r, Qt::AspectRatioMode aspect );
};
/**
* Defines the class to be used for effect with given name
* E.g. KWIN_EFFECT( Flames, MyFlameEffect )
* In this case object of MyFlameEffect class would be created when effect
* "Flames" is loaded.
**/
#define KWIN_EFFECT( name, classname ) \
extern "C" { \
KWIN_EXPORT Effect* effect_create_##name() { return new classname; } \
}
/**
* Defines the function used to check whether an effect is supported
* E.g. KWIN_EFFECT_SUPPORTED( Flames, MyFlameEffect::supported() )
**/
#define KWIN_EFFECT_SUPPORTED( name, function ) \
extern "C" { \
KWIN_EXPORT bool effect_supported_##name() { return function; } \
}
/**
* Defines the function used to retrieve an effect's config widget
* E.g. KWIN_EFFECT_CONFIG( Flames, MyFlameEffect::configWidget() )
**/
#define KWIN_EFFECT_CONFIG( name, function ) \
extern "C" { \
KWIN_EXPORT Effect* effect_config_##name() { return function; } \
}
class KWIN_EXPORT EffectsHandler
{
friend class Effect;
public:
EffectsHandler(CompositingType type);
virtual ~EffectsHandler();
// for use by effects
virtual void prePaintScreen( int* mask, QRegion* region, int time ) = 0;
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ) = 0;
virtual void postPaintScreen() = 0;
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ) = 0;
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0;
virtual void postPaintWindow( EffectWindow* w ) = 0;
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0;
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// Functions for handling input - e.g. when an Expose-like effect is shown, an input window
// covering the whole screen is created and all mouse events will be intercepted by it.
// The effect's windowInputMouseEvent() will get called with such events.
virtual Window createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor ) = 0;
virtual Window createInputWindow( Effect* e, const QRect& r, const QCursor& cursor );
virtual Window createFullScreenInputWindow( Effect* e, const QCursor& cursor );
virtual void destroyInputWindow( Window w ) = 0;
virtual void checkElectricBorder(const QPoint &pos, Time time) = 0;
virtual void reserveElectricBorder( ElectricBorder border ) = 0;
virtual void unreserveElectricBorder( ElectricBorder border ) = 0;
virtual void reserveElectricBorderSwitching( bool reserve ) = 0;
// functions that allow controlling windows/desktop
virtual void activateWindow( EffectWindow* c ) = 0;
//
virtual int currentDesktop() const = 0;
virtual QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const = 0;
virtual EffectWindowList stackingOrder() const = 0;
// Repaints the entire workspace
virtual void addRepaintFull() = 0;
// internal (used by kwin core or compositing code)
virtual void startPaint();
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
virtual void windowAdded( EffectWindow* c );
virtual void windowClosed( EffectWindow* c );
virtual void windowDeleted( EffectWindow* c );
virtual void windowActivated( EffectWindow* c );
virtual void windowMinimized( EffectWindow* c );
virtual void windowUnminimized( EffectWindow* c );
virtual bool checkInputWindowEvent( XEvent* e ) = 0;
virtual void checkInputWindowStacking() = 0;
virtual void desktopChanged( int old );
virtual void windowDamaged( EffectWindow* w, const QRect& r );
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
virtual void tabBoxAdded( int mode );
virtual void tabBoxClosed();
virtual void tabBoxUpdated();
virtual bool borderActivated( ElectricBorder border );
CompositingType compositingType() const { return compositing_type; }
//void registerEffect( const QString& name, EffectFactory* factory );
void loadEffect( const QString& name );
void unloadEffect( const QString& name );
protected:
KLibrary* findEffectLibrary( const QString& effectname );
protected:
QVector< EffectPair > loaded_effects;
QHash< QString, KLibrary* > effect_libraries;
QList< InputWindowPair > input_windows;
//QHash< QString, EffectFactory* > effect_factories;
int current_paint_screen;
int current_paint_window;
int current_draw_window;
int current_transform;
CompositingType compositing_type;
};
// This class is a representation of a window used by/for Effect classes.
// The purpose is to hide internal data and also to serve as a single
// representation for the case when Client/Unmanaged becomes Deleted.
class KWIN_EXPORT EffectWindow
{
public:
// Flags explaining why painting should be disabled
enum
{
// Window will not be painted
PAINT_DISABLED = 1 << 0,
// Window will not be painted because it is deleted
PAINT_DISABLED_BY_DELETE = 1 << 1,
// Window will not be painted because of which desktop it's on
PAINT_DISABLED_BY_DESKTOP = 1 << 2,
// Window will not be painted because it is minimized
PAINT_DISABLED_BY_MINIMIZE = 1 << 3
};
EffectWindow();
virtual ~EffectWindow();
virtual void enablePainting( int reason ) = 0;
virtual void disablePainting( int reason ) = 0;
virtual bool isDeleted() const = 0;
virtual bool isMinimized() const = 0;
virtual bool isOnDesktop( int d ) const;
virtual bool isOnCurrentDesktop() const;
virtual bool isOnAllDesktops() const = 0;
virtual int desktop() const = 0; // prefer isOnXXX()
virtual int x() const = 0;
virtual int y() const = 0;
virtual int width() const = 0;
virtual int height() const = 0;
virtual QRect geometry() const = 0;
virtual QPoint pos() const = 0;
virtual QSize size() const = 0;
virtual QRect rect() const = 0;
virtual QString caption() const = 0;
virtual bool isDesktop() const = 0;
virtual bool isDock() const = 0;
virtual bool isToolbar() const = 0;
virtual bool isTopMenu() const = 0;
virtual bool isMenu() const = 0;
virtual bool isNormalWindow() const = 0; // normal as in 'NET::Normal or NET::Unknown non-transient'
virtual bool isSpecialWindow() const = 0;
virtual bool isDialog() const = 0;
virtual bool isSplash() const = 0;
virtual bool isUtility() const = 0;
virtual bool isDropdownMenu() const = 0;
virtual bool isPopupMenu() const = 0; // a context popup, not dropdown, not torn-off
virtual bool isTooltip() const = 0;
virtual bool isNotification() const = 0;
virtual bool isComboBox() const = 0;
virtual bool isDNDIcon() const = 0;
};
extern KWIN_EXPORT EffectsHandler* effects;
} // namespace
#endif

43
lib/kwinglobals.cpp Normal file
View file

@ -0,0 +1,43 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "kwinglobals.h"
#include <QCursor>
#include "kdebug.h"
#include <assert.h>
namespace KWin
{
// Optimized version of QCursor::pos() that tries to avoid X roundtrips
// by updating the value only when the X timestamp changes.
static QPoint last_cursor_pos;
static Time last_cursor_timestamp = CurrentTime;
QPoint cursorPos()
{
last_cursor_timestamp = CurrentTime;
if( last_cursor_timestamp == CurrentTime
|| last_cursor_timestamp != QX11Info::appTime())
{
last_cursor_timestamp = QX11Info::appTime();
last_cursor_pos = QCursor::pos();
}
return last_cursor_pos;
}
} // namespace

122
lib/kwinglobals.h Normal file
View file

@ -0,0 +1,122 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#ifndef KWIN_LIB_KWINGLOBALS_H
#define KWIN_LIB_KWINGLOBALS_H
#include <QX11Info>
#include <QPoint>
#include <kdemacros.h>
#include <X11/Xlib.h>
#include <fixx11h.h>
namespace KWin
{
#define KWIN_EXPORT KDE_EXPORT
enum CompositingType
{
NoCompositing = 0,
OpenGLCompositing,
XRenderCompositing
};
enum clientAreaOption
{
PlacementArea, // geometry where a window will be initially placed after being mapped
MovementArea, // ??? window movement snapping area? ignore struts
MaximizeArea, // geometry to which a window will be maximized
MaximizeFullArea, // like MaximizeArea, but ignore struts - used e.g. for topmenu
FullScreenArea, // area for fullscreen windows
// these below don't depend on xinerama settings
WorkArea, // whole workarea (all screens together)
FullArea, // whole area (all screens together), ignore struts
ScreenArea // one whole screen, ignore struts
};
enum ElectricBorder
{
ElectricTop,
ElectricTopRight,
ElectricRight,
ElectricBottomRight,
ElectricBottom,
ElectricBottomLeft,
ElectricLeft,
ElectricTopLeft,
ELECTRIC_COUNT,
ElectricNone
};
class KWIN_EXPORT WindowPaintData
{
public:
WindowPaintData();
/**
* Window opacity, in range 0 = transparent to 1 = fully opaque
*/
double opacity;
double xScale;
double yScale;
int xTranslate;
int yTranslate;
/**
* Saturation of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* unsaturated (greyscale). 0.5 would make the colors less intense,
* but not completely grey
**/
float saturation;
/**
* Brightness of the window, in range [0; 1]
* 1 means that the window is unchanged, 0 means that it's completely
* black. 0.5 would make it 50% darker than usual
**/
float brightness;
};
class KWIN_EXPORT ScreenPaintData
{
public:
ScreenPaintData();
double xScale;
double yScale;
int xTranslate;
int yTranslate;
};
inline
Display* display()
{
return QX11Info::display();
}
inline
int displayWidth()
{
return XDisplayWidth( display(), DefaultScreen( display()));
}
inline
int displayHeight()
{
return XDisplayHeight( display(), DefaultScreen( display()));
}
QPoint KWIN_EXPORT cursorPos();
} // namespace
#endif

View file

@ -8,9 +8,12 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "glutils.h"
#include "kwinglutils.h"
#include "kwinglobals.h"
#include "kdebug.h"
#include <kdebug.h>
#include <QPixmap>
#include <QImage>
#include <QHash>
@ -441,7 +444,7 @@ bool GLShader::load(const QString& vertexsource, const QString& fragmentsource)
glCompileShader(vertexshader);
// Make sure it compiled correctly
int compiled;
glGetShaderiv(fragmentshader, GL_COMPILE_STATUS, &compiled);
glGetShaderiv(vertexshader, GL_COMPILE_STATUS, &compiled);
// Get info log
glGetShaderiv(vertexshader, GL_INFO_LOG_LENGTH, &logarraysize);
log = new char[logarraysize];

View file

@ -11,17 +11,20 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_GLUTILS_H
#define KWIN_GLUTILS_H
#include "utils.h"
#include <QStringList>
#include <config.h>
#ifdef HAVE_OPENGL
#include <GL/gl.h>
#include <GL/glx.h>
#include <fixx11h.h>
#endif
#include "glutils_funcs.h"
#include <QPixmap>
#include <QString>
#include <QImage>
#include <QSize>
#include <kwinglutils_funcs.h>
template< class K, class V > class QHash;
@ -32,28 +35,28 @@ namespace KWin
// Initializes GLX function pointers
void initGLX();
void KWIN_EXPORT initGLX();
// Initializes OpenGL stuff. This includes resolving function pointers as
// well as checking for GL version and extensions
// Note that GL context has to be created by the time this function is called
void initGL();
void KWIN_EXPORT initGL();
// Number of supported texture units
extern int glTextureUnitsCount;
extern KWIN_EXPORT int glTextureUnitsCount;
bool hasGLVersion(int major, int minor, int release = 0);
bool hasGLXVersion(int major, int minor, int release = 0);
bool KWIN_EXPORT hasGLVersion(int major, int minor, int release = 0);
bool KWIN_EXPORT hasGLXVersion(int major, int minor, int release = 0);
// use for both OpenGL and GLX extensions
bool hasGLExtension(const QString& extension);
bool KWIN_EXPORT hasGLExtension(const QString& extension);
inline bool isPowerOfTwo( int x ) { return (( x & ( x - 1 )) == 0 ); }
int nearestPowerOfTwo( int x );
inline bool KWIN_EXPORT isPowerOfTwo( int x ) { return (( x & ( x - 1 )) == 0 ); }
int KWIN_EXPORT nearestPowerOfTwo( int x );
#ifdef HAVE_OPENGL
class GLTexture
class KWIN_EXPORT GLTexture
{
public:
GLTexture();
@ -108,7 +111,7 @@ class GLTexture
static bool mSaturationSupported;
};
class GLShader
class KWIN_EXPORT GLShader
{
public:
GLShader(const QString& vertexfile, const QString& fragmentfile);

View file

@ -8,7 +8,7 @@ You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "glutils.h"
#include "kwinglutils.h"
#include <dlfcn.h>

View file

@ -11,13 +11,17 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_GLUTILS_FUNCS_H
#define KWIN_GLUTILS_FUNCS_H
#include <kdemacros.h>
#define KWIN_EXPORT KDE_EXPORT
#ifdef HAVE_OPENGL
namespace KWin
{
void glxResolveFunctions();
void glResolveFunctions();
void KWIN_EXPORT glxResolveFunctions();
void KWIN_EXPORT glResolveFunctions();
// Defines
@ -56,32 +60,37 @@ void glResolveFunctions();
#define GL_VERTEX_SHADER 0x8B31
#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
typedef char GLchar;
// Function pointers
// finding of OpenGL extensions functions
typedef void (*glXFuncPtr)();
typedef glXFuncPtr (*glXGetProcAddress_func)( const GLubyte* );
extern glXGetProcAddress_func glXGetProcAddress;
extern KWIN_EXPORT glXGetProcAddress_func glXGetProcAddress;
// glXQueryDrawable (added in GLX 1.3)
typedef void (*glXQueryDrawable_func)( Display* dpy, GLXDrawable drawable,
int attribute, unsigned int *value );
extern glXQueryDrawable_func glXQueryDrawable;
extern KWIN_EXPORT glXQueryDrawable_func glXQueryDrawable;
// texture_from_pixmap extension functions
typedef void (*glXBindTexImageEXT_func)( Display* dpy, GLXDrawable drawable,
int buffer, const int* attrib_list );
typedef void (*glXReleaseTexImageEXT_func)( Display* dpy, GLXDrawable drawable, int buffer );
extern glXReleaseTexImageEXT_func glXReleaseTexImageEXT;
extern glXBindTexImageEXT_func glXBindTexImageEXT;
extern KWIN_EXPORT glXReleaseTexImageEXT_func glXReleaseTexImageEXT;
extern KWIN_EXPORT glXBindTexImageEXT_func glXBindTexImageEXT;
// glXCopySubBufferMESA
typedef void (*glXCopySubBuffer_func) ( Display* , GLXDrawable, int, int, int, int );
extern glXCopySubBuffer_func glXCopySubBuffer;
extern KWIN_EXPORT glXCopySubBuffer_func glXCopySubBuffer;
// video_sync extension functions
typedef void (*glXGetVideoSync_func)( unsigned int *count );
typedef void (*glXWaitVideoSync_func)( int divisor, int remainder, unsigned int *count );
extern glXGetVideoSync_func glXGetVideoSync;
extern glXWaitVideoSync_func glXWaitVideoSync;
extern KWIN_EXPORT glXGetVideoSync_func glXGetVideoSync;
extern KWIN_EXPORT glXWaitVideoSync_func glXWaitVideoSync;
// glActiveTexture
typedef void (*glActiveTexture_func)(GLenum);
extern glActiveTexture_func glActiveTexture;
extern KWIN_EXPORT glActiveTexture_func glActiveTexture;
// framebuffer_object extension functions
typedef bool (*glIsRenderbuffer_func)( GLuint renderbuffer );
typedef void (*glBindRenderbuffer_func)( GLenum target, GLuint renderbuffer );
@ -100,23 +109,23 @@ typedef void (*glFramebufferTexture3D_func)( GLenum target, GLenum attachment, G
typedef void (*glFramebufferRenderbuffer_func)( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer );
typedef void (*glGetFramebufferAttachmentParameteriv_func)( GLenum target, GLenum attachment, GLenum pname, GLint *params );
typedef void (*glGenerateMipmap_func)( GLenum target );
extern glIsRenderbuffer_func glIsRenderbuffer;
extern glBindRenderbuffer_func glBindRenderbuffer;
extern glDeleteRenderbuffers_func glDeleteRenderbuffers;
extern glGenRenderbuffers_func glGenRenderbuffers;
extern glRenderbufferStorage_func glRenderbufferStorage;
extern glGetRenderbufferParameteriv_func glGetRenderbufferParameteriv;
extern glIsFramebuffer_func glIsFramebuffer;
extern glBindFramebuffer_func glBindFramebuffer;
extern glDeleteFramebuffers_func glDeleteFramebuffers;
extern glGenFramebuffers_func glGenFramebuffers;
extern glCheckFramebufferStatus_func glCheckFramebufferStatus;
extern glFramebufferTexture1D_func glFramebufferTexture1D;
extern glFramebufferTexture2D_func glFramebufferTexture2D;
extern glFramebufferTexture3D_func glFramebufferTexture3D;
extern glFramebufferRenderbuffer_func glFramebufferRenderbuffer;
extern glGetFramebufferAttachmentParameteriv_func glGetFramebufferAttachmentParameteriv;
extern glGenerateMipmap_func glGenerateMipmap;
extern KWIN_EXPORT glIsRenderbuffer_func glIsRenderbuffer;
extern KWIN_EXPORT glBindRenderbuffer_func glBindRenderbuffer;
extern KWIN_EXPORT glDeleteRenderbuffers_func glDeleteRenderbuffers;
extern KWIN_EXPORT glGenRenderbuffers_func glGenRenderbuffers;
extern KWIN_EXPORT glRenderbufferStorage_func glRenderbufferStorage;
extern KWIN_EXPORT glGetRenderbufferParameteriv_func glGetRenderbufferParameteriv;
extern KWIN_EXPORT glIsFramebuffer_func glIsFramebuffer;
extern KWIN_EXPORT glBindFramebuffer_func glBindFramebuffer;
extern KWIN_EXPORT glDeleteFramebuffers_func glDeleteFramebuffers;
extern KWIN_EXPORT glGenFramebuffers_func glGenFramebuffers;
extern KWIN_EXPORT glCheckFramebufferStatus_func glCheckFramebufferStatus;
extern KWIN_EXPORT glFramebufferTexture1D_func glFramebufferTexture1D;
extern KWIN_EXPORT glFramebufferTexture2D_func glFramebufferTexture2D;
extern KWIN_EXPORT glFramebufferTexture3D_func glFramebufferTexture3D;
extern KWIN_EXPORT glFramebufferRenderbuffer_func glFramebufferRenderbuffer;
extern KWIN_EXPORT glGetFramebufferAttachmentParameteriv_func glGetFramebufferAttachmentParameteriv;
extern KWIN_EXPORT glGenerateMipmap_func glGenerateMipmap;
// Shader stuff
typedef GLuint (*glCreateShader_func)(GLenum);
typedef GLvoid (*glShaderSource_func)(GLuint, GLsizei, const GLchar**, const GLint*);
@ -140,27 +149,27 @@ typedef GLvoid (*glValidateProgram_func)(GLuint);
typedef GLint (*glGetUniformLocation_func)(GLuint, const GLchar*);
typedef GLvoid (*glVertexAttrib1f_func)(GLuint, GLfloat);
typedef GLint (*glGetAttribLocation_func)(GLuint, const GLchar*);
extern glCreateShader_func glCreateShader;
extern glShaderSource_func glShaderSource;
extern glCompileShader_func glCompileShader;
extern glDeleteShader_func glDeleteShader;
extern glCreateProgram_func glCreateProgram;
extern glAttachShader_func glAttachShader;
extern glLinkProgram_func glLinkProgram;
extern glUseProgram_func glUseProgram;
extern glDeleteProgram_func glDeleteProgram;
extern glGetShaderInfoLog_func glGetShaderInfoLog;
extern glGetProgramInfoLog_func glGetProgramInfoLog;
extern glGetProgramiv_func glGetProgramiv;
extern glGetShaderiv_func glGetShaderiv;
extern glUniform1f_func glUniform1f;
extern glUniform1i_func glUniform1i;
extern glUniform1fv_func glUniform1fv;
extern glUniform2fv_func glUniform2fv;
extern glValidateProgram_func glValidateProgram;
extern glGetUniformLocation_func glGetUniformLocation;
extern glVertexAttrib1f_func glVertexAttrib1f;
extern glGetAttribLocation_func glGetAttribLocation;
extern KWIN_EXPORT glCreateShader_func glCreateShader;
extern KWIN_EXPORT glShaderSource_func glShaderSource;
extern KWIN_EXPORT glCompileShader_func glCompileShader;
extern KWIN_EXPORT glDeleteShader_func glDeleteShader;
extern KWIN_EXPORT glCreateProgram_func glCreateProgram;
extern KWIN_EXPORT glAttachShader_func glAttachShader;
extern KWIN_EXPORT glLinkProgram_func glLinkProgram;
extern KWIN_EXPORT glUseProgram_func glUseProgram;
extern KWIN_EXPORT glDeleteProgram_func glDeleteProgram;
extern KWIN_EXPORT glGetShaderInfoLog_func glGetShaderInfoLog;
extern KWIN_EXPORT glGetProgramInfoLog_func glGetProgramInfoLog;
extern KWIN_EXPORT glGetProgramiv_func glGetProgramiv;
extern KWIN_EXPORT glGetShaderiv_func glGetShaderiv;
extern KWIN_EXPORT glUniform1f_func glUniform1f;
extern KWIN_EXPORT glUniform1i_func glUniform1i;
extern KWIN_EXPORT glUniform1fv_func glUniform1fv;
extern KWIN_EXPORT glUniform2fv_func glUniform2fv;
extern KWIN_EXPORT glValidateProgram_func glValidateProgram;
extern KWIN_EXPORT glGetUniformLocation_func glGetUniformLocation;
extern KWIN_EXPORT glVertexAttrib1f_func glVertexAttrib1f;
extern KWIN_EXPORT glGetAttribLocation_func glGetAttribLocation;
} // namespace

View file

@ -246,13 +246,13 @@ void Scene::paintWindow( Window* w, int mask, QRegion region )
}
// the function that'll be eventually called by paintWindow() above
void Scene::finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
void Scene::finalPaintWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data )
{
effects->drawWindow( w, mask, region, data );
}
// will be eventually called from drawWindow()
void Scene::finalDrawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
void Scene::finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data )
{
w->sceneWindow()->performPaint( mask, region, data );
}

14
scene.h
View file

@ -15,15 +15,15 @@ License. See the file "COPYING" for the exact licensing terms.
#include "toplevel.h"
#include "utils.h"
#include "kwineffects.h"
namespace KWin
{
class Workspace;
class Deleted;
class WindowPaintData;
class ScreenPaintData;
class EffectWindow;
class EffectWindowImpl;
class EffectHandlerImpl;
// The base class for compositing backends.
class Scene
@ -32,6 +32,8 @@ class Scene
Scene( Workspace* ws );
virtual ~Scene() = 0;
class Window;
virtual CompositingType compositingType() const = 0;
// Repaints the given screen areas, windows provides the stacking order.
// The entry point for the main part of the painting pass.
virtual void paint( QRegion damage, ToplevelList windows ) = 0;
@ -76,7 +78,7 @@ class Scene
protected:
// shared implementation, starts painting the screen
void paintScreen( int* mask, QRegion* region );
friend class EffectsHandler;
friend class EffectsHandlerImpl;
// called after all effects had their paintScreen() called
void finalPaintScreen( int mask, QRegion region, ScreenPaintData& data );
// shared implementation of painting the screen in the generic
@ -87,11 +89,11 @@ class Scene
// paint the background (not the desktop background - the whole background)
virtual void paintBackground( QRegion region ) = 0;
// called after all effects had their paintWindow() called
void finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
void finalPaintWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data );
// shared implementation, starts painting the window
virtual void paintWindow( Window* w, int mask, QRegion region );
// called after all effects had their drawWindow() called
void finalDrawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data );
// infinite region, i.e. everything
static QRegion infiniteRegion();
// compute time since the last repaint

View file

@ -22,6 +22,7 @@ class SceneBasic
public:
SceneBasic( Workspace* ws );
virtual ~SceneBasic();
virtual CompositingType compositingType() const { return NoCompositing; }
virtual void paint( QRegion damage, ToplevelList windows );
protected:
virtual void paintBackground( QRegion region );

View file

@ -62,7 +62,6 @@ Sources and other compositing managers:
#include "client.h"
#include "deleted.h"
#include "effects.h"
#include "glutils.h"
#include <sys/ipc.h>
#include <sys/shm.h>
@ -717,6 +716,10 @@ SceneOpenGL::Texture::Texture( const Pixmap& pix, const QSize& size, int depth )
load( pix, size, depth );
}
SceneOpenGL::Texture::~Texture()
{
}
void SceneOpenGL::Texture::init()
{
bound_glxpixmap = None;

View file

@ -13,7 +13,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "scene.h"
#include "glutils.h"
#include "kwinglutils.h"
#ifdef HAVE_OPENGL
@ -32,6 +32,7 @@ class SceneOpenGL
class Window;
SceneOpenGL( Workspace* ws );
virtual ~SceneOpenGL();
virtual CompositingType compositingType() const { return OpenGLCompositing; }
virtual void paint( QRegion damage, ToplevelList windows );
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );
@ -87,6 +88,7 @@ class SceneOpenGL::Texture
public:
Texture();
Texture( const Pixmap& pix, const QSize& size, int depth );
virtual ~Texture();
using GLTexture::load;
virtual bool load( const Pixmap& pix, const QSize& size, int depth,

View file

@ -29,6 +29,7 @@ class SceneXrender
public:
SceneXrender( Workspace* ws );
virtual ~SceneXrender();
virtual CompositingType compositingType() const { return XRenderCompositing; }
virtual void paint( QRegion damage, ToplevelList windows );
virtual void windowGeometryShapeChanged( Toplevel* );
virtual void windowOpacityChanged( Toplevel* );

View file

@ -296,6 +296,8 @@ void Toplevel::setOpacity( double new_opacity )
{
double old_opacity = opacity();
new_opacity = qBound( 0.0, new_opacity, 1.0 );
if( old_opacity == new_opacity )
return;
info->setOpacity( static_cast< unsigned long >( new_opacity * 0xffffffff ));
if( compositing())
{

View file

@ -24,7 +24,7 @@ namespace KWin
{
class Workspace;
class EffectWindow;
class EffectWindowImpl;
class Toplevel
: public QObject, public KDecorationDefines
@ -97,7 +97,7 @@ class Toplevel
void resetRepaints( const QRect& r );
QRegion damage() const;
void resetDamage( const QRect& r );
EffectWindow* effectWindow();
EffectWindowImpl* effectWindow();
protected:
virtual ~Toplevel();
@ -137,7 +137,7 @@ class Toplevel
QRegion damage_region; // damage is really damaged window (XDamage) and texture needs
QRegion repaints_region; // updating, repaint just requires repaint of that area
bool is_shape;
EffectWindow* effect_window;
EffectWindowImpl* effect_window;
QByteArray resource_name;
QByteArray resource_class;
QByteArray client_machine;
@ -322,7 +322,7 @@ inline bool Toplevel::hasAlpha() const
}
inline
EffectWindow* Toplevel::effectWindow()
EffectWindowImpl* Toplevel::effectWindow()
{
return effect_window;
}

161
utils.cpp
View file

@ -25,11 +25,13 @@ License. See the file "COPYING" for the exact licensing terms.
#include <assert.h>
#include <kdebug.h>
#include <kshortcut.h>
#include <kkeyserver.h>
#include <X11/Xlib.h>
#include <X11/extensions/shape.h>
#include <X11/Xatom.h>
#include <QX11Info>
#include <stdio.h>
#include "atoms.h"
@ -42,19 +44,68 @@ namespace KWin
#ifndef KCMRULES
// used to store the return values of
// XShapeQueryExtension.
// Necessary since shaped window are an extension to X
int Shape::kwin_shape_version = 0;
int Shape::kwin_shape_event = 0;
bool Extensions::has_shape = false;
int Extensions::shape_event_base = 0;
bool Extensions::has_randr = false;
int Extensions::randr_event_base = 0;
bool Extensions::has_damage = false;
int Extensions::damage_event_base = 0;
bool Extensions::has_composite = false;
bool Extensions::has_composite_overlay = false;
bool Extensions::has_fixes = false;
// does the window w need a shape combine mask around it?
bool Shape::hasShape( WId w)
void Extensions::init()
{
int dummy;
has_shape = XShapeQueryExtension( display(), &shape_event_base, &dummy);
#ifdef HAVE_XRANDR
has_randr = XRRQueryExtension( display(), &randr_event_base, &dummy );
if( has_randr )
{
int major, minor;
XRRQueryVersion( display(), &major, &minor );
has_randr = ( major > 1 || ( major == 1 && minor >= 1 ) );
}
#else
has_randr = false;
#endif
#ifdef HAVE_XDAMAGE
has_damage = XDamageQueryExtension( display(), &damage_event_base, &dummy );
#else
has_damage = false;
#endif
#ifdef HAVE_XCOMPOSITE
has_composite = XCompositeQueryExtension( display(), &dummy, &dummy );
if( has_composite )
{
int major, minor;
XCompositeQueryVersion( display(), &major, &minor );
has_composite = ( major > 0 || minor >= 2 );
has_composite_overlay = ( major > 0 || minor >= 3 );
}
#else
has_composite = false;
has_composite_overlay = false;
#endif
#ifdef HAVE_XFIXES
has_fixes = XFixesQueryExtension( display(), &dummy, &dummy );
#else
has_fixes = false;
#endif
}
int Extensions::shapeNotifyEvent()
{
return shape_event_base + ShapeNotify;
}
// does the window w need a shape combine mask around it?
bool Extensions::hasShape( Window w )
{
int xws, yws, xbs, ybs;
unsigned int wws, hws, wbs, hbs;
int boundingShaped = 0, clipShaped = 0;
if (!available())
if( !Extensions::shapeAvailable())
return false;
XShapeQueryExtents(display(), w,
&boundingShaped, &xws, &yws, &wws, &hws,
@ -62,21 +113,22 @@ bool Shape::hasShape( WId w)
return boundingShaped != 0;
}
int Shape::shapeEvent()
int Extensions::randrNotifyEvent()
{
return kwin_shape_event;
#ifdef HAVE_XRANDR
return randr_event_base + RRScreenChangeNotify;
#else
return 0;
#endif
}
void Shape::init()
int Extensions::damageNotifyEvent()
{
kwin_shape_version = 0;
int dummy;
if( !XShapeQueryExtension( display(), &kwin_shape_event, &dummy ))
return;
int major, minor;
if( !XShapeQueryVersion( display(), &major, &minor ))
return;
kwin_shape_version = major * 0x10 + minor;
#ifdef HAVE_XDAMAGE
return damage_event_base + XDamageNotify;
#else
return 0;
#endif
}
void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move,
@ -301,6 +353,76 @@ bool grabbedXServer()
return server_grab_count > 0;
}
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
int qtToX11Button( Qt::MouseButton button )
{
if( button == Qt::LeftButton )
return Button1;
else if( button == Qt::MidButton )
return Button2;
else if( button == Qt::RightButton )
return Button3;
return AnyButton; // 0
}
Qt::MouseButton x11ToQtMouseButton( int button )
{
if( button == Button1 )
return Qt::LeftButton;
if( button == Button2 )
return Qt::MidButton;
if( button == Button3 )
return Qt::RightButton;
return Qt::NoButton;
}
int qtToX11State( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers )
{
int ret = 0;
if( buttons & Qt::LeftButton )
ret |= Button1Mask;
if( buttons & Qt::MidButton )
ret |= Button2Mask;
if( buttons & Qt::RightButton )
ret |= Button3Mask;
if( modifiers & Qt::ShiftModifier )
ret |= ShiftMask;
if( modifiers & Qt::ControlModifier )
ret |= ControlMask;
if( modifiers & Qt::AltModifier )
ret |= KKeyServer::modXAlt();
if( modifiers & Qt::MetaModifier )
ret |= KKeyServer::modXMeta();
return ret;
}
Qt::MouseButtons x11ToQtMouseButtons( int state )
{
Qt::MouseButtons ret = 0;
if( state & Button1Mask )
ret |= Qt::LeftButton;
if( state & Button2Mask )
ret |= Qt::MidButton;
if( state & Button3Mask )
ret |= Qt::RightButton;
return ret;
}
Qt::KeyboardModifiers x11ToQtKeyboardModifiers( int state )
{
Qt::KeyboardModifiers ret = 0;
if( state & ShiftMask )
ret |= Qt::ShiftModifier;
if( state & ControlMask )
ret |= Qt::ControlModifier;
if( state & KKeyServer::modXAlt())
ret |= Qt::AltModifier;
if( state & KKeyServer::modXMeta())
ret |= Qt::MetaModifier;
return ret;
}
#endif
bool isLocalMachine( const QByteArray& host )
@ -369,7 +491,6 @@ void ShortcutDialog::accept()
}
#endif //0
#endif //KCMRULES
} // namespace
#ifndef KCMRULES

148
utils.h
View file

@ -12,6 +12,33 @@ License. See the file "COPYING" for the exact licensing terms.
#ifndef KWIN_UTILS_H
#define KWIN_UTILS_H
#include <config.h>
#include <config-X11.h>
#include <config-kwin.h>
#include <X11/Xlib.h>
#ifdef HAVE_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XCOMPOSITE
#include <X11/extensions/Xcomposite.h>
#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3
#define HAVE_XCOMPOSITE_OVERLAY
#endif
#endif
#ifdef HAVE_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif
#ifdef HAVE_XFIXES
#include <X11/extensions/Xfixes.h>
#endif
#include <fixx11h.h>
#include <QWidget>
#include <kmanagerselection.h>
#include <netwm_def.h>
@ -19,12 +46,23 @@ License. See the file "COPYING" for the exact licensing terms.
#include <limits.h>
#include <QX11Info>
#include <kwinglobals.h>
namespace KWin
{
#ifndef HAVE_XDAMAGE
typedef long Damage;
struct XDamageNotifyEvent
{
};
#endif
const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
| NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
| NET::UtilityMask | NET::SplashMask;
| NET::UtilityMask | NET::SplashMask | NET::DropdownMenuMask | NET::PopupMenuMask
| NET::TooltipMask | NET::NotificationMask | NET::ComboBoxMask | NET::DNDIconMask;
const long ClientWinMask = KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
@ -39,12 +77,21 @@ const long ClientWinMask = KeyPressMask | KeyReleaseMask |
const QPoint invalidPoint( INT_MIN, INT_MIN );
class Toplevel;
class Client;
class Unmanaged;
class Deleted;
class Group;
class Options;
typedef QList< Toplevel* > ToplevelList;
typedef QList< const Toplevel* > ConstToplevelList;
typedef QList< Client* > ClientList;
typedef QList< const Client* > ConstClientList;
typedef QList< Unmanaged* > UnmanagedList;
typedef QList< const Unmanaged* > ConstUnmanagedList;
typedef QList< Deleted* > DeletedList;
typedef QList< const Deleted* > ConstDeletedList;
typedef QList< Group* > GroupList;
typedef QList< const Group* > ConstGroupList;
@ -87,19 +134,7 @@ enum allowed_t { Allowed };
// some enums to have more readable code, instead of using bools
enum ForceGeometry_t { NormalGeometrySet, ForceGeometrySet };
// Areas, mostly related to Xinerama
enum clientAreaOption
{
PlacementArea, // geometry where a window will be initially placed after being mapped
MovementArea, // ??? window movement snapping area? ignore struts
MaximizeArea, // geometry to which a window will be maximized
MaximizeFullArea, // like MaximizeArea, but ignore struts - used e.g. for topmenu
FullScreenArea, // area for fullscreen windows
// these below don't depend on xinerama settings
WorkArea, // whole workarea (all screens together)
FullArea, // whole area (all screens together), ignore struts
ScreenArea // one whole screen, ignore struts
};
enum ShadeMode
{
@ -109,24 +144,32 @@ enum ShadeMode
ShadeActivated // "shaded", but visible due to alt+tab to the window
};
class Shape
class Extensions
{
public:
static bool available() { return kwin_shape_version > 0; }
static int version() { return kwin_shape_version; } // as 16*major+minor, i.e. two hex digits
static bool hasShape( WId w);
static int shapeEvent();
static void init();
static bool shapeAvailable() { return has_shape; }
static int shapeNotifyEvent();
static bool randrAvailable() { return has_randr; }
static int randrNotifyEvent();
static bool damageAvailable() { return has_damage; }
static int damageNotifyEvent();
static bool compositeAvailable() { return has_composite; }
static bool compositeOverlayAvailable() { return has_composite && has_composite_overlay; }
static bool fixesAvailable() { return has_fixes; }
static bool hasShape( Window w );
private:
static int kwin_shape_version;
static int kwin_shape_event;
static bool has_shape;
static int shape_event_base;
static bool has_randr;
static int randr_event_base;
static bool has_damage;
static int damage_event_base;
static bool has_composite;
static bool has_composite_overlay;
static bool has_fixes;
};
// compile with XShape older than 1.0
#ifndef ShapeInput
const int ShapeInput = 2;
#endif
class Motif
{
public:
@ -196,12 +239,6 @@ void grabXServer();
void ungrabXServer();
bool grabbedXServer();
inline
Display* display()
{
return QX11Info::display();
}
inline
Window rootWindow()
{
@ -214,17 +251,10 @@ Window xTime()
return QX11Info::appTime();
}
inline
int displayWidth()
{
return XDisplayWidth( display(), DefaultScreen( display()));
}
inline
int displayHeight()
{
return XDisplayHeight( display(), DefaultScreen( display()));
}
class Scene;
extern Scene* scene;
inline bool compositing() { return scene != NULL; }
// the docs say it's UrgencyHint, but it's often #defined as XUrgencyHint
#ifndef UrgencyHint
@ -232,28 +262,28 @@ int displayHeight()
#endif
// for STL-like algo's
#define KWIN_CHECK_PREDICATE( name, check ) \
#define KWIN_CHECK_PREDICATE( name, cls, check ) \
struct name \
{ \
inline bool operator()( const Client* cl ) { return check; } \
inline bool operator()( const cls* cl ) { return check; }; \
}
#define KWIN_COMPARE_PREDICATE( name, type, check ) \
#define KWIN_COMPARE_PREDICATE( name, cls, type, check ) \
struct name \
{ \
typedef type type_helper; /* in order to work also with type being 'const Client*' etc. */ \
inline name( const type_helper& compare_value ) : value( compare_value ) {} \
inline bool operator()( const Client* cl ) { return check; } \
inline name( const type_helper& compare_value ) : value( compare_value ) {}; \
inline bool operator()( const cls* cl ) { return check; }; \
const type_helper& value; \
}
#define KWIN_PROCEDURE( name, action ) \
#define KWIN_PROCEDURE( name, cls, action ) \
struct name \
{ \
inline void operator()( Client* cl ) { action; } \
inline void operator()( cls* cl ) { action; }; \
}
KWIN_CHECK_PREDICATE( TruePredicate, cl == cl /*true, avoid warning about 'cl' */ );
KWIN_CHECK_PREDICATE( TruePredicate, Client, cl == cl /*true, avoid warning about 'cl' */ );
template< typename T >
Client* findClientInList( const ClientList& list, T predicate )
@ -266,6 +296,17 @@ Client* findClientInList( const ClientList& list, T predicate )
return NULL;
}
template< typename T >
Unmanaged* findUnmanagedInList( const UnmanagedList& list, T predicate )
{
for ( UnmanagedList::ConstIterator it = list.begin(); it != list.end(); ++it)
{
if ( predicate( const_cast< const Unmanaged* >( *it)))
return *it;
}
return NULL;
}
inline
int timestampCompare( Time time1, Time time2 ) // like strcmp()
{
@ -280,7 +321,12 @@ Time timestampDiff( Time time1, Time time2 ) // returns time2 - time1
bool isLocalMachine( const QByteArray& host );
void checkNonExistentClients();
// converting between X11 mouse/keyboard state mask and Qt button/keyboard states
int qtToX11Button( Qt::MouseButton button );
Qt::MouseButton x11ToQtMouseButton( int button );
int qtToX11State( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers );
Qt::MouseButtons x11ToQtMouseButtons( int state );
Qt::KeyboardModifiers x11ToQtKeyboardModifiers( int state );
#ifndef KCMRULES
// Qt dialogs emit no signal when closed :(