diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 68b72bc5ba..742c459f55 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -19,6 +19,7 @@ SET(kwin4_effect_builtins_sources fade.cpp fallapart.cpp flame.cpp + magnifier.cpp maketransparent.cpp minimizeanimation.cpp presentwindows.cpp @@ -78,6 +79,7 @@ install( FILES fallapart.desktop flame.desktop howto.desktop + magnifier.desktop maketransparent.desktop minimizeanimation.desktop presentwindows.desktop diff --git a/effects/magnifier.cpp b/effects/magnifier.cpp new file mode 100644 index 0000000000..320ff331cd --- /dev/null +++ b/effects/magnifier.cpp @@ -0,0 +1,145 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2006 Lubos Lunak + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + +#include + +#include "magnifier.h" + +#include +#include +#include + +#ifdef HAVE_OPENGL +#include +#endif + +namespace KWin +{ + +KWIN_EFFECT( Magnifier, MagnifierEffect ) + +MagnifierEffect::MagnifierEffect() + : zoom( 1 ) + , target_zoom( 1 ) + { + 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_Equal)); + 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)); + magnifier_size = QSize( 200, 200 ); // TODO config option + } + +void MagnifierEffect::prePaintScreen( int* mask, QRegion* region, int time ) + { + if( zoom != target_zoom ) + { + double diff = time / 500.0; + if( target_zoom > zoom ) + zoom = qMin( zoom * qMax( 1 + diff, 1.2 ), target_zoom ); + else + zoom = qMax( zoom * qMin( 1 - diff, 0.8 ), target_zoom ); + } + effects->prePaintScreen( mask, region, time ); + } + +void MagnifierEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) + { + ScreenPaintData data2 = data; + effects->paintScreen( mask, region, data ); // paint normal screen + if( zoom != 1.0 ) + { // paint magnifier + glPushAttrib( GL_ENABLE_BIT ); + QRect area = magnifierArea(); + glEnable( GL_SCISSOR_TEST ); + int dh = displayHeight(); + // Scissor rect has to be given in OpenGL coords + glScissor( area.x(), dh - area.y() - area.height(), area.width(), area.height()); + mask |= PAINT_SCREEN_TRANSFORMED; + data2.xScale *= zoom; + data2.yScale *= zoom; + QPoint cursor = cursorPos(); + // set the position so that the cursor is in the same position in the scaled view + data2.xTranslate = - int( cursor.x() * ( zoom - 1 )); + data2.yTranslate = - int( cursor.y() * ( zoom - 1 )); + effects->paintScreen( mask, region, data2 ); + glPopAttrib(); + glPushAttrib( GL_CURRENT_BIT ); + glColor4f( 0, 0, 0, 1 ); // black + glBegin( GL_QUADS ); + glVertex2i( area.left() - 5, area.top() - 5 ); // top frame + glVertex2i( area.right() + 5, area.top() - 5 ); + glVertex2i( area.right() + 5, area.top() - 1 ); + glVertex2i( area.left() - 5, area.top() - 1 ); + glVertex2i( area.left() - 5, area.top() - 5 ); // left frame + glVertex2i( area.left() - 1, area.top() - 5 ); + glVertex2i( area.left() - 1, area.bottom() + 5 ); + glVertex2i( area.left() - 5, area.bottom() + 5 ); + glVertex2i( area.right() + 1, area.top() - 5 ); // right frame + glVertex2i( area.right() + 5, area.top() - 5 ); + glVertex2i( area.right() + 5, area.bottom() + 5 ); + glVertex2i( area.right() + 1, area.bottom() + 5 ); + glVertex2i( area.left() - 5, area.bottom() + 1 ); // bottom frame + glVertex2i( area.right() + 5, area.bottom() + 1 ); + glVertex2i( area.right() + 5, area.bottom() + 5 ); + glVertex2i( area.left() - 5, area.bottom() + 5 ); + glEnd(); + glPopAttrib(); + } + } + +void MagnifierEffect::postPaintScreen() + { + if( zoom != target_zoom ) + effects->addRepaintFull(); + if( zoom != 1.0 ) + { // TODO repaint only what's need and when needed +// effects->addRepaint( magnifierArea()); + effects->addRepaintFull(); + } + effects->postPaintScreen(); + } + +QRect MagnifierEffect::magnifierArea() const + { + QPoint cursor = cursorPos(); + return QRect( cursor.x() - magnifier_size.width() / 2, cursor.y() - magnifier_size.height() / 2, + magnifier_size.width(), magnifier_size.height()); + } + +void MagnifierEffect::zoomIn() + { + target_zoom *= 1.2; + effects->addRepaintFull(); + } + +void MagnifierEffect::zoomOut() + { + target_zoom /= 1.2; + if( target_zoom < 1 ) + target_zoom = 1; + effects->addRepaintFull(); + } + +void MagnifierEffect::toggle() + { + if( target_zoom == 1.0 ) + target_zoom = 2; + else + target_zoom = 1; + effects->addRepaintFull(); + } + +} // namespace + +#include "magnifier.moc" diff --git a/effects/magnifier.desktop b/effects/magnifier.desktop new file mode 100644 index 0000000000..fc147704a3 --- /dev/null +++ b/effects/magnifier.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Magnifier +X-KDE-Library=kwin4_effect_builtins diff --git a/effects/magnifier.h b/effects/magnifier.h new file mode 100644 index 0000000000..302eeafabf --- /dev/null +++ b/effects/magnifier.h @@ -0,0 +1,41 @@ +/***************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2007 Lubos Lunak + +You can Freely distribute this program under the GNU General Public +License. See the file "COPYING" for the exact licensing terms. +******************************************************************/ + +#ifndef KWIN_MAGNIFIER_H +#define KWIN_MAGNIFIER_H + +#include + +namespace KWin +{ + +class MagnifierEffect + : public QObject, public Effect + { + Q_OBJECT + public: + MagnifierEffect(); + virtual void prePaintScreen( int* mask, QRegion* region, int time ); + virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); + virtual void postPaintScreen(); + private slots: + void zoomIn(); + void zoomOut(); + void toggle(); + private: + QRect magnifierArea() const; + double zoom; + double target_zoom; + QSize magnifier_size; + }; + +} // namespace + +#endif