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:
parent
faf7477fdb
commit
9a52d3c709
7 changed files with 147 additions and 21 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
void main()
|
||||
{
|
||||
gl_TexCoord[0].xy = gl_Vertex.xy;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue