diff --git a/effects.cpp b/effects.cpp index b96a00ba99..53d63be7f4 100644 --- a/effects.cpp +++ b/effects.cpp @@ -228,10 +228,10 @@ void EffectsHandlerImpl::postPaintWindow( EffectWindow* w ) // no special final code } -bool EffectsHandlerImpl::providesResizeEffect() +bool EffectsHandlerImpl::provides( Effect::Feature ef ) { for( int i = 0; i < loaded_effects.size(); ++i ) - if( loaded_effects.at(i).second->isResizeEffect() ) + if( loaded_effects.at(i).second->provides( ef ) ) return true; return false; } diff --git a/effects.h b/effects.h index 796a47c319..c224c52e12 100644 --- a/effects.h +++ b/effects.h @@ -48,7 +48,7 @@ class EffectsHandlerImpl : public EffectsHandler virtual void postPaintWindow( EffectWindow* w ); virtual void paintEffectFrame( EffectFrame* frame, QRegion region, double opacity, double frameOpacity ); - bool providesResizeEffect(); + bool provides( Effect::Feature ef ); virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt index 8367472c06..5f7d3e4102 100644 --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -81,6 +81,7 @@ include( slideback/CMakeLists.txt ) include( slidingpopups/CMakeLists.txt ) include( taskbarthumbnail/CMakeLists.txt ) include( thumbnailaside/CMakeLists.txt ) +include( windowgeometry/CMakeLists.txt ) include( zoom/CMakeLists.txt ) # OpenGL-specific effects diff --git a/effects/resize/resize.desktop b/effects/resize/resize.desktop index 25639bb5de..f9f001f04d 100644 --- a/effects/resize/resize.desktop +++ b/effects/resize/resize.desktop @@ -61,7 +61,7 @@ Name[x-test]=xxResize Windowxx Name[zh_CN]=缩放窗口 Name[zh_TW]=重新調整視窗大小 Icon=preferences-system-windows-effect-resize -Comment=Effect to outline geometry while resizing a window +Comment=Resizes windows with a fast texture scale instead of updating contents Comment[ar]=تأثير لإظهار شكل النافذة الأصلي أثناء تغيير حجمها Comment[ast]=Efeutu pa dibuxar la xeometría al camudar el tamañu d'una ventana Comment[ca]=Efecte de geometria de contorn en redimensionar una finestra diff --git a/effects/resize/resize.h b/effects/resize/resize.h index 2f0df4d669..9575fbcd20 100644 --- a/effects/resize/resize.h +++ b/effects/resize/resize.h @@ -32,7 +32,7 @@ class ResizeEffect public: ResizeEffect(); ~ResizeEffect(); - virtual inline bool isResizeEffect() { return true; } + virtual inline bool provides( Effect::Feature ef ) { return ef == Effect::Resize; } virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); diff --git a/effects/windowgeometry/CMakeLists.txt b/effects/windowgeometry/CMakeLists.txt new file mode 100644 index 0000000000..acf2474186 --- /dev/null +++ b/effects/windowgeometry/CMakeLists.txt @@ -0,0 +1,26 @@ +####################################### +# Effect + +# Source files +set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources} + windowgeometry/windowgeometry.cpp + ) + +# .desktop files +install( FILES + windowgeometry/windowgeometry.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kwin ) + +####################################### +# Config + +# Source files +set( kwin4_effect_builtins_config_sources ${kwin4_effect_builtins_config_sources} + windowgeometry/windowgeometry_config.cpp + windowgeometry/windowgeometry_config.ui + ) + +# .desktop files +install( FILES + windowgeometry/windowgeometry_config.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kwin ) diff --git a/effects/windowgeometry/windowgeometry.cpp b/effects/windowgeometry/windowgeometry.cpp new file mode 100644 index 0000000000..006152ea2d --- /dev/null +++ b/effects/windowgeometry/windowgeometry.cpp @@ -0,0 +1,179 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2010 Thomas Lübking + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "windowgeometry.h" +#include +#include +#include +#include +#include +#include + +using namespace KWin; + +KWIN_EFFECT( windowgeometry, WindowGeometry ) + +WindowGeometry::WindowGeometry() + { + iAmActivated = true; + iAmActive = false; + myResizeWindow = 0L; + myResizeString = i18nc("Window geometry display, %1 and %2 are the new size," + " %3 and %4 are pixel increments - avoid reformatting or suffixes like 'px'", + "Width: %1 (%3)\nHeight: %2 (%4)"); + myCoordString[0] = i18nc("Window geometry display, %1 and %2 are the cartesian x and y coordinates" + " - avoid reformatting or suffixes like 'px'", + "X: %1\nY: %2"); + myCoordString[1] = i18nc("Window geometry display, %1 and %2 are the cartesian x and y coordinates," + " %3 and %4 are the resp. increments - avoid reformatting or suffixes like 'px'", + "X: %1 (%3)\nY: %2 (%4)"); + reconfigure( ReconfigureAll ); + QFont fnt; fnt.setBold(true); fnt.setPointSize(12); + for ( int i = 0; i < 3; ++i ) + { + myMeasure[i] = effects->effectFrame( EffectFrameUnstyled, false ); + myMeasure[i]->setFont( fnt ); + } + myMeasure[0]->setAlignment( Qt::AlignLeft|Qt::AlignTop ); + myMeasure[1]->setAlignment( Qt::AlignCenter ); + myMeasure[2]->setAlignment( Qt::AlignRight|Qt::AlignBottom ); + + KActionCollection* actionCollection = new KActionCollection( this ); + KAction* a = static_cast< KAction* >( actionCollection->addAction( "WindowGeometry" )); + a->setText( i18n("Toggle window geometry display (effect only)" )); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_F11 )); + connect( a, SIGNAL( triggered(bool) ), this, SLOT( toggle() ) ); + } + +WindowGeometry::~WindowGeometry() + { + for ( int i = 0; i < 3; ++i ) + delete myMeasure[i]; + } + +void WindowGeometry::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = effects->effectConfig( "WindowGeometry" ); + iHandleMoves = conf.readEntry( "Move", true ); + iHandleResizes = conf.readEntry( "Resize", true ); + } + +void WindowGeometry::paintScreen(int mask, QRegion region, ScreenPaintData &data) + { + effects->paintScreen( mask, region, data ); + if ( iAmActivated && iAmActive ) + { + for ( int i = 0; i < 3; ++i ) + myMeasure[i]->render(infiniteRegion(), 1.0, .66); + } + } + +void WindowGeometry::toggle() + { + iAmActivated = !iAmActivated; + } + +void WindowGeometry::windowUserMovedResized( EffectWindow* w, bool first, bool last ) + { + if (first && last) // "maximized" + return; + + if ( first ) + { + if ( !iAmActivated ) + return; + if ( w->isUserResize() && !iHandleResizes ) + return; + if ( w->isUserMove() && !iHandleMoves) + return; + + iAmActive = true; + myResizeWindow = w; + myOriginalGeometry = w->geometry(); + myCurrentGeometry = w->geometry(); + effects->addRepaint( myCurrentGeometry.adjusted(-20, -20, 20, 20) ); + } + + if ( iAmActive && w == myResizeWindow && last ) + { + iAmActive = false; + myResizeWindow = 0L; + effects->addRepaint( myCurrentGeometry.adjusted(-20, -20, 20, 20) ); + } +} + +static inline QString number(int n) + { + if ( n >= 0 ) + return "+" + QString::number(n); + return QString::number(n); // "-" is auto-applied + } + + +void WindowGeometry::windowMoveResizeGeometryUpdate( EffectWindow* w, const QRect& geometry ) +{ + if ( iAmActivated && iAmActive && w == myResizeWindow ) + { + myCurrentGeometry = geometry; + const QRect &r = geometry; + const QRect &r2 = myOriginalGeometry; + + // sufficient for moves, resizes calculated otherwise + int dx = r.x() - r2.x(); + int dy = r.y() - r2.y(); + + // upper left ---------------------- + if ( w->isUserResize() ) + myMeasure[0]->setText( myCoordString[1].arg( r.x() ).arg( r.y() ).arg( number(dx) ).arg( number(dy) ) ); + else + myMeasure[0]->setText( myCoordString[0].arg( r.x() ).arg( r.y() ) ); + myMeasure[0]->setPosition( geometry.topLeft() ); + + // center ---------------------- + if ( w->isUserResize() ) + { + // calc width for center element, otherwise the current dx/dx remains right + dx = r.width() - r2.width(); + dy = r.height() - r2.height(); + + // TODO: i hate this. anyone got a nice idea to invoke the stringbuilder or otherwise avoid + // dogslow QString::arg() system here? + myMeasure[1]->setText( myResizeString.arg( r.width() ).arg( r.height() ).arg( number(dx) ).arg( number(dy) ) ); + + // calc width for bottomright element, superflous otherwise + dx = r.right() - r2.right(); + dy = r.bottom() - r2.bottom(); + } + else + myMeasure[1]->setText( myCoordString[0].arg( number(dx) ).arg( number(dy) ) ); + + myMeasure[1]->setPosition( geometry.center() ); + + // lower right ---------------------- + if ( w->isUserResize() ) + myMeasure[2]->setText( myCoordString[1].arg( r.right() ).arg( r.bottom() ).arg( number(dx) ).arg( number(dy) ) ); + else + myMeasure[2]->setText( myCoordString[0].arg( r.right() ).arg( r.bottom() ) ); + myMeasure[2]->setPosition( geometry.bottomRight() ); + + effects->addRepaint( geometry.adjusted(-20, -20, 20, 20) ); + } + } + diff --git a/effects/windowgeometry/windowgeometry.desktop b/effects/windowgeometry/windowgeometry.desktop new file mode 100644 index 0000000000..f4c66c43dd --- /dev/null +++ b/effects/windowgeometry/windowgeometry.desktop @@ -0,0 +1,28 @@ +[Desktop Entry] +# Name of the effect +Name=WindowGeometry +Comment=Display window geometries on move/resize +Icon=preferences-system-windows-effect-windowgeometry + +# This is KWin effect +Type=Service +X-KDE-ServiceTypes=KWin/Effect +# Author and email of the author +X-KDE-PluginInfo-Author=Thomas Lübking +X-KDE-PluginInfo-Email=thomas.luebking@web.de +# Internal name of the effect +X-KDE-PluginInfo-Name=kwin4_effect_windowgeometry +# Category of the effect, for config dialog +X-KDE-PluginInfo-Category=Appearance +# Version and license +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-License=GPL +# If the effect depends on any other effect(s) to be active, then internal +# names of those effects can be given here +X-KDE-PluginInfo-Depends= +# Whether this effect should be enabled by default +X-KDE-PluginInfo-EnabledByDefault=false +# The plugin (library) which contains the effect. One library may contain more effects. +X-KDE-Library=kwin4_effect_builtins +# The order in which this effect is loaded. Lower numbers are loaded first. +X-KDE-Ordering=90 diff --git a/effects/windowgeometry/windowgeometry.h b/effects/windowgeometry/windowgeometry.h new file mode 100644 index 0000000000..f3556f4f0e --- /dev/null +++ b/effects/windowgeometry/windowgeometry.h @@ -0,0 +1,54 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2010 Thomas Lübking + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef WINDOWGEOMETRY_H +#define WINDOWGEOMETRY_H + +#include + +namespace KWin +{ + +class WindowGeometry : public QObject, public Effect +{ + Q_OBJECT +public: + WindowGeometry(); + ~WindowGeometry(); + + inline bool provides( Effect::Feature ef ) { return ef == Effect::GeometryTip; } + void reconfigure( ReconfigureFlags ); + void paintScreen(int mask, QRegion region, ScreenPaintData &data); + void windowUserMovedResized( EffectWindow* w, bool first, bool last ); + void windowMoveResizeGeometryUpdate( EffectWindow* c, const QRect& geometry ); + +private slots: + void toggle(); +private: + EffectWindow *myResizeWindow; + EffectFrame *myMeasure[3]; + QRect myOriginalGeometry, myCurrentGeometry; + bool iAmActive, iAmActivated, iHandleMoves, iHandleResizes; + QString myCoordString[2], myResizeString; +}; + +} // namespace + +#endif diff --git a/effects/windowgeometry/windowgeometry_config.cpp b/effects/windowgeometry/windowgeometry_config.cpp new file mode 100644 index 0000000000..50c9c33f64 --- /dev/null +++ b/effects/windowgeometry/windowgeometry_config.cpp @@ -0,0 +1,91 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2010 Thomas Lübking + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "windowgeometry_config.h" +#include +#include +#include +#include +#include + +namespace KWin +{ +KWIN_EFFECT_CONFIG_FACTORY + +WindowGeometryConfigForm::WindowGeometryConfigForm(QWidget* parent) : QWidget(parent) + { + setupUi(this); + } + +WindowGeometryConfig::WindowGeometryConfig(QWidget* parent, const QVariantList& args) + : KCModule(KWin::EffectFactory::componentData(), parent, args) + { + QVBoxLayout* layout = new QVBoxLayout(this); + layout->addWidget(myUi = new WindowGeometryConfigForm(this)); + + // Shortcut config. The shortcut belongs to the component "kwin"! + myActionCollection = new KActionCollection( this, KComponentData("kwin") ); + KAction* a = (KAction*)myActionCollection->addAction( "WindowGeometry" ); + a->setText( i18n("Toggle KWin composited geometry display" )); + a->setProperty("isConfigurationAction", true); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_F11 )); + + myUi->shortcuts->addCollection(myActionCollection); + connect(myUi->shortcuts, SIGNAL(keyChange()), this, SLOT(changed())); + + connect(myUi->handleMove, SIGNAL(toggled(bool)), this, SLOT(changed())); + connect(myUi->handleResize, SIGNAL(toggled(bool)), this, SLOT(changed())); + } + +WindowGeometryConfig::~WindowGeometryConfig() + { + // Undo (only) unsaved changes to global key shortcuts + myUi->shortcuts->undoChanges(); + } + +void WindowGeometryConfig::load() + { + KCModule::load(); + KConfigGroup conf = EffectsHandler::effectConfig("WindowGeometry"); + myUi->handleMove->setChecked( conf.readEntry("Move", true) ); + myUi->handleResize->setChecked( conf.readEntry("Resize", true) ); + emit changed(false); + } + +void WindowGeometryConfig::save() + { + KConfigGroup conf = EffectsHandler::effectConfig("WindowGeometry"); + conf.writeEntry("Move", myUi->handleMove->isChecked()); + conf.writeEntry("Resize", myUi->handleResize->isChecked()); + myUi->shortcuts->save(); // undo() will restore to this state from now on + conf.sync(); + emit changed(false); + EffectsHandler::sendReloadMessage( "windowgeometry" ); + } + +void WindowGeometryConfig::defaults() + { + myUi->handleMove->setChecked( true ); + myUi->handleResize->setChecked( true ); + myUi->shortcuts->allDefault(); + emit changed(true); + } +} //namespace +#include "windowgeometry_config.moc" diff --git a/effects/windowgeometry/windowgeometry_config.desktop b/effects/windowgeometry/windowgeometry_config.desktop new file mode 100644 index 0000000000..3513614efb --- /dev/null +++ b/effects/windowgeometry/windowgeometry_config.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kcm_kwin4_effect_builtins +X-KDE-ParentComponents=kwin4_effect_windowgeometry +X-KDE-PluginKeyword=windowgeometry + +Name=WindowGeometry diff --git a/effects/windowgeometry/windowgeometry_config.h b/effects/windowgeometry/windowgeometry_config.h new file mode 100644 index 0000000000..76b1054a3e --- /dev/null +++ b/effects/windowgeometry/windowgeometry_config.h @@ -0,0 +1,58 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2010 Thomas Lübking + +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 +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef WINDOWGEOMETRY_CONFIG_H +#define WINDOWGEOMETRY_CONFIG_H + +#include + +#include "ui_windowgeometry_config.h" + + +namespace KWin +{ + +class WindowGeometryConfigForm : public QWidget, public Ui::WindowGeometryConfigForm +{ + Q_OBJECT +public: + explicit WindowGeometryConfigForm(QWidget* parent); +}; + +class WindowGeometryConfig : public KCModule +{ + Q_OBJECT +public: + explicit WindowGeometryConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); + ~WindowGeometryConfig(); + +public slots: + void save(); + void load(); + void defaults(); + +private: + WindowGeometryConfigForm* myUi; + KActionCollection* myActionCollection; +}; + +} // namespace + +#endif diff --git a/effects/windowgeometry/windowgeometry_config.ui b/effects/windowgeometry/windowgeometry_config.ui new file mode 100644 index 0000000000..2b8e8a67c2 --- /dev/null +++ b/effects/windowgeometry/windowgeometry_config.ui @@ -0,0 +1,43 @@ + + + KWin::WindowGeometryConfigForm + + + + 0 + 0 + 430 + 187 + + + + + + + Display for moving windows + + + + + + + Display for resizing windows + + + + + + + + + + + KWin::GlobalShortcutsEditor + QWidget +
kwineffects.h
+ 1 +
+
+ + +
diff --git a/geometry.cpp b/geometry.cpp index 4bc888f449..cdb2f0fd11 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2695,7 +2695,7 @@ void Client::clearbound() void Client::doDrawbound( const QRect& geom, bool clear ) { - if( effects && static_cast(effects)->providesResizeEffect() ) + if( effects && static_cast(effects)->provides( Effect::Resize ) ) return; // done by effect if( decoration != NULL && decoration->drawbound( geom, clear ) ) return; // done by decoration @@ -2727,7 +2727,9 @@ void Client::positionGeometryTip() { assert( isMove() || isResize()); // Position and Size display - if (options->showGeometryTip()) + if ( effects && static_cast(effects)->provides( Effect::GeometryTip ) ) + return; // some effect paints this for us + if ( options->showGeometryTip() ) { if( !geometryTip ) { // save under is not necessary with opaque, and seem to make things slower @@ -3348,7 +3350,7 @@ void Client::performMoveResize() bool transparent = false; if( isResize() ) { - haveResizeEffect = effects && static_cast(effects)->providesResizeEffect(); + haveResizeEffect = effects && static_cast(effects)->provides( Effect::Resize ); transparent = haveResizeEffect || rules()->checkMoveResizeMode( options->resizeMode) != Options::Opaque; } else if ( isMove()) diff --git a/kcmkwin/kwinoptions/windows.cpp b/kcmkwin/kwinoptions/windows.cpp index f1e7c9e4b9..178a552e79 100644 --- a/kcmkwin/kwinoptions/windows.cpp +++ b/kcmkwin/kwinoptions/windows.cpp @@ -1172,6 +1172,8 @@ void KMovingConfig::save( void ) cg.writeEntry(KWM_CNTR_SNAP_ZONE,getCenterSnapZone()); cg.writeEntry("SnapOnlyWhenOverlapping",OverlapSnap->isChecked()); + KConfigGroup( config, "Plugins" ).writeEntry("kwin4_effect_windowgeometryEnabled", getGeometryTip()); + if (standAlone) { config->sync(); diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index e2e5b60b63..6801c99f3a 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -251,6 +251,11 @@ void Effect::paintEffectFrame( KWin::EffectFrame* frame, QRegion region, double { effects->paintEffectFrame( frame, region, opacity, frameOpacity ); } + +bool Effect::provides( Feature ) + { + return false; + } void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { diff --git a/lib/kwineffects.h b/lib/kwineffects.h index ec1fb316e4..ee4d49ae2a 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -325,6 +325,11 @@ class KWIN_EXPORT Effect PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_WITHOUT_FULL_REPAINTS = 1 << 9 }; + enum Feature + { + Nothing = 0, Resize, GeometryTip + }; + /** * Constructs new Effect object. **/ @@ -419,7 +424,7 @@ class KWIN_EXPORT Effect * Called on Transparent resizes. * return true if your effect substitutes the XOR rubberband */ - virtual bool isResizeEffect() { return false; } + virtual bool provides( Feature ); /** * Can be called to draw multiple copies (e.g. thumbnails) of a window.