diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e78dce2a1..9a1305526e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,22 @@ add_subdirectory( pics ) add_subdirectory( clients ) 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 ############### @@ -35,28 +50,134 @@ 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 + glutils.cpp + glutils_funcs.cpp + deleted.cpp + effects.cpp + effects/fade.cpp + effects/maketransparent.cpp + effects/scalein.cpp + effects/shakymove.cpp + effects/shiftworkspaceup.cpp + effects/howto.cpp + effects/dialogparent.cpp + effects/showfps.cpp + effects/zoom.cpp + effects/presentwindows.cpp + effects/minimizeanimation.cpp + effects/desktopchangeslide.cpp + effects/boxswitch.cpp + effects/fallapart.cpp + effects/drunken.cpp + effects/test_input.cpp + effects/test_thumbnail.cpp + ) + +if( CAPTURY_FOUND ) + set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} + effects/videorecord.cpp + ) + include_directories(${CAPTURY_INCLUDES}) +endif( CAPTURY_FOUND ) + +if(HAVE_OPENGL) + set(kwin_KDEINIT_SRCS ${kwin_KDEINIT_SRCS} + effects/wavywindows.cpp + effects/explosioneffect.cpp + ) +endif(HAVE_OPENGL) qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml workspace.h KWinInternal::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} ) +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/effects.cpp b/effects.cpp index 021020e143..47ac3f1a61 100644 --- a/effects.cpp +++ b/effects.cpp @@ -19,6 +19,7 @@ License. See the file "COPYING" for the exact licensing terms. #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" @@ -183,6 +184,7 @@ EffectsHandler::EffectsHandler() registerEffect("PresentWindows", new GenericEffectFactory); #ifdef HAVE_OPENGL registerEffect("WavyWindows", new GenericEffectFactory); + registerEffect("Explosion", new GenericEffectFactory); #endif registerEffect("MinimizeAnimation", new GenericEffectFactory); registerEffect("Howto", new GenericEffectFactory); diff --git a/effects/data/explosion-end.png b/effects/data/explosion-end.png new file mode 100644 index 0000000000..433b9b274f Binary files /dev/null and b/effects/data/explosion-end.png differ diff --git a/effects/data/explosion-start.png b/effects/data/explosion-start.png new file mode 100644 index 0000000000..2da11af633 Binary files /dev/null and b/effects/data/explosion-start.png differ diff --git a/effects/data/explosion.frag b/effects/data/explosion.frag new file mode 100644 index 0000000000..863ea50b84 --- /dev/null +++ b/effects/data/explosion.frag @@ -0,0 +1,42 @@ +uniform sampler2D winTexture; +uniform sampler2D startOffsetTexture; +uniform sampler2D endOffsetTexture; +uniform float factor; +uniform float scale; + +const float regionTexSize = 512.0; + + +vec2 getOffset(sampler2D texture, vec2 pos) +{ + return (texture2D(texture, pos / regionTexSize).xy - 0.5) / (5.0 / 256.0); +} + +void main() +{ + // Original (unscaled) position in pixels + vec2 origpos = gl_TexCoord[0].xy; + // Position in pixels on the scaled window + vec2 pos = origpos * scale; + // Start/end position of current region + vec2 rstart = origpos + getOffset(startOffsetTexture, origpos); + vec2 rend = origpos + getOffset(endOffsetTexture, origpos); + float alpha = texture2D(startOffsetTexture, origpos / regionTexSize).b; + // Distance from the start of the region + vec2 dist = pos - rstart*scale; + if(any(greaterThan(dist, rend-rstart))) + discard;//alpha = 0.0; + + vec4 transformedtexcoord = vec4(rstart + dist, vec2(1.0)) * gl_TextureMatrix[0]; + vec3 tex = texture2D(winTexture, transformedtexcoord.xy).rgb; +#if 0 + // ATM we ignore custom opacity values because Fade effect fades out the + // window which results in the explosion being way too quick. Once there's + // a way to suppress Fade effect when ExplosionEffect is active, we can + // use the custom opacity again + gl_FragColor = vec4(tex, (1.0 - factor*factor) * alpha * opacity); +#else + gl_FragColor = vec4(tex, (1.0 - factor*factor) * alpha); +#endif +} + diff --git a/effects/data/explosion.vert b/effects/data/explosion.vert new file mode 100644 index 0000000000..f1bef4e5ed --- /dev/null +++ b/effects/data/explosion.vert @@ -0,0 +1,5 @@ +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +} diff --git a/effects/explosioneffect.cpp b/effects/explosioneffect.cpp new file mode 100644 index 0000000000..3785e25f49 --- /dev/null +++ b/effects/explosioneffect.cpp @@ -0,0 +1,230 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Rivo Laks + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + + +#include "explosioneffect.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + + +namespace KWinInternal +{ + +ExplosionEffect::ExplosionEffect() : Effect() + { + mActiveAnimations = 0; + mValid = true; + mInited = false; + } + +bool ExplosionEffect::loadData() +{ + mInited = true; + QString shadername("explosion"); + QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/explosion.frag"); + QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/explosion.vert"); + if(fragmentshader.isEmpty() || vertexshader.isEmpty()) + { + kError() << k_funcinfo << "Couldn't locate shader files" << endl; + return false; + } + + mShader = new GLShader(vertexshader, fragmentshader); + if(!mShader->isValid()) + { + kError() << k_funcinfo << "The shader failed to load!" << endl; + return false; + } + else + { + mShader->bind(); + mShader->setUniform("winTexture", 0); + mShader->setUniform("startOffsetTexture", 4); + mShader->setUniform("endOffsetTexture", 5); + mShader->unbind(); + } + + if((mStartOffsetTex = loadTexture("explosion-start.png")) == 0) + return false; + if((mEndOffsetTex = loadTexture("explosion-end.png")) == 0) + return false; + + return true; + } + +unsigned int ExplosionEffect::loadTexture(const QString& filename) +{ + QString fullfilename = KGlobal::dirs()->findResource("data", "kwin/" + filename); + if(fullfilename.isEmpty()) + { + kError() << k_funcinfo << "Couldn't find texture '" << filename << "'" << endl; + return 0; + } + + QImage img(fullfilename); + if(img.isNull()) + { + kError() << k_funcinfo << "Couldn't load image from file " << fullfilename << endl; + return 0; + } + img = convertToGLFormat(img); + + unsigned int tex; + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.width(), img.height(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, img.bits()); + glBindTexture(GL_TEXTURE_2D, 0); + return tex; +} + +QImage ExplosionEffect::convertToGLFormat(const QImage& img) const +{ + // This method has been copied from Qt's QGLWidget::convertToGLFormat() + QImage res = img.convertToFormat(QImage::Format_ARGB32); + res = res.mirrored(); + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + // Qt has ARGB; OpenGL wants RGBA + for (int i=0; i < res.height(); i++) { + uint *p = (uint*)res.scanLine(i); + uint *end = p + res.width(); + while (p < end) { + *p = (*p << 8) | ((*p >> 24) & 0xFF); + p++; + } + } + } + else { + // Qt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards) + res = res.rgbSwapped(); + } + return res; +} + +void ExplosionEffect::prePaintScreen( int* mask, QRegion* region, int time ) + { + if( mActiveAnimations > 0 ) + // We need to mark the screen as transformed. Otherwise the whole screen + // won't be repainted, resulting in artefacts + *mask |= Scene::PAINT_SCREEN_TRANSFORMED; + + effects->prePaintScreen(mask, region, time); + } + +void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time ) + { + if( mWindows.contains( w )) + { + mWindows[ w ] += time / 700.0; // complete change in 700ms + if( mWindows[ w ] < 1 ) + { + *mask |= Scene::PAINT_WINDOW_TRANSLUCENT | Scene::PAINT_WINDOW_TRANSFORMED; + *mask &= ~Scene::PAINT_WINDOW_OPAQUE; + w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DELETE ); + } + else + { + mWindows.remove( w ); + static_cast< Deleted* >( w->window())->unrefWindow(); + mActiveAnimations--; + } + } + + effects->prePaintWindow( w, mask, region, time ); + } + +void ExplosionEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + // Make sure we have OpenGL compositing and the window is vidible and not a + // special window + SceneOpenGL::Window* glwin = dynamic_cast< SceneOpenGL::Window* >( w->sceneWindow() ); + //Client* c = qobject_cast< Client* >( w->window() ); + bool useshader = ( mValid && glwin && mWindows.contains( w ) ); + if( useshader && !mInited ) + useshader = mValid = loadData(); + if( useshader ) + { + float maxscaleadd = 1.5f; + float scale = 1 + maxscaleadd*mWindows[w]; + //data.xTranslate = (f - 1)* + data.xScale = scale; + data.yScale = scale; + data.xTranslate += int( w->window()->width() / 2 * ( 1 - scale )); + data.yTranslate += int( w->window()->height() / 2 * ( 1 - scale )); + data.opacity *= 0.99; // Force blending + mShader->bind(); + mShader->setUniform("factor", (float)mWindows[w]); + mShader->setUniform("scale", scale); + glActiveTexture(GL_TEXTURE4); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mStartOffsetTex); + glActiveTexture(GL_TEXTURE5); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, mEndOffsetTex); + glActiveTexture(GL_TEXTURE0); + glwin->setShader(mShader); + } + + // Call the next effect. + effects->paintWindow( w, mask, region, data ); + + if( useshader ) + { + mShader->unbind(); + glActiveTexture(GL_TEXTURE4); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE5); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + } + } + +void ExplosionEffect::postPaintScreen() + { + if( mActiveAnimations > 0 ) + workspace()->addRepaintFull(); + + // Call the next effect. + effects->postPaintScreen(); + } + +void ExplosionEffect::windowClosed( EffectWindow* c ) + { + Client* cc = dynamic_cast< Client* >( c->window()); + if( cc == NULL || (cc->isOnCurrentDesktop() && !cc->isMinimized())) + { + mWindows[ c ] = 0; // count up to 1 + c->window()->addRepaintFull(); + static_cast< Deleted* >( c->window())->refWindow(); + mActiveAnimations++; + } + } + +void ExplosionEffect::windowDeleted( EffectWindow* c ) + { + mWindows.remove( c ); + } + +} // namespace + diff --git a/effects/explosioneffect.h b/effects/explosioneffect.h new file mode 100644 index 0000000000..3441def1b5 --- /dev/null +++ b/effects/explosioneffect.h @@ -0,0 +1,57 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Rivo Laks + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + +#ifndef KWIN_EXPLOSIONEFFECT_H +#define KWIN_EXPLOSIONEFFECT_H + +// Include with base class for effects. +#include + +namespace KWinInternal +{ + +class GLShader; + +/** + * Makes windows explode into small pieces when they're closed + **/ +class ExplosionEffect + : public Effect + { + public: + ExplosionEffect(); + + virtual void prePaintScreen( int* mask, QRegion* region, int time ); + virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time ); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void postPaintScreen(); + + virtual void windowClosed( EffectWindow* c ); + virtual void windowDeleted( EffectWindow* c ); + + + protected: + bool loadData(); + unsigned int loadTexture(const QString& filename); + QImage convertToGLFormat(const QImage& img) const; + + private: + GLShader* mShader; + unsigned int mStartOffsetTex; + unsigned int mEndOffsetTex; + QMap< const EffectWindow*, double > mWindows; + int mActiveAnimations; + bool mValid; + bool mInited; + }; + +} // namespace + +#endif