Make your windows explode!

Add ExplosionEffect which makes the windows blow up into small pieces when they're closed.
  In the future this could be used only when user kills (an unresponsive) window.

svn path=/branches/work/kwin_composite/; revision=643135
This commit is contained in:
Rivo Laks 2007-03-16 13:02:47 +00:00
parent 19e7ebe1d8
commit aae967c5f9
8 changed files with 463 additions and 6 deletions

View file

@ -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

View file

@ -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<PresentWindowsEffect>);
#ifdef HAVE_OPENGL
registerEffect("WavyWindows", new GenericEffectFactory<WavyWindowsEffect>);
registerEffect("Explosion", new GenericEffectFactory<ExplosionEffect>);
#endif
registerEffect("MinimizeAnimation", new GenericEffectFactory<MinimizeAnimationEffect>);
registerEffect("Howto", new GenericEffectFactory<HowtoEffect>);

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -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
}

View file

@ -0,0 +1,5 @@
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}

230
effects/explosioneffect.cpp Normal file
View file

@ -0,0 +1,230 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
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 <scene_opengl.h>
#include <workspace.h>
#include <client.h>
#include <glutils.h>
#include <deleted.h>
#include <QString>
#include <KStandardDirs>
#include <math.h>
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

57
effects/explosioneffect.h Normal file
View file

@ -0,0 +1,57 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
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 <effects.h>
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