Added feature to only invert the colours of selected windows

Fixed shader alpha blending
CCMAIL: kwin@kde.org

svn path=/trunk/KDE/kdebase/workspace/; revision=853224
This commit is contained in:
Lucas Murray 2008-08-27 12:20:34 +00:00
parent faf7477fdb
commit 9a52d3c709
7 changed files with 147 additions and 21 deletions

View file

@ -1,18 +1,27 @@
uniform sampler2D sceneTex;
uniform sampler2D winTexture;
uniform float textureWidth;
uniform float textureHeight;
uniform float opacity;
uniform float brightness;
uniform float saturation;
// Converts pixel coordinates to texture coordinates
vec2 pix2tex(vec2 pix)
vec2 pix2tex( vec2 pix )
{
return vec2(pix.x / textureWidth, 1.0 - pix.y / textureHeight);
return vec2( pix.s / textureWidth, pix.t / textureHeight );
}
void main()
{
vec3 tex = texture2D(sceneTex, pix2tex(gl_TexCoord[0].xy)).rgb;
vec4 tex = texture2D( winTexture, pix2tex( gl_TexCoord[0].st ));
tex = vec4( vec3( 1.0 ) - tex.rgb, tex.a * opacity );
if( saturation != 1.0 )
{
vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 );
desaturated = vec3( dot( desaturated, tex.rgb ));
tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation );
}
tex.rgb = tex.rgb * vec3( brightness );
gl_FragColor = vec4(vec3(1.0) - tex, 1.0);
gl_FragColor = tex;
}

View file

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

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,10 +21,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "invert.h"
#include <kwinglutils.h>
#include <kactioncollection.h>
#include <kaction.h>
#include <klocale.h>
#include <kdebug.h>
#include <kwinshadereffect.h>
#include <KStandardDirs>
namespace KWin
{
@ -31,19 +35,107 @@ namespace KWin
KWIN_EFFECT( invert, InvertEffect )
KWIN_EFFECT_SUPPORTED( invert, ShaderEffect::supported() )
InvertEffect::InvertEffect() : QObject(), ShaderEffect("invert")
InvertEffect::InvertEffect()
: m_inited( false ),
m_valid( true ),
m_shader( NULL ),
m_allWindows( false )
{
KActionCollection* actionCollection = new KActionCollection( this );
KAction* a = (KAction*)actionCollection->addAction( "Invert" );
a->setText( i18n("Toggle Invert Effect" ));
a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_I));
connect(a, SIGNAL(triggered(bool)), this, SLOT(toggle()));
a->setText( i18n( "Toggle Invert Effect" ));
a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_I ));
connect(a, SIGNAL( triggered(bool) ), this, SLOT( toggle() ));
KAction* b = (KAction*)actionCollection->addAction( "InvertWindow" );
b->setText( i18n( "Toggle Invert Effect On Window" ));
b->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_U ));
connect(b, SIGNAL( triggered(bool) ), this, SLOT( toggleWindow() ));
}
InvertEffect::~InvertEffect()
{
delete m_shader;
}
bool InvertEffect::loadData()
{
m_inited = true;
QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/invert.frag");
QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/invert.vert");
if(fragmentshader.isEmpty() || vertexshader.isEmpty())
{
kError(1212) << "Couldn't locate shader files" << endl;
return false;
}
m_shader = new GLShader(vertexshader, fragmentshader);
if( !m_shader->isValid() )
{
kError(1212) << "The shader failed to load!" << endl;
return false;
}
else
{
m_shader->bind();
m_shader->setUniform("winTexture", 0);
m_shader->unbind();
}
return true;
}
void InvertEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
// Load if we haven't already
if( m_valid && !m_inited )
m_valid = loadData();
bool useShader = m_valid && ( m_allWindows != m_windows.contains( w ));
if( useShader )
{
m_shader->bind();
int texw = w->width();
int texh = w->height();
if( !GLTexture::NPOTTextureSupported() )
{
kWarning( 1212 ) << "NPOT textures not supported, wasting some memory" ;
texw = nearestPowerOfTwo(texw);
texh = nearestPowerOfTwo(texh);
}
m_shader->setUniform("textureWidth", (float)texw);
m_shader->setUniform("textureHeight", (float)texh);
data.shader = m_shader;
}
effects->paintWindow( w, mask, region, data );
if( useShader )
m_shader->unbind();
}
void InvertEffect::windowClosed( EffectWindow* w )
{
m_windows.removeOne( w );
}
void InvertEffect::toggle()
{
setEnabled( !isEnabled());
m_allWindows = !m_allWindows;
effects->addRepaintFull();
}
void InvertEffect::toggleWindow()
{
if( !m_windows.contains( effects->activeWindow() ))
m_windows.append( effects->activeWindow() );
else
m_windows.removeOne( effects->activeWindow() );
effects->activeWindow()->addRepaintFull();
}
} // namespace

View file

@ -116,10 +116,10 @@ Icon=preferences-system-windows-effect-invert
Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Rivo Laks
X-KDE-PluginInfo-Email=rivolaks@hot.ee
X-KDE-PluginInfo-Author=Rivo Laks & Lucas Murray
X-KDE-PluginInfo-Email=rivolaks@hot.ee & lmurray@undefinedfire.com
X-KDE-PluginInfo-Name=kwin4_effect_invert
X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Version=0.2.0
X-KDE-PluginInfo-Category=Accessibility
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -21,22 +22,40 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_INVERT_H
#define KWIN_INVERT_H
#include <kwinshadereffect.h>
#include <kwineffects.h>
namespace KWin
{
class GLShader;
/**
* Inverts desktop's colors
**/
class InvertEffect : public QObject, public ShaderEffect
class InvertEffect
: public QObject, public Effect
{
Q_OBJECT
public:
InvertEffect();
~InvertEffect();
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowClosed( EffectWindow* w );
public slots:
void toggle();
void toggleWindow();
protected:
bool loadData();
private:
bool m_inited;
bool m_valid;
GLShader* m_shader;
bool m_allWindows;
QList<EffectWindow*> m_windows;
};
} // namespace

View file

@ -42,11 +42,17 @@ InvertEffectConfig::InvertEffectConfig(QWidget* parent, const QVariantList& args
QVBoxLayout* layout = new QVBoxLayout(this);
KActionCollection* actionCollection = new KActionCollection( this, componentData() );
KAction* a = static_cast<KAction*>(actionCollection->addAction( "Invert" ));
a->setText( i18n("Toggle Invert Effect" ));
a->setProperty("isConfigurationAction", true);
a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_I));
KAction* b = static_cast<KAction*>(actionCollection->addAction( "InvertWindow" ));
b->setText( i18n("Toggle Invert Effect On Window" ));
b->setProperty("isConfigurationAction", true);
b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_U));
mShortcutEditor = new KShortcutsEditor(actionCollection, this,
KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed);
connect(mShortcutEditor, SIGNAL(keyChange()), this, SLOT(changed()));

View file

@ -1365,7 +1365,7 @@ void SceneOpenGL::Window::prepareShaderRenderStates( double opacity, double brig
if( !opaque )
{
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // TODO: GL_ONE like below?
glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
}
shader->setUniform("opacity", (float)opacity);
shader->setUniform("saturation", (float)saturation);