diff --git a/CMakeLists.txt b/CMakeLists.txt index b2a30deedc..f73baa76ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/composite.cpp b/composite.cpp index abbb0ece4d..4569d869d0 100644 --- a/composite.cpp +++ b/composite.cpp @@ -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 } diff --git a/effects.cpp b/effects.cpp index ce0a4a153c..1b33473e61 100644 --- a/effects.cpp +++ b/effects.cpp @@ -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 -#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); -#endif - registerEffect("ShowFps", new GenericEffectFactory); - registerEffect("Zoom", new GenericEffectFactory); - registerEffect("PresentWindows", new GenericEffectFactory); -#ifdef HAVE_OPENGL - registerEffect("WavyWindows", new GenericEffectFactory); - registerEffect("Explosion", new GenericEffectFactory); -#endif - registerEffect("MinimizeAnimation", new GenericEffectFactory); - registerEffect("Howto", new GenericEffectFactory); - registerEffect("MakeTransparent", new GenericEffectFactory); - registerEffect("ShakyMove", new GenericEffectFactory); - registerEffect("ShiftWorkspaceUp", new GenericEffectFactory); - registerEffect("Fade", new GenericEffectFactory); - registerEffect("ScaleIn", new GenericEffectFactory); - registerEffect("FallApart", new GenericEffectFactory); - registerEffect("Flame", new GenericEffectFactory); - registerEffect("DialogParent", new GenericEffectFactory); - registerEffect("DesktopChangeSlide", new GenericEffectFactory); - registerEffect("BoxSwitch", new GenericEffectFactory); - registerEffect("Drunken", new GenericEffectFactory); - registerEffect("TaskbarThumbnail", new GenericEffectFactory); - registerEffect("Shadow", new GenericEffectFactory); - - registerEffect("TestInput", new GenericEffectFactory); - registerEffect("TestThumbnail", new GenericEffectFactory); - - 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( 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( 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(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(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::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::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( toplevel )) + return c->caption(); + else + return ""; } -bool EffectWindow::isDeleted() const -{ +bool EffectWindowImpl::isMinimized() const + { + if( Client* c = dynamic_cast( toplevel )) + return c->isMinimized(); + else + return false; + } + +bool EffectWindowImpl::isDeleted() const + { return (dynamic_cast( 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( 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 diff --git a/effects.h b/effects.h index 0f6cc61f68..784a926376 100644 --- a/effects.h +++ b/effects.h @@ -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 + 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 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 diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt new file mode 100644 index 0000000000..f444ff413c --- /dev/null +++ b/effects/CMakeLists.txt @@ -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 ) diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index 9c39ae79a6..208ef71cb9 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -11,14 +11,14 @@ License. See the file "COPYING" for the exact licensing terms. #include "presentwindows.h" -#include -#include - #include #include #include +#include + #include +#include @@ -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::iterator it = mWindowData.begin(); + for( QHash::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 geometryRects; QList maxRowHeights; // Process rows @@ -307,15 +305,15 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(ClientList clie // Process columns for ( int j=0; j 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; diff --git a/effects/presentwindows.desktop b/effects/presentwindows.desktop new file mode 100644 index 0000000000..b6f065db53 --- /dev/null +++ b/effects/presentwindows.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=PresentWindows +X-KDE-Library=kwin4_effect_builtins diff --git a/effects/presentwindows.h b/effects/presentwindows.h index f3e637bbd5..7603b59312 100644 --- a/effects/presentwindows.h +++ b/effects/presentwindows.h @@ -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 +#include 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 mWindowData; + QHash mWindowData; ElectricBorder borderActivate; ElectricBorder borderActivateAll; }; + KWIN_EFFECT( PresentWindows, PresentWindowsEffect ); + } // namespace #endif diff --git a/effects/shadow.cpp b/effects/shadow.cpp index 6564cdd6a0..0f47ced977 100644 --- a/effects/shadow.cpp +++ b/effects/shadow.cpp @@ -10,9 +10,7 @@ License. See the file "COPYING" for the exact licensing terms. #include "shadow.h" -#ifdef HAVE_OPENGL -#include -#endif +#include 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 diff --git a/effects/shadow.desktop b/effects/shadow.desktop new file mode 100644 index 0000000000..90a9c6c4b5 --- /dev/null +++ b/effects/shadow.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Shadow +X-KDE-Library=kwin4_effect_builtins diff --git a/effects/shadow.h b/effects/shadow.h index 8b3c2bfd25..59fb679099 100644 --- a/effects/shadow.h +++ b/effects/shadow.h @@ -11,7 +11,7 @@ License. See the file "COPYING" for the exact licensing terms. #ifndef KWIN_SHADOW_H #define KWIN_SHADOW_H -#include +#include namespace KWin { @@ -30,6 +30,8 @@ class ShadowEffect int shadowXOffset, shadowYOffset; }; + KWIN_EFFECT( Shadow, ShadowEffect ) + } // namespace #endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 46ab879367..bf87caddc8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -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 diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp new file mode 100644 index 0000000000..ec4e38a773 --- /dev/null +++ b/lib/kwineffects.cpp @@ -0,0 +1,472 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2006 Lubos Lunak + +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 +#include + +#include "kdebug.h" +#include "klibloader.h" +#include "kdesktopfile.h" +#include "kconfiggroup.h" +#include "kstandarddirs.h" + +#include + +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(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(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 diff --git a/lib/kwineffects.h b/lib/kwineffects.h new file mode 100644 index 0000000000..d5b56bf466 --- /dev/null +++ b/lib/kwineffects.h @@ -0,0 +1,300 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2006 Lubos Lunak + +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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +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 diff --git a/lib/kwinglobals.cpp b/lib/kwinglobals.cpp new file mode 100644 index 0000000000..edf3f46d55 --- /dev/null +++ b/lib/kwinglobals.cpp @@ -0,0 +1,43 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2006 Lubos Lunak + +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 + +#include "kdebug.h" + +#include + + +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 + diff --git a/lib/kwinglobals.h b/lib/kwinglobals.h new file mode 100644 index 0000000000..5f68baf4e2 --- /dev/null +++ b/lib/kwinglobals.h @@ -0,0 +1,122 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2006 Lubos Lunak + +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 +#include + +#include + +#include +#include + +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 diff --git a/glutils.cpp b/lib/kwinglutils.cpp similarity index 99% rename from glutils.cpp rename to lib/kwinglutils.cpp index 7e51c25c2b..43afde79b3 100644 --- a/glutils.cpp +++ b/lib/kwinglutils.cpp @@ -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 #include #include #include @@ -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]; diff --git a/glutils.h b/lib/kwinglutils.h similarity index 85% rename from glutils.h rename to lib/kwinglutils.h index 7d0fcddf5d..9bc9aaa3bc 100644 --- a/glutils.h +++ b/lib/kwinglutils.h @@ -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 +#include #ifdef HAVE_OPENGL #include #include +#include #endif -#include "glutils_funcs.h" +#include +#include +#include +#include + +#include 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); diff --git a/glutils_funcs.cpp b/lib/kwinglutils_funcs.cpp similarity index 99% rename from glutils_funcs.cpp rename to lib/kwinglutils_funcs.cpp index 5d2536c7ac..a3ba57fd36 100644 --- a/glutils_funcs.cpp +++ b/lib/kwinglutils_funcs.cpp @@ -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 diff --git a/glutils_funcs.h b/lib/kwinglutils_funcs.h similarity index 64% rename from glutils_funcs.h rename to lib/kwinglutils_funcs.h index 016e73d4d8..72a97a556f 100644 --- a/glutils_funcs.h +++ b/lib/kwinglutils_funcs.h @@ -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 + +#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 diff --git a/scene.cpp b/scene.cpp index 4a1721c214..55d8fbc5c6 100644 --- a/scene.cpp +++ b/scene.cpp @@ -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 ); } diff --git a/scene.h b/scene.h index be5f5dd78b..a26405c4bd 100644 --- a/scene.h +++ b/scene.h @@ -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 diff --git a/scene_basic.h b/scene_basic.h index 87e95ceb29..8229ab3653 100644 --- a/scene_basic.h +++ b/scene_basic.h @@ -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 ); diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 807bc9e411..d2b406c6d9 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -62,7 +62,6 @@ Sources and other compositing managers: #include "client.h" #include "deleted.h" #include "effects.h" -#include "glutils.h" #include #include @@ -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; diff --git a/scene_opengl.h b/scene_opengl.h index 8adc784582..be6c141a1c 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -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, diff --git a/scene_xrender.h b/scene_xrender.h index 4fa919ab5b..099ab488b7 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -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* ); diff --git a/toplevel.cpp b/toplevel.cpp index d88e3d78b5..894d782784 100644 --- a/toplevel.cpp +++ b/toplevel.cpp @@ -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()) { diff --git a/toplevel.h b/toplevel.h index b3c3540bbd..d0e4438ab4 100644 --- a/toplevel.h +++ b/toplevel.h @@ -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; } diff --git a/utils.cpp b/utils.cpp index 8158dad77f..19c264b90b 100644 --- a/utils.cpp +++ b/utils.cpp @@ -25,11 +25,13 @@ License. See the file "COPYING" for the exact licensing terms. #include #include #include +#include #include #include #include #include + #include #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 diff --git a/utils.h b/utils.h index b6b9ada648..1c16ba2df7 100644 --- a/utils.h +++ b/utils.h @@ -12,6 +12,33 @@ License. See the file "COPYING" for the exact licensing terms. #ifndef KWIN_UTILS_H #define KWIN_UTILS_H +#include +#include +#include + +#include + +#ifdef HAVE_XRANDR +#include +#endif + +#ifdef HAVE_XCOMPOSITE +#include +#if XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR >= 3 +#define HAVE_XCOMPOSITE_OVERLAY +#endif +#endif + +#ifdef HAVE_XDAMAGE +#include +#endif + +#ifdef HAVE_XFIXES +#include +#endif + +#include + #include #include #include @@ -19,12 +46,23 @@ License. See the file "COPYING" for the exact licensing terms. #include #include +#include + + 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 :(