diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 93a3d660ac..5a6b43aa1c 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -59,6 +59,7 @@ if(OPENGL_FOUND) blur.cpp explosioneffect.cpp invert.cpp + lookingglass.cpp magnifier.cpp mousemark.cpp shadow.cpp @@ -69,6 +70,7 @@ if(OPENGL_FOUND) blur.desktop explosion.desktop invert.desktop + lookingglass.desktop magnifier.desktop mousemark.desktop shadow.desktop @@ -89,6 +91,8 @@ if(OPENGL_FOUND) data/invert.vert data/sharpen.frag data/sharpen.vert + data/lookingglass.frag + data/lookingglass.vert data/shadow-texture.png data/circle.png DESTINATION ${DATA_INSTALL_DIR}/kwin ) diff --git a/effects/data/lookingglass.frag b/effects/data/lookingglass.frag new file mode 100644 index 0000000000..ab3e73ef55 --- /dev/null +++ b/effects/data/lookingglass.frag @@ -0,0 +1,33 @@ +uniform sampler2D sceneTex; +uniform float textureWidth; +uniform float textureHeight; +uniform float cursorX; +uniform float cursorY; +uniform float zoom; +uniform float radius; + +#define PI 3.14159 + +// Converts pixel coordinates to texture coordinates +vec2 pix2tex(vec2 pix) +{ + return vec2(pix.x / textureWidth, 1.0 - pix.y / textureHeight); +} + +void main() +{ + vec2 texcoord = gl_TexCoord[0].xy; + + float dx = cursorX - texcoord.x; + float dy = cursorY - texcoord.y; + float dist = sqrt(dx*dx + dy*dy); + if(dist < radius) + { + float disp = sin(dist / radius * PI) * (zoom - 1.0) * 20.0; + texcoord.x += dx / dist * disp; + texcoord.y += dy / dist * disp; + } + + gl_FragColor = texture2D(sceneTex, pix2tex(texcoord)); +} + diff --git a/effects/data/lookingglass.vert b/effects/data/lookingglass.vert new file mode 100644 index 0000000000..066ac6c2aa --- /dev/null +++ b/effects/data/lookingglass.vert @@ -0,0 +1,6 @@ +void main() +{ + gl_TexCoord[0].xy = gl_Vertex.xy; + gl_Position = ftransform(); +} + diff --git a/effects/lookingglass.cpp b/effects/lookingglass.cpp new file mode 100644 index 0000000000..72de4e8c0e --- /dev/null +++ b/effects/lookingglass.cpp @@ -0,0 +1,113 @@ +/***************************************************************** + 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 "lookingglass.h" + +#include + +#include +#include +#include +#include + + +namespace KWin +{ + +KWIN_EFFECT( lookingglass, LookingGlassEffect ) +KWIN_EFFECT_SUPPORTED( lookingglass, ShaderEffect::supported() ) + + +LookingGlassEffect::LookingGlassEffect() : QObject(), ShaderEffect("lookingglass") + { + zoom = 1.0f; + target_zoom = 1.0f; + + KActionCollection* actionCollection = new KActionCollection( this ); + KAction* a; + a = static_cast< KAction* >( actionCollection->addAction( KStandardAction::ZoomIn, this, SLOT( zoomIn()))); + a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Plus)); + a = static_cast< KAction* >( actionCollection->addAction( KStandardAction::ZoomOut, this, SLOT( zoomOut()))); + a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Minus)); + a = static_cast< KAction* >( actionCollection->addAction( KStandardAction::ActualSize, this, SLOT( toggle()))); + a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_0)); + radius = 200; // TODO config option + } + +void LookingGlassEffect::toggle() + { + if( target_zoom == 1.0f ) + target_zoom = 2.0f; + else + target_zoom = 1.0f; + setEnabled( true ); + } + +void LookingGlassEffect::zoomIn() + { + target_zoom = qMin(7.0f, target_zoom + 0.5f); + setEnabled( true ); + effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius ); + } + +void LookingGlassEffect::zoomOut() + { + target_zoom -= 0.5; + if( target_zoom < 1 ) + { + target_zoom = 1; + setEnabled( false ); + } + effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius ); + } + +void LookingGlassEffect::prePaintScreen( ScreenPrePaintData& data, int time ) + { + if( zoom != target_zoom ) + { + float diff = time / 500.0f; + if( target_zoom > zoom ) + zoom = qMin( zoom * qMax( 1.0f + diff, 1.2f ), target_zoom ); + else + zoom = qMax( zoom * qMin( 1.0f - diff, 0.8f ), target_zoom ); + kDebug() << k_funcinfo << "zoom is now " << zoom << endl; + radius = qBound(200.0f, 200.0f * zoom, 500.0f); + + if( zoom > 1.0f ) + { + shader()->bind(); + shader()->setUniform("zoom", zoom); + shader()->setUniform("radius", (float)radius); + shader()->unbind(); + } + else + { + setEnabled( false ); + } + + effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius ); + } + + ShaderEffect::prePaintScreen( data, time ); + } + +void LookingGlassEffect::mouseChanged( const QPoint& pos, const QPoint& old, Qt::MouseButtons, Qt::KeyboardModifiers ) + { + if( pos != old && isEnabled() ) + { + effects->addRepaint( pos.x() - radius, pos.y() - radius, 2*radius, 2*radius ); + effects->addRepaint( old.x() - radius, old.y() - radius, 2*radius, 2*radius ); + } + } + +} // namespace + +#include "lookingglass.moc" diff --git a/effects/lookingglass.desktop b/effects/lookingglass.desktop new file mode 100644 index 0000000000..e8f1b121c8 --- /dev/null +++ b/effects/lookingglass.desktop @@ -0,0 +1,16 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Looking Glass +Comment=Looking Glass enhanced magnifier + +Type=Service +ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Rivo Laks +X-KDE-PluginInfo-Email=rivolaks@hot.ee +X-KDE-PluginInfo-Name=kwin4_effect_lookingglass +X-KDE-PluginInfo-Version=0.1.0 +X-KDE-PluginInfo-Category=Accessibility +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-Library=kwin4_effect_builtins diff --git a/effects/lookingglass.h b/effects/lookingglass.h new file mode 100644 index 0000000000..bbb6307186 --- /dev/null +++ b/effects/lookingglass.h @@ -0,0 +1,46 @@ +/***************************************************************** + 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_LOOKINGGLASS_H +#define KWIN_LOOKINGGLASS_H + +#include + +namespace KWin +{ + +/** + * Enhanced magnifier + **/ +class LookingGlassEffect : public QObject, public ShaderEffect + { + Q_OBJECT + public: + LookingGlassEffect(); + + virtual void mouseChanged( const QPoint& pos, const QPoint& old, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers ); + + virtual void prePaintScreen( ScreenPrePaintData& data, int time ); + + public slots: + void toggle(); + void zoomIn(); + void zoomOut(); + + private: + float zoom; + float target_zoom; + int radius; + }; + +} // namespace + +#endif