Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1:Test
kdebase4-wallpapers
kwin.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kwin.diff of Package kdebase4-wallpapers
Index: effects/thumbnailaside.h =================================================================== --- kwin/effects/thumbnailaside.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/thumbnailaside.h (.../work/~seli/kwin11.1) (revision 880714) @@ -42,6 +42,7 @@ Q_OBJECT public: ThumbnailAsideEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void windowDamaged( EffectWindow* w, const QRect& damage ); virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old ); Index: effects/fade.cpp =================================================================== --- kwin/effects/fade.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/fade.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -29,9 +29,14 @@ FadeEffect::FadeEffect() { + reconfigure( ReconfigureAll ); + } + +void FadeEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig( "Fade" ); - fadeInTime = qMax( conf.readEntry( "FadeInTime", 150 ), 1 ); - fadeOutTime = qMax( conf.readEntry( "FadeOutTime", 150 ), 1 ); + fadeInTime = animationTime( conf, "FadeInTime", 150 ); + fadeOutTime = animationTime( conf, "FadeOutTime", 150 ); fadeWindows = conf.readEntry( "FadeWindows", true ); } @@ -188,7 +193,7 @@ { // see login effect return false; } - return !w->isDesktop(); + return ( !w->isDesktop() && !w->isUtility() ); } } // namespace Index: effects/trackmouse_config.cpp =================================================================== --- kwin/effects/trackmouse_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/trackmouse_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -24,10 +24,8 @@ #include <klocale.h> #include <kdebug.h> -#include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QVBoxLayout> #include <QLabel> Index: effects/magnifier.h =================================================================== --- kwin/effects/magnifier.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/magnifier.h (.../work/~seli/kwin11.1) (revision 880714) @@ -32,6 +32,7 @@ Q_OBJECT public: MagnifierEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); Index: effects/fallapart.cpp =================================================================== --- kwin/effects/fallapart.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/fallapart.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -41,7 +41,7 @@ { if( windows[ w ] < 1 ) { - windows[ w ] += time / 1000.; + windows[ w ] += time / animationTime( 1000. ); data.setTransformed(); w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE ); // Request the window to be divided into cells Index: effects/sphere_config.ui =================================================================== --- kwin/effects/sphere_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,552 @@ +<ui version="4.0" > + <class>KWin::SphereEffectConfigForm</class> + <widget class="QWidget" name="KWin::SphereEffectConfigForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>568</width> + <height>595</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QTabWidget" name="tabWidget" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>546</width> + <height>552</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_5" > + <item row="1" column="1" > + <widget class="QGroupBox" name="groupBox_5" > + <property name="title" > + <string>Background</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>Background Color:</string> + </property> + <property name="buddy" > + <cstring>backgroundColorButton</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="KColorButton" name="backgroundColorButton" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Wallpaper:</string> + </property> + <property name="buddy" > + <cstring>wallpaperRequester</cstring> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2" > + <widget class="KUrlRequester" name="wallpaperRequester" /> + </item> + </layout> + </widget> + </item> + <item row="3" column="0" colspan="2" > + <widget class="QGroupBox" name="groupBox_8" > + <property name="title" > + <string>Activation</string> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <item row="0" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Screen edge:</string> + </property> + <property name="buddy" > + <cstring>screenEdgeCombo</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QComboBox" name="screenEdgeCombo" /> + </item> + <item row="1" column="0" colspan="2" > + <widget class="KWin::GlobalShortcutsEditor" native="1" name="editor" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item rowspan="2" row="0" column="0" > + <widget class="QGroupBox" name="groupBox_7" > + <property name="title" > + <string>Appearance</string> + </property> + <layout class="QGridLayout" name="gridLayout_2" > + <item row="0" column="0" colspan="2" > + <widget class="QCheckBox" name="displayDesktopNameBox" > + <property name="text" > + <string>Display desktop name</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Rotation duration:</string> + </property> + <property name="buddy" > + <cstring>rotationDurationSpin</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="QSpinBox" name="rotationDurationSpin" > + <property name="minimumSize" > + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="specialValueText" > + <string>Default</string> + </property> + <property name="suffix" > + <string> msec</string> + </property> + <property name="maximum" > + <number>5000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2" > + <spacer name="verticalSpacer_2" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="0" column="1" > + <widget class="QGroupBox" name="groupBox_4" > + <property name="title" > + <string>Opacity</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3" > + <item> + <layout class="QVBoxLayout" name="verticalLayout_5" > + <item> + <widget class="QSlider" name="cubeOpacitySlider" > + <property name="minimumSize" > + <size> + <width>200</width> + <height>0</height> + </size> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="singleStep" > + <number>1</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>10</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6" > + <item> + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Transparent</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>Opaque</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QSpinBox" name="cubeOpacitySpin" > + <property name="minimumSize" > + <size> + <width>75</width> + <height>0</height> + </size> + </property> + <property name="suffix" > + <string> %</string> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="value" > + <number>100</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>553</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 2</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3" > + <item> + <widget class="QGroupBox" name="groupBox_3" > + <property name="title" > + <string>Caps</string> + </property> + <layout class="QGridLayout" name="gridLayout_4" > + <item row="0" column="0" > + <widget class="QCheckBox" name="cubeCapsBox" > + <property name="text" > + <string>Show caps</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="capColorLabel" > + <property name="text" > + <string>Cap Color:</string> + </property> + <property name="buddy" > + <cstring>capColorButton</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="KColorButton" name="capColorButton" /> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="capsImageBox" > + <property name="text" > + <string>Display image on caps</string> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="capDeformationLabel" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text" > + <string>Cap deformation:</string> + </property> + <property name="alignment" > + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <property name="buddy" > + <cstring>capDeformationSlider</cstring> + </property> + </widget> + </item> + <item row="3" column="1" > + <layout class="QVBoxLayout" name="verticalLayout_4" > + <item> + <widget class="QSlider" name="capDeformationSlider" > + <property name="maximum" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>25</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLabel" name="capDeformationSphereLabel" > + <property name="text" > + <string>Sphere</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="capDeformationPlaneLabel" > + <property name="text" > + <string>Plane</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Zoom</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QSlider" name="zPositionSlider" > + <property name="toolTip" > + <string>Define how far away the object should appear</string> + </property> + <property name="maximum" > + <number>3000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + <property name="pageStep" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>100</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <widget class="QLabel" name="label_8" > + <property name="text" > + <string>Near</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_9" > + <property name="text" > + <string>Far</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_9" > + <property name="title" > + <string>Additional options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QCheckBox" name="closeOnMouseReleaseBox" > + <property name="toolTip" > + <string>Sphere is deactivated after rotating the sphere with the mouse. +Otherwise sphere will stay in the position.</string> + </property> + <property name="text" > + <string>Close after mouse dragging</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="walkThroughDesktopBox" > + <property name="text" > + <string>Use for walk through desktop list</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KColorButton</class> + <extends>QPushButton</extends> + <header>kcolorbutton.h</header> + </customwidget> + <customwidget> + <class>KUrlRequester</class> + <extends>QFrame</extends> + <header>kurlrequester.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>KWin::GlobalShortcutsEditor</class> + <extends>QWidget</extends> + <header location="global" >kwineffects.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>tabWidget</tabstop> + <tabstop>displayDesktopNameBox</tabstop> + <tabstop>rotationDurationSpin</tabstop> + <tabstop>cubeOpacitySlider</tabstop> + <tabstop>cubeOpacitySpin</tabstop> + <tabstop>backgroundColorButton</tabstop> + <tabstop>wallpaperRequester</tabstop> + <tabstop>screenEdgeCombo</tabstop> + <tabstop>cubeCapsBox</tabstop> + <tabstop>capColorButton</tabstop> + <tabstop>capsImageBox</tabstop> + <tabstop>capDeformationSlider</tabstop> + <tabstop>zPositionSlider</tabstop> + <tabstop>closeOnMouseReleaseBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>cubeOpacitySpin</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>386</x> + <y>175</y> + </hint> + <hint type="destinationlabel" > + <x>235</x> + <y>162</y> + </hint> + </hints> + </connection> + <connection> + <sender>cubeOpacitySlider</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySpin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>133</x> + <y>162</y> + </hint> + <hint type="destinationlabel" > + <x>386</x> + <y>175</y> + </hint> + </hints> + </connection> + </connections> +</ui> Index: effects/cube_config.h =================================================================== --- kwin/effects/cube_config.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube_config.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,60 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_CUBE_CONFIG_H +#define KWIN_CUBE_CONFIG_H + +#include <kcmodule.h> + +#include "ui_cube_config.h" + +class KFileDialog; + +namespace KWin +{ + +class CubeEffectConfigForm : public QWidget, public Ui::CubeEffectConfigForm +{ + Q_OBJECT + public: + explicit CubeEffectConfigForm(QWidget* parent); +}; + +class CubeEffectConfig : public KCModule + { + Q_OBJECT + public: + explicit CubeEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); + + public slots: + virtual void save(); + virtual void load(); + virtual void defaults(); + + private slots: + void capsSelectionChanged(); + private: + CubeEffectConfigForm* m_ui; + KActionCollection* m_actionCollection; + }; + +} // namespace + +#endif Index: effects/logout.cpp =================================================================== --- kwin/effects/logout.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/logout.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -45,9 +45,9 @@ void LogoutEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if( logout_window != NULL ) - progress = qBound( 0., progress + time / 2000., 1. ); + progress = qBound( 0., progress + time / animationTime( 2000. ), 1. ); else if( progress != 0 ) - progress = qBound( 0., progress - time / 500., 1. ); + progress = qBound( 0., progress - time / animationTime( 500. ), 1. ); effects->prePaintScreen( data, time ); } Index: effects/cylinder.cpp =================================================================== --- kwin/effects/cylinder.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,223 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "cube.h" +#include "cylinder.h" + +#include <kdebug.h> +#include <KStandardDirs> + +#include <math.h> + +#include <GL/gl.h> + +namespace KWin +{ + +KWIN_EFFECT( cylinder, CylinderEffect ) +KWIN_EFFECT_SUPPORTED( cylinder, CylinderEffect::supported() ) + +CylinderEffect::CylinderEffect() + : CubeEffect() + , mInited( false ) + , mValid( true ) + , mShader( 0 ) + { + if( wallpaper ) + wallpaper->discard(); + reconfigure( ReconfigureAll ); + } + +CylinderEffect::~CylinderEffect() + { + delete mShader; + } + +void CylinderEffect::reconfigure( ReconfigureFlags ) + { + loadConfig( "Cylinder" ); + animateDesktopChange = false; + bigCube = true; + } + +bool CylinderEffect::supported() + { + return GLShader::fragmentShaderSupported() && + (effects->compositingType() == OpenGLCompositing); + } + +bool CylinderEffect::loadData() + { + mInited = true; + QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.frag"); + QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.vert"); + if(fragmentshader.isEmpty() || vertexshader.isEmpty()) + { + kError() << "Couldn't locate shader files" << endl; + return false; + } + + mShader = new GLShader(vertexshader, fragmentshader); + if(!mShader->isValid()) + { + kError() << "The shader failed to load!" << endl; + return false; + } + else + { + mShader->bind(); + mShader->setUniform( "winTexture", 0 ); + mShader->setUniform( "opacity", cubeOpacity ); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && (slide || bigCube ) ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + mShader->setUniform( "width", (float)rect.width() ); + mShader->unbind(); + } + return true; + } + +void CylinderEffect::paintScene( int mask, QRegion region, ScreenPaintData& data ) + { + glPushMatrix(); + QRect rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop()); + + float cubeAngle = (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f; + float radian = (cubeAngle*0.5)*M_PI/180; + // height of the triangle compound of one side of the cube and the two bisecting lines + float midpoint = rect.width()*0.5*tan(radian); + // radius of the circle + float radius = (rect.width()*0.5)/cos(radian); + glTranslatef( 0.0, 0.0, midpoint - radius ); + CubeEffect::paintScene( mask, region, data ); + glPopMatrix(); + } + +void CylinderEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { + if( activated ) + { + if( cube_painting ) + { + if( w->isOnDesktop( painting_desktop )) + { + data.quads = data.quads.makeGrid( 40 ); + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + if( w->x() < rect.width()/2 && w->x() + w->width() > rect.width()/ 2 ) + data.quads = data.quads.splitAtX( rect.width()/2 - w->x() ); + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + else + { + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + } + } + effects->prePaintWindow( w, data, time ); + } + +void CylinderEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + if( activated && cube_painting ) + { + if( mValid && !mInited ) + mValid = loadData(); + bool useShader = mValid; + if( useShader ) + { + mShader->bind(); + mShader->setUniform( "windowWidth", (float)w->width() ); + mShader->setUniform( "windowHeight", (float)w->height() ); + mShader->setUniform( "xCoord", (float)w->x() ); + mShader->setUniform( "cubeAngle", (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f ); + data.shader = mShader; + } + CubeEffect::paintWindow( w, mask, region, data ); + if( useShader ) + { + mShader->unbind(); + } + } + else + effects->paintWindow( w, mask, region, data ); + } + +void CylinderEffect::desktopChanged( int old ) + { + // cylinder effect is not useful to slide + } + +void CylinderEffect::paintCap( float z, float zTexture ) + { + if( ( !paintCaps ) || effects->numberOfDesktops() <= 2 ) + return; + CubeEffect::paintCap( z, zTexture ); + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + + float cubeAngle = (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f; + float radian = (cubeAngle*0.5)*M_PI/180; + // height of the triangle compound of one side of the cube and the two bisecting lines + float midpoint = rect.width()*0.5*tan(radian); + // radius of the circle + float radius = (rect.width()*0.5)/cos(radian); + + // paint round part of the cap + glPushMatrix(); + float zTranslate = zPosition + zoom; + if( start ) + zTranslate *= timeLine.value(); + if( stop ) + zTranslate *= ( 1.0 - timeLine.value() ); + glTranslatef( 0.0, 0.0, -zTranslate ); + float triangleWidth = 40.0; + + for( int i=0; i<effects->numberOfDesktops(); i++ ) + { + glPushMatrix(); + glTranslatef( rect.width()/2, 0.0, -z ); + glRotatef( i*(360.0f/effects->numberOfDesktops()), 0.0, 1.0, 0.0 ); + glTranslatef( -rect.width()/2, 0.0, z ); + glBegin( GL_TRIANGLE_STRIP ); + for( int j=0; j<rect.width()/triangleWidth; j++ ) + { + float zValue = 0.0; + // distance from midpoint of desktop to x coord + // calculation is same as in shader -> see comments + float distance = rect.width()*0.5 - (j*triangleWidth); + if( (j*triangleWidth) > rect.width()*0.5 ) + { + distance = (j*triangleWidth) - rect.width()*0.5; + } + // distance in correct format + float angle = acos( distance/radius ); + float h = radius; + // if distance == 0 -> angle=90 -> tan(90) singularity + if( distance != 0.0 ) + h = tan( angle ) * distance; + zValue = h - midpoint; + glVertex3f( j*triangleWidth, 0.0, zValue ); + glVertex3f( (j+1)*triangleWidth, 0.0, 0.0 ); + } + glEnd(); + glPopMatrix(); + } + glPopMatrix(); + } + +} // namespace Index: effects/boxswitch.cpp =================================================================== --- kwin/effects/boxswitch.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/boxswitch.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -22,9 +22,7 @@ #include <kwinconfig.h> -#include <QCursor> #include <QMouseEvent> -#include <QPainter> #include <QSize> #include <kapplication.h> @@ -47,6 +45,15 @@ { frame_margin = 10; highlight_margin = 5; + reconfigure( ReconfigureAll ); + } + +BoxSwitchEffect::~BoxSwitchEffect() + { + } + +void BoxSwitchEffect::reconfigure( ReconfigureFlags ) + { color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color(); color_frame.setAlphaF( 0.9 ); color_highlight = KColorScheme( QPalette::Active, KColorScheme::Selection ).background().color(); @@ -54,10 +61,6 @@ color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color(); } -BoxSwitchEffect::~BoxSwitchEffect() - { - } - void BoxSwitchEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) { if( mActivated ) @@ -602,21 +605,7 @@ // Render the icon glColor4f( 1, 1, 1, 1 ); windows[ w ]->iconTexture.bind(); - const float verts[ 4 * 2 ] = - { - x, y, - x, y + height, - x + width, y + height, - x + width, y - }; - const float texcoords[ 4 * 2 ] = - { - 0, 1, - 0, 0, - 1, 0, - 1, 1 - }; - renderGLGeometry( 4, verts, texcoords ); + windows[ w ]->iconTexture.render( infiniteRegion(), QRect( x, y, width, height )); windows[ w ]->iconTexture.unbind(); glPopAttrib(); } Index: effects/magnifier_config.ui =================================================================== --- kwin/effects/magnifier_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/magnifier_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -34,6 +34,9 @@ <property name="maximum" > <number>500</number> </property> + <property name="singleStep" > + <number>10</number> + </property> </widget> </item> <item row="1" column="0" > @@ -54,6 +57,9 @@ <property name="maximum" > <number>500</number> </property> + <property name="singleStep" > + <number>10</number> + </property> </widget> </item> </layout> Index: effects/zoom.cpp =================================================================== --- kwin/effects/zoom.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/zoom.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -47,7 +47,7 @@ { if( zoom != target_zoom ) { - double diff = time / 500.0; + double diff = time / animationTime( 500.0 ); if( target_zoom > zoom ) zoom = qMin( zoom * qMax( 1 + diff, 1.2 ), target_zoom ); else Index: effects/shadow.cpp =================================================================== --- kwin/effects/shadow.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/shadow.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -77,7 +77,31 @@ #endif ShadowEffect::ShadowEffect() + : shadowSize( 0 ) +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + , mShadowTexture( NULL ) +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + , mShadowPics( NULL ) +#endif { + reconfigure( ReconfigureAll ); + connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), + this, SLOT(updateShadowColor())); + } + +ShadowEffect::~ShadowEffect() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete mShadowTexture; +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete mShadowPics; +#endif + } + +void ShadowEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig("Shadow"); shadowXOffset = conf.readEntry( "XOffset", 0 ); shadowYOffset = conf.readEntry( "YOffset", 3 ); @@ -86,15 +110,17 @@ shadowSize = conf.readEntry( "Size", 5 ); intensifyActiveShadow = conf.readEntry( "IntensifyActiveShadow", true ); #ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete mShadowTexture; + mShadowTexture = NULL; if ( effects->compositingType() == OpenGLCompositing) { QString shadowtexture = KGlobal::dirs()->findResource("data", "kwin/shadow-texture.png"); mShadowTexture = new GLTexture(shadowtexture); } - else - mShadowTexture = NULL; #endif #ifdef KWIN_HAVE_XRENDER_COMPOSITING + delete mShadowPics; + mShadowPics = NULL; if ( effects->compositingType() == XRenderCompositing) { qreal size = 2*(shadowFuzzyness+shadowSize)+1; @@ -116,25 +142,10 @@ mShadowPics = new ShadowTiles(*shadow); delete shadow; } - else - mShadowPics = NULL; #endif - updateShadowColor(); - connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), - this, SLOT(updateShadowColor())); } -ShadowEffect::~ShadowEffect() - { -#ifdef KWIN_HAVE_OPENGL_COMPOSITING - delete mShadowTexture; -#endif -#ifdef KWIN_HAVE_XRENDER_COMPOSITING - delete mShadowPics; -#endif - } - void ShadowEffect::updateShadowColor() { KConfigGroup conf = effects->effectConfig("Shadow"); @@ -333,7 +344,9 @@ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // We have two elements per vertex in the verts array int verticesCount = verts.count() / 2; + mShadowTexture->enableNormalizedTexCoords(); renderGLGeometry( region, verticesCount, verts.data(), texcoords.data() ); + mShadowTexture->disableNormalizedTexCoords(); mShadowTexture->unbind(); glPopMatrix(); Index: effects/presentwindows.h =================================================================== --- kwin/effects/presentwindows.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/presentwindows.h (.../work/~seli/kwin11.1) (revision 880714) @@ -43,17 +43,25 @@ PresentWindowsEffect(); virtual ~PresentWindowsEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void postPaintScreen(); + virtual void windowAdded( EffectWindow* c ); virtual void windowClosed( EffectWindow* c ); virtual void windowInputMouseEvent( Window w, QEvent* e ); virtual bool borderActivated( ElectricBorder border ); virtual void grabbedKeyboardEvent( QKeyEvent* e ); + virtual void tabBoxAdded( int mode ); + virtual void tabBoxClosed(); + virtual void tabBoxUpdated(); + + enum { LayoutNatural, LayoutRegularGrid, LayoutFlexibleGrid }; // Layout modes + public slots: void setActive(bool active); void toggleActive() { mShowWindowsFromAllDesktops = false; setActive(!mActivated); } @@ -63,9 +71,9 @@ // Updates window tranformations, i.e. destination pos and scale of the window void rearrangeWindows(); void prepareToRearrange(); - void calculateWindowTransformationsDumb(EffectWindowList windowlist); - void calculateWindowTransformationsKompose(EffectWindowList windowlist); + void calculateWindowTransformationsKompose(EffectWindowList windowlist, int screen); void calculateWindowTransformationsClosest(EffectWindowList windowlist, int screen); + void calculateWindowTransformationsNatural(EffectWindowList windowlist, int screen); // Helper methods for layout calculation double windowAspectRatio(EffectWindow* c); @@ -75,6 +83,8 @@ void assignSlots( EffectWindowList windowlist, const QRect& area, int columns, int rows ); void getBestAssignments( EffectWindowList windowlist ); + bool isOverlappingAny( EffectWindow* w, const EffectWindowList& windowlist, const QRegion& border ); + void updateFilterTexture(); void discardFilterTexture(); @@ -82,6 +92,7 @@ void setHighlightedWindow( EffectWindow* w ); EffectWindow* relativeWindow( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const; + EffectWindow* relativeWindowGrid( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const; EffectWindow* findFirstWindow() const; // Called once the effect is activated (and wasn't activated before) @@ -95,9 +106,9 @@ // Whether the effect is currently activated by the user bool mActivated; // 0 = not active, 1 = fully active - double mActiveness; + TimeLine mActiveness; // 0 = start of rearranging (old_area), 1 = done - double mRearranging; + TimeLine mRearranging; Window mInput; bool hasKeyboardGrab; @@ -142,7 +153,13 @@ ElectricBorder borderActivate; ElectricBorder borderActivateAll; + int layoutMode; bool drawWindowCaptions; + bool drawWindowIcons; + bool mTabBoxMode; + bool tabBox; + int accuracy; + bool fillGaps; }; } // namespace Index: effects/lookingglass.h =================================================================== --- kwin/effects/lookingglass.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/lookingglass.h (.../work/~seli/kwin11.1) (revision 880714) @@ -39,6 +39,7 @@ LookingGlassEffect(); virtual ~LookingGlassEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void mouseChanged( const QPoint& pos, const QPoint& old, Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers ); Index: effects/flipswitch_config.cpp =================================================================== --- kwin/effects/flipswitch_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/flipswitch_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -60,7 +60,7 @@ KConfigGroup conf = EffectsHandler::effectConfig( "FlipSwitch" ); - int flipDuration = conf.readEntry( "FlipDuration", 200 ); + int flipDuration = conf.readEntry( "FlipDuration", 0 ); bool animateFlip = conf.readEntry( "AnimateFlip", true ); m_ui->spinFlipDuration->setValue( flipDuration ); if( animateFlip ) @@ -90,7 +90,7 @@ void FlipSwitchEffectConfig::defaults() { - m_ui->spinFlipDuration->setValue( 200 ); + m_ui->spinFlipDuration->setValue( 0 ); m_ui->checkAnimateFlip->setCheckState( Qt::Checked ); emit changed(true); } Index: effects/cube_config.cpp =================================================================== --- kwin/effects/cube_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,273 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "cube_config.h" +#include <kwineffects.h> + +#include <kconfiggroup.h> +#include <kcolorscheme.h> +#include <KActionCollection> +#include <kaction.h> +#include <KFileDialog> +#include <KImageFilePreview> + +#include <QGridLayout> +#include <QColor> +#ifndef KDE_USE_FINAL +KWIN_EFFECT_CONFIG_FACTORY +#endif + +namespace KWin +{ + +CubeEffectConfigForm::CubeEffectConfigForm(QWidget* parent) : QWidget(parent) +{ + setupUi(this); +} + +CubeEffectConfig::CubeEffectConfig(QWidget* parent, const QVariantList& args) : + KCModule(EffectFactory::componentData(), parent, args) + { + m_ui = new CubeEffectConfigForm(this); + + QGridLayout* layout = new QGridLayout(this); + + layout->addWidget(m_ui, 0, 0); + + m_ui->tabWidget->setTabText( 0, i18n("Basic") ); + m_ui->tabWidget->setTabText( 1, i18n("Advanced") ); + + m_ui->screenEdgeCombo->addItem(i18n("Top")); + m_ui->screenEdgeCombo->addItem(i18n("Top-right")); + m_ui->screenEdgeCombo->addItem(i18n("Right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-left")); + m_ui->screenEdgeCombo->addItem(i18n("Left")); + m_ui->screenEdgeCombo->addItem(i18n("Top-left")); + m_ui->screenEdgeCombo->addItem(i18n("None")); + + m_actionCollection = new KActionCollection( this, componentData() ); + m_actionCollection->setConfigGroup( "Cube" ); + m_actionCollection->setConfigGlobal(true); + + KAction* a = (KAction*) m_actionCollection->addAction( "Cube" ); + a->setText( i18n("Desktop Cube" )); + a->setProperty("isConfigurationAction", true); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F11 )); + + m_ui->editor->addCollection(m_actionCollection); + + m_ui->wallpaperRequester->setFilter("*.png *.jpeg *.jpg "); + + connect(m_ui->screenEdgeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + connect(m_ui->rotationDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->displayDesktopNameBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->reflectionBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->backgroundColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->animateDesktopChangeBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->bigCubeBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(capsSelectionChanged())); + connect(m_ui->capsImageBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->capColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->wallpaperRequester, SIGNAL(textChanged(QString)), this, SLOT(changed())); + connect(m_ui->closeOnMouseReleaseBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->zPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->walkThroughDesktopBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + + load(); + } + +void CubeEffectConfig::load() + { + KCModule::load(); + + KConfigGroup conf = EffectsHandler::effectConfig( "Cube" ); + + int duration = conf.readEntry( "RotationDuration", 0 ); + float opacity = conf.readEntry( "Opacity", 80 ); + bool desktopName = conf.readEntry( "DisplayDesktopName", true ); + bool reflection = conf.readEntry( "Reflection", true ); + int activateBorder = conf.readEntry( "BorderActivate", (int)ElectricNone ); + QColor background = conf.readEntry( "BackgroundColor", QColor( Qt::black ) ); + QColor capColor = conf.readEntry( "CapColor", KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + bool texturedCaps = conf.readEntry( "TexturedCaps", true ); + bool caps = conf.readEntry( "Caps", true ); + bool animateChange = conf.readEntry( "AnimateDesktopChange", false ); + bool bigCube = conf.readEntry( "BigCube", false ); + bool closeOnMouseRelease = conf.readEntry( "CloseOnMouseRelease", false ); + bool walkThroughDesktop = conf.readEntry( "TabBox", false ); + m_ui->zPositionSlider->setValue( conf.readEntry( "ZPosition", 100 ) ); + m_ui->wallpaperRequester->setPath( conf.readEntry( "Wallpaper", "" ) ); + if( activateBorder == (int)ElectricNone ) + activateBorder--; + m_ui->screenEdgeCombo->setCurrentIndex( activateBorder ); + + m_ui->rotationDurationSpin->setValue( duration ); + m_ui->cubeOpacitySlider->setValue( opacity ); + m_ui->cubeOpacitySpin->setValue( opacity ); + if( desktopName ) + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Unchecked ); + } + if( reflection ) + { + m_ui->reflectionBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->reflectionBox->setCheckState( Qt::Unchecked ); + } + if( caps ) + { + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->cubeCapsBox->setCheckState( Qt::Unchecked ); + } + if( texturedCaps ) + { + m_ui->capsImageBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->capsImageBox->setCheckState( Qt::Unchecked ); + } + if( animateChange ) + { + m_ui->animateDesktopChangeBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->animateDesktopChangeBox->setCheckState( Qt::Unchecked ); + } + if( bigCube ) + { + m_ui->bigCubeBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->bigCubeBox->setCheckState( Qt::Unchecked ); + } + if( closeOnMouseRelease ) + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + } + if( walkThroughDesktop ) + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + } + m_ui->backgroundColorButton->setColor( background ); + m_ui->capColorButton->setColor( capColor ); + capsSelectionChanged(); + + emit changed(false); + } + +void CubeEffectConfig::save() + { + KConfigGroup conf = EffectsHandler::effectConfig( "Cube" ); + + conf.writeEntry( "RotationDuration", m_ui->rotationDurationSpin->value() ); + conf.writeEntry( "DisplayDesktopName", m_ui->displayDesktopNameBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Reflection", m_ui->reflectionBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Opacity", m_ui->cubeOpacitySpin->value() ); + conf.writeEntry( "BackgroundColor", m_ui->backgroundColorButton->color() ); + conf.writeEntry( "Caps", m_ui->cubeCapsBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CapColor", m_ui->capColorButton->color() ); + conf.writeEntry( "TexturedCaps", m_ui->capsImageBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "AnimateDesktopChange", m_ui->animateDesktopChangeBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "BigCube", m_ui->bigCubeBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CloseOnMouseRelease", m_ui->closeOnMouseReleaseBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Wallpaper", m_ui->wallpaperRequester->url().path() ); + conf.writeEntry( "ZPosition", m_ui->zPositionSlider->value() ); + conf.writeEntry( "TabBox", m_ui->walkThroughDesktopBox->checkState() == Qt::Checked ? true : false ); + + int activateBorder = m_ui->screenEdgeCombo->currentIndex(); + if( activateBorder == (int)ELECTRIC_COUNT ) + activateBorder = (int)ElectricNone; + conf.writeEntry( "BorderActivate", activateBorder ); + + m_ui->editor->save(); + + conf.sync(); + + emit changed(false); + EffectsHandler::sendReloadMessage( "cube" ); + } + +void CubeEffectConfig::defaults() + { + m_ui->rotationDurationSpin->setValue( 0 ); + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + m_ui->reflectionBox->setCheckState( Qt::Checked ); + m_ui->cubeOpacitySpin->setValue( 80 ); + m_ui->cubeOpacitySlider->setValue( 80 ); + m_ui->screenEdgeCombo->setCurrentIndex( (int)ElectricNone -1 ); + m_ui->backgroundColorButton->setColor( QColor( Qt::black ) ); + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + m_ui->capColorButton->setColor( KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + m_ui->capsImageBox->setCheckState( Qt::Checked ); + m_ui->animateDesktopChangeBox->setCheckState( Qt::Unchecked ); + m_ui->bigCubeBox->setCheckState( Qt::Unchecked ); + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + m_ui->wallpaperRequester->setPath( "" ); + m_ui->zPositionSlider->setValue( 100 ); + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + m_ui->editor->allDefault(); + emit changed(true); + } + +void CubeEffectConfig::capsSelectionChanged() + { + if( m_ui->cubeCapsBox->checkState() == Qt::Checked ) + { + // activate cap color + m_ui->capColorButton->setEnabled( true ); + m_ui->capColorLabel->setEnabled( true ); + m_ui->capsImageBox->setEnabled( true ); + } + else + { + // deactivate cap color + m_ui->capColorButton->setEnabled( false ); + m_ui->capColorLabel->setEnabled( false ); + m_ui->capsImageBox->setEnabled( false ); + } + } + +} // namespace + +#include "cube_config.moc" Index: effects/presentwindows_config.ui =================================================================== --- kwin/effects/presentwindows_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/presentwindows_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,249 @@ +<ui version="4.0" > + <class>KWin::PresentWindowsEffectConfigForm</class> + <widget class="QWidget" name="KWin::PresentWindowsEffectConfigForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>430</width> + <height>306</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QGroupBox" name="groupBox" > + <property name="title" > + <string>Appearance</string> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <item row="2" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Rearrange &duration:</string> + </property> + <property name="buddy" > + <cstring>rearrangeDurationSpin</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QSpinBox" name="rearrangeDurationSpin" > + <property name="specialValueText" > + <string>Default</string> + </property> + <property name="suffix" > + <string> msec</string> + </property> + <property name="maximum" > + <number>5000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + <property name="value" > + <number>0</number> + </property> + </widget> + </item> + <item row="4" column="0" colspan="2" > + <widget class="QCheckBox" name="displayTitleBox" > + <property name="text" > + <string>Display window &titles</string> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2" > + <widget class="QCheckBox" name="displayIconBox" > + <property name="text" > + <string>Display window &icons</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2" > + <widget class="QCheckBox" name="switchingBox" > + <property name="text" > + <string>Use for window &switching</string> + </property> + </widget> + </item> + <item row="3" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Layout mode:</string> + </property> + <property name="buddy" > + <cstring>layoutCombo</cstring> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QComboBox" name="layoutCombo" > + <item> + <property name="text" > + <string>Natural</string> + </property> + </item> + <item> + <property name="text" > + <string>Regular grid</string> + </property> + </item> + <item> + <property name="text" > + <string>Flexible grid</string> + </property> + </item> + </widget> + </item> + </layout> + </widget> + </item> + <item row="1" column="0" colspan="2" > + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Activation</string> + </property> + <layout class="QGridLayout" name="gridLayout_2" > + <item row="5" column="0" colspan="2" > + <widget class="KWin::GlobalShortcutsEditor" native="1" name="shortcutEditor" > + <property name="sizePolicy" > + <sizepolicy vsizetype="Preferred" hsizetype="Preferred" > + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Active screen &edge (Current desktop):</string> + </property> + <property name="buddy" > + <cstring>screenEdgeCombo</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QComboBox" name="screenEdgeCombo" /> + </item> + <item row="0" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Active screen &edge (All desktops):</string> + </property> + <property name="buddy" > + <cstring>screenEdgeAllCombo</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QComboBox" name="screenEdgeAllCombo" /> + </item> + </layout> + </widget> + </item> + <item row="0" column="1" > + <widget class="QGroupBox" name="groupBox_3" > + <property name="title" > + <string>Natural Layout Settings</string> + </property> + <layout class="QGridLayout" name="gridLayout_4" > + <item row="5" column="0" > + <widget class="QCheckBox" name="fillGapsBox" > + <property name="text" > + <string>Fill &gaps</string> + </property> + </widget> + </item> + <item row="6" column="0" > + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>Faster</string> + </property> + <property name="buddy" > + <cstring></cstring> + </property> + </widget> + </item> + <item> + <widget class="QSlider" name="accuracySlider" > + <property name="minimum" > + <number>1</number> + </property> + <property name="maximum" > + <number>8</number> + </property> + <property name="singleStep" > + <number>1</number> + </property> + <property name="pageStep" > + <number>1</number> + </property> + <property name="value" > + <number>1</number> + </property> + <property name="tracking" > + <bool>true</bool> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="invertedAppearance" > + <bool>true</bool> + </property> + <property name="invertedControls" > + <bool>false</bool> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>Nicer</string> + </property> + <property name="buddy" > + <cstring></cstring> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KWin::GlobalShortcutsEditor</class> + <extends>QWidget</extends> + <header location="global" >kwineffects.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>rearrangeDurationSpin</tabstop> + <tabstop>displayTitleBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> Index: effects/snow_config.cpp =================================================================== --- kwin/effects/snow_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/snow_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -25,7 +25,6 @@ #include <kdebug.h> #include <KActionCollection> #include <kaction.h> -#include <KGlobalAccel> #include <kconfiggroup.h> #include <QGridLayout> Index: effects/cube.cpp =================================================================== --- kwin/effects/cube.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,1669 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "cube.h" + +#include <kaction.h> +#include <kactioncollection.h> +#include <klocale.h> +#include <kwinconfig.h> +#include <kconfiggroup.h> +#include <kcolorscheme.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <kdebug.h> + +#include <QColor> +#include <QRect> +#include <QEvent> +#include <QKeyEvent> + +#include <math.h> + +#include <GL/gl.h> + +namespace KWin +{ + +KWIN_EFFECT( cube, CubeEffect ) + +CubeEffect::CubeEffect() + : activated( false ) + , cube_painting( false ) + , keyboard_grab( false ) + , schedule_close( false ) + , borderActivate( ElectricNone ) + , frontDesktop( 0 ) + , cubeOpacity( 1.0 ) + , displayDesktopName( true ) + , reflection( true ) + , rotating( false ) + , desktopChangedWhileRotating( false ) + , paintCaps( true ) + , rotationDirection( Left ) + , verticalRotationDirection( Upwards ) + , verticalPosition( Normal ) + , wallpaper( NULL ) + , texturedCaps( true ) + , capTexture( NULL ) + , manualAngle( 0.0 ) + , manualVerticalAngle( 0.0 ) + , currentShape( TimeLine::EaseInOutCurve ) + , start( false ) + , stop( false ) + , reflectionPainting( false ) + , slide( false ) + , oldDesktop( 0 ) + , activeScreen( 0 ) + , animateDesktopChange( false ) + , bigCube( false ) + , bottomCap( false ) + , closeOnMouseRelease( false ) + , zoom( 0.0 ) + , zPosition( 0.0 ) + , useForTabBox( false ) + , tabBoxMode( false ) + , capListCreated( false ) + , capList( 0 ) + { + reconfigure( ReconfigureAll ); + + KActionCollection* actionCollection = new KActionCollection( this ); + KAction* a = static_cast< KAction* >( actionCollection->addAction( "Cube" )); + a->setText( i18n("Desktop Cube" )); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F11 )); + connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle())); + } + +void CubeEffect::reconfigure( ReconfigureFlags ) + { + loadConfig( "Cube" ); + } + +void CubeEffect::loadConfig( QString config ) + { + KConfigGroup conf = effects->effectConfig( config ); + effects->unreserveElectricBorder( borderActivate ); + borderActivate = (ElectricBorder)conf.readEntry( "BorderActivate", (int)ElectricNone ); + effects->reserveElectricBorder( borderActivate ); + + cubeOpacity = (float)conf.readEntry( "Opacity", 80 )/100.0f; + displayDesktopName = conf.readEntry( "DisplayDesktopName", true ); + reflection = conf.readEntry( "Reflection", true ); + rotationDuration = animationTime( conf, "RotationDuration", 500 ); + backgroundColor = conf.readEntry( "BackgroundColor", QColor( Qt::black ) ); + animateDesktopChange = conf.readEntry( "AnimateDesktopChange", false ); + bigCube = conf.readEntry( "BigCube", false ); + capColor = conf.readEntry( "CapColor", KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + paintCaps = conf.readEntry( "Caps", true ); + closeOnMouseRelease = conf.readEntry( "CloseOnMouseRelease", false ); + zPosition = conf.readEntry( "ZPosition", 100.0 ); + useForTabBox = conf.readEntry( "TabBox", false ); + QString file = conf.readEntry( "Wallpaper", QString("") ); + delete wallpaper; + wallpaper = NULL; + if( !file.isEmpty() ) + { + QImage img = QImage( file ); + if( !img.isNull() ) + { + wallpaper = new GLTexture( img ); + } + } + delete capTexture; + capTexture = NULL; + texturedCaps = conf.readEntry( "TexturedCaps", true ); + if( texturedCaps ) + { + QImage img = QImage( KGlobal::dirs()->findResource( "appdata", "cubecap.png" ) ); + if( !img.isNull() ) + { + // change the alpha value of each pixel + for( int x=0; x<img.width(); x++ ) + { + for( int y=0; y<img.height(); y++ ) + { + QRgb pixel = img.pixel( x, y ); + if( x == 0 || x == img.width()-1 || y == 0 || y == img.height()-1 ) + img.setPixel( x, y, qRgba( capColor.red(), capColor.green(), capColor.blue(), 255*cubeOpacity ) ); + else + { + if( qAlpha(pixel) < 255 ) + { + // Pixel is transparent - has to be blended with cap color + int red = (qAlpha(pixel)/255)*(qRed(pixel)/255) + (1 - qAlpha(pixel)/255 )*capColor.red(); + int green = (qAlpha(pixel)/255)*(qGreen(pixel)/255) + (1 - qAlpha(pixel)/255 )*capColor.green(); + int blue = (qAlpha(pixel)/255)*(qBlue(pixel)/255) + (1 - qAlpha(pixel)/255 )*capColor.blue(); + int alpha = qAlpha(pixel) + (255 - qAlpha(pixel))*cubeOpacity; + img.setPixel( x, y, qRgba( red, green, blue, alpha ) ); + } + else + { + img.setPixel( x, y, qRgba( qRed(pixel), qGreen(pixel), qBlue(pixel), ((float)qAlpha(pixel))*cubeOpacity ) ); + } + } + } + } + capTexture = new GLTexture( img ); + capTexture->setFilter( GL_LINEAR ); + capTexture->setWrapMode( GL_CLAMP_TO_EDGE ); + } + } + + timeLine.setCurveShape( TimeLine::EaseInOutCurve ); + timeLine.setDuration( rotationDuration ); + + verticalTimeLine.setCurveShape( TimeLine::EaseInOutCurve ); + verticalTimeLine.setDuration( rotationDuration ); + } + +CubeEffect::~CubeEffect() + { + effects->unreserveElectricBorder( borderActivate ); + delete wallpaper; + delete capTexture; + } + +void CubeEffect::prePaintScreen( ScreenPrePaintData& data, int time ) + { + if( activated ) + { + //kDebug(); + data.mask |= PAINT_SCREEN_TRANSFORMED | Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST; + + if( rotating || start || stop ) + { + timeLine.addTime( time ); + } + if( verticalRotating ) + { + verticalTimeLine.addTime( time ); + } + } + effects->prePaintScreen( data, time ); + } + +void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) + { + if( activated ) + { + //kDebug(); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && (slide || bigCube ) ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + + // background + float clearColor[4]; + glGetFloatv( GL_COLOR_CLEAR_VALUE, clearColor ); + glClearColor( backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF(), 1.0 ); + glClear( GL_COLOR_BUFFER_BIT ); + glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] ); + + // wallpaper + if( wallpaper && !slide ) + { + wallpaper->bind(); + wallpaper->render( region, rect ); + wallpaper->unbind(); + } + + glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + if( effects->numScreens() > 1 && !slide && !bigCube ) + { + windowsOnOtherScreens.clear(); + // unfortunatelly we have to change the projection matrix in dual screen mode + glMatrixMode( GL_PROJECTION ); + glPushMatrix(); + glLoadIdentity(); + float fovy = 60.0f; + float aspect = 1.0f; + float zNear = 0.1f; + float zFar = 100.0f; + float ymax = zNear * tan( fovy * M_PI / 360.0f ); + float ymin = -ymax; + float xmin = ymin * aspect; + float xmax = ymax * aspect; + float xTranslate = 0.0; + float yTranslate = 0.0; + bool projectionSet = false; + if( rect.x() == 0 && rect.width() != fullRect.width() ) + { + // horizontal layout: left screen + glFrustum( xmin*0.5, xmax*1.5, ymin, ymax, zNear, zFar ); + xTranslate = rect.width()*0.5; + projectionSet = true; + } + if( rect.x() != 0 && rect.width() != fullRect.width() ) + { + // horizontal layout: right screen + glFrustum( xmin*1.5, xmax*0.5, ymin, ymax, zNear, zFar ); + xTranslate = rect.width()*0.5; + projectionSet = true; + } + if( rect.y() == 0 && rect.height() != fullRect.height() ) + { + glFrustum( xmin, xmax, ymin*1.5, ymax*0.5, zNear, zFar ); + yTranslate = rect.height()*0.5; + projectionSet = true; + } + if( rect.y() != 0 && rect.height() != fullRect.height() ) + { + glFrustum( xmin, xmax, ymin*0.5, ymax*1.5, zNear, zFar ); + yTranslate = rect.height()*0.5; + projectionSet = true; + } + if( !projectionSet ) + { + // this should never happen; nevertheless reset the projection to the default + glPopMatrix(); + glPushMatrix(); + } + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glTranslatef( xTranslate, yTranslate, 0.0 ); + } + + // reflection + if( reflection && (!slide) ) + { + glPushMatrix(); + float scaleFactor = 10000 * tan( 60.0 * M_PI / 360.0f )/rect.height(); + glScalef( 1.0, -1.0, 1.0 ); + glTranslatef( 0.0, -rect.height()*2, 0.0 ); + + glEnable( GL_CLIP_PLANE0 ); + reflectionPainting = true; + paintScene( mask, region, data ); + reflectionPainting = false; + glDisable( GL_CLIP_PLANE0 ); + + glPopMatrix(); + glPushMatrix(); + glTranslatef( 0.0, rect.height(), 0.0 ); + if( effects->numScreens() > 1 && rect.width() != fullRect.width() && !slide && !bigCube ) + { + // have to change the reflection area in horizontal layout and right screen + glTranslatef( -rect.width(), 0.0, 0.0 ); + } + float vertices[] = { + rect.x(), 0.0, 0.0, + rect.x()+rect.width(), 0.0, 0.0, + (rect.x()+rect.width())*scaleFactor, 0.0, -5000, + (-rect.x()-rect.width())*scaleFactor, 0.0, -5000 }; + // foreground + float alpha = 0.7; + if( start ) + alpha = 0.3 + 0.4 * timeLine.value(); + if( stop ) + alpha = 0.3 + 0.4 * ( 1.0 - timeLine.value() ); + glColor4f( 0.0, 0.0, 0.0, alpha ); + glBegin( GL_POLYGON ); + glVertex3f( vertices[0], vertices[1], vertices[2] ); + glVertex3f( vertices[3], vertices[4], vertices[5] ); + // rearground + alpha = -1.0; + glColor4f( 0.0, 0.0, 0.0, alpha ); + glVertex3f( vertices[6], vertices[7], vertices[8] ); + glVertex3f( vertices[9], vertices[10], vertices[11] ); + glEnd(); + glPopMatrix(); + } + glPushMatrix(); + paintScene( mask, region, data ); + glPopMatrix(); + + if( effects->numScreens() > 1 && !slide && !bigCube ) + { + glPopMatrix(); + // revert change of projection matrix + glMatrixMode( GL_PROJECTION ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + } + + glDisable( GL_BLEND ); + glPopAttrib(); + + // desktop name box - inspired from coverswitch + if( displayDesktopName && (!slide) ) + { + QColor color_frame; + QColor color_text; + color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color(); + color_frame.setAlphaF( 0.5 ); + color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color(); + if( start ) + { + color_frame.setAlphaF( 0.5 * timeLine.value() ); + color_text.setAlphaF( timeLine.value() ); + } + if( stop ) + { + color_frame.setAlphaF( 0.5 - 0.5 * timeLine.value() ); + color_text.setAlphaF( 1.0 - timeLine.value() ); + } + QFont text_font; + text_font.setBold( true ); + text_font.setPointSize( 14 ); + glPushAttrib( GL_CURRENT_BIT ); + glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF()); + QRect frameRect = QRect( rect.width()*0.33f + rect.x(), + rect.height() + rect.y() - QFontMetrics( text_font ).height() * 1.2f, + rect.width()*0.33f, + QFontMetrics( text_font ).height() * 1.2f ); + renderRoundBoxWithEdge( frameRect ); + effects->paintText( effects->desktopName( frontDesktop ), + frameRect.center(), + frameRect.width(), + color_text, + text_font ); + glPopAttrib(); + } + if( stop && timeLine.value() == 1.0 ) + { + effects->paintScreen( mask, region, data ); + } + if( effects->numScreens() > 1 && !slide && !bigCube ) + { + foreach( EffectWindow* w, windowsOnOtherScreens ) + { + WindowPaintData wData( w ); + if( start && !w->isDesktop() && !w->isDock() ) + wData.opacity *= (1.0 - timeLine.value()); + if( stop && !w->isDesktop() && !w->isDock() ) + wData.opacity *= timeLine.value(); + effects->paintWindow( w, 0, QRegion( w->x(), w->y(), w->width(), w->height() ), wData ); + } + } + } + else + { + effects->paintScreen( mask, region, data ); + } + } + +void CubeEffect::paintScene( int mask, QRegion region, ScreenPaintData& data ) + { + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && (slide || bigCube ) ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + float xScale = 1.0; + float yScale = 1.0; + if( effects->numScreens() > 1 && !slide && !bigCube ) + { + QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + xScale = (float)rect.width()/(float)fullRect.width(); + yScale = (float)rect.height()/(float)fullRect.height(); + if( start ) + { + xScale = xScale + (1.0 - xScale) * (1.0 - timeLine.value()); + yScale = yScale + (1.0 - yScale) * (1.0 - timeLine.value()); + if( rect.x() > 0 ) + glTranslatef( -rect.x()*(1.0 - timeLine.value()), 0.0, 0.0 ); + if( rect.y() > 0 ) + glTranslatef( 0.0, -rect.y()*(1.0 - timeLine.value()), 0.0 ); + } + if( stop ) + { + xScale = xScale + (1.0 - xScale) * timeLine.value(); + yScale = yScale + (1.0 - yScale) * timeLine.value(); + if( rect.x() > 0 ) + glTranslatef( -rect.x()*timeLine.value(), 0.0, 0.0 ); + if( rect.y() > 0 ) + glTranslatef( 0.0, -rect.y()*timeLine.value(), 0.0 ); + } + glScalef( xScale, yScale, 1.0 ); + rect = fullRect; + } + int rightSteps = effects->numberOfDesktops()/2; + int leftSteps = rightSteps+1; + int rightSideCounter = 0; + int leftSideCounter = 0; + float internalCubeAngle = 360.0f / effects->numberOfDesktops(); + cube_painting = true; + int desktopIndex = 0; + float zTranslate = zPosition + zoom; + if( start ) + zTranslate *= timeLine.value(); + if( stop ) + zTranslate *= ( 1.0 - timeLine.value() ); + if( slide ) + zTranslate = 0.0; + + bool topCapAfter = false; + bool topCapBefore = false; + + // Rotation of the cube + float cubeAngle = (float)((float)(effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f); + float point = rect.width()/2*tan(cubeAngle*0.5f*M_PI/180.0f); + float zTexture = rect.width()/2*tan(45.0f*M_PI/180.0f); + if( verticalRotating || verticalPosition != Normal || manualVerticalAngle != 0.0 ) + { + // change the verticalPosition if manualVerticalAngle > 90 or < -90 degrees + if( manualVerticalAngle <= -90.0 ) + { + manualVerticalAngle += 90.0; + if( verticalPosition == Normal ) + verticalPosition = Down; + if( verticalPosition == Up ) + verticalPosition = Normal; + } + if( manualVerticalAngle >= 90.0 ) + { + manualVerticalAngle -= 90.0; + if( verticalPosition == Normal ) + verticalPosition = Up; + if( verticalPosition == Down ) + verticalPosition = Normal; + } + float angle = 0.0; + if( verticalPosition == Up ) + { + angle = 90.0; + if( !verticalRotating) + { + if( manualVerticalAngle < 0.0 ) + angle += manualVerticalAngle; + else + manualVerticalAngle = 0.0; + } + } + else if( verticalPosition == Down ) + { + angle = -90.0; + if( !verticalRotating) + { + if( manualVerticalAngle > 0.0 ) + angle += manualVerticalAngle; + else + manualVerticalAngle = 0.0; + } + } + else + { + angle = manualVerticalAngle; + } + if( verticalRotating ) + { + angle *= verticalTimeLine.value(); + if( verticalPosition == Normal && verticalRotationDirection == Upwards ) + angle = -90.0 + 90*verticalTimeLine.value(); + if( verticalPosition == Normal && verticalRotationDirection == Downwards ) + angle = 90.0 - 90*verticalTimeLine.value(); + angle += manualVerticalAngle * (1.0-verticalTimeLine.value()); + } + if( stop ) + angle *= (1.0 - timeLine.value()); + glTranslatef( rect.width()/2, rect.height()/2, -point-zTranslate ); + glRotatef( angle, 1.0, 0.0, 0.0 ); + glTranslatef( -rect.width()/2, -rect.height()/2, point+zTranslate ); + + // calculate if the caps have to be painted before/after or during desktop painting + if( paintCaps ) + { + float M[16]; + float P[16]; + float V[4]; + glGetFloatv( GL_PROJECTION_MATRIX, P ); + glGetFloatv( GL_MODELVIEW_MATRIX, M ); + glGetFloatv( GL_VIEWPORT, V ); + + // calculate y coordinate of the top of front desktop + float X = M[0]*0.0 + M[4]*0.0 + M[8]*(-zTranslate) + M[12]*1; + float Y = M[1]*0.0 + M[5]*0.0 + M[9]*(-zTranslate) + M[13]*1; + float Z = M[2]*0.0 + M[6]*0.0 + M[10]*(-zTranslate) + M[14]*1; + float W = M[3]*0.0 + M[7]*0.0 + M[11]*(-zTranslate) + M[15]*1; + float clipY = P[1]*X + P[5]*Y + P[9]*Z + P[13]*W; + float clipW = P[3]*X + P[7]*Y + P[11]*Z + P[15]*W; + float normY = clipY/clipW; + float yFront = (V[3]/2)*normY+(V[3]-V[1])/2; + + // calculate y coordinate of the bottom of front desktop + X = M[0]*0.0 + M[4]*rect.height() + M[8]*(-zTranslate) + M[12]*1; + Y = M[1]*0.0 + M[5]*rect.height() + M[9]*(-zTranslate) + M[13]*1; + Z = M[2]*0.0 + M[6]*rect.height() + M[10]*(-zTranslate) + M[14]*1; + W = M[3]*0.0 + M[7]*rect.height() + M[11]*(-zTranslate) + M[15]*1; + clipY = P[1]*X + P[5]*Y + P[9]*Z + P[13]*W; + clipW = P[3]*X + P[7]*Y + P[11]*Z + P[15]*W; + normY = clipY/clipW; + float yFrontBottom = (V[3]/2)*normY+(V[3]-V[1])/2; + + // change matrix to a rear position + glPushMatrix(); + glTranslatef( 0.0, 0.0, -point-zTranslate ); + float desktops = (effects->numberOfDesktops()/2.0); + glRotatef( desktops*internalCubeAngle, 1.0, 0.0, 0.0 ); + glTranslatef( 0.0, 0.0, point ); + glGetFloatv(GL_MODELVIEW_MATRIX, M); + // calculate y coordinate of the top of rear desktop + X = M[0]*0.0 + M[4]*0.0 + M[8]*0.0 + M[12]*1; + Y = M[1]*0.0 + M[5]*0.0 + M[9]*0.0 + M[13]*1; + Z = M[2]*0.0 + M[6]*0.0 + M[10]*0.0 + M[14]*1; + W = M[3]*0.0 + M[7]*0.0 + M[11]*0.0 + M[15]*1; + clipY = P[1]*X + P[5]*Y + P[9]*Z + P[13]*W; + clipW = P[3]*X + P[7]*Y + P[11]*Z + P[15]*W; + normY = clipY/clipW; + float yBack = (V[3]/2)*normY+(V[3]-V[1])/2; + + // calculate y coordniate of the bottom of rear desktop + glTranslatef( 0.0, -rect.height(), 0.0 ); + glGetFloatv(GL_MODELVIEW_MATRIX, M); + X = M[0]*0.0 + M[4]*0.0 + M[8]*0.0 + M[12]*1; + Y = M[1]*0.0 + M[5]*0.0 + M[9]*0.0 + M[13]*1; + Z = M[2]*0.0 + M[6]*0.0 + M[10]*0.0 + M[14]*1; + W = M[3]*0.0 + M[7]*0.0 + M[11]*0.0 + M[15]*1; + clipY = P[1]*X + P[5]*Y + P[9]*Z + P[13]*W; + clipW = P[3]*X + P[7]*Y + P[11]*Z + P[15]*W; + normY = clipY/clipW; + float yBackBottom = (V[3]/2)*normY+(V[3]-V[1])/2; + glPopMatrix(); + if( yBack >= yFront ) + topCapAfter = true; + if( yBackBottom <= yFrontBottom ) + topCapBefore = true; + } + } + if( rotating || (manualAngle != 0.0) ) + { + if( manualAngle > internalCubeAngle * 0.5f ) + { + manualAngle -= internalCubeAngle; + frontDesktop--; + if( frontDesktop == 0 ) + frontDesktop = effects->numberOfDesktops(); + } + if( manualAngle < -internalCubeAngle * 0.5f ) + { + manualAngle += internalCubeAngle; + frontDesktop++; + if( frontDesktop > effects->numberOfDesktops() ) + frontDesktop = 1; + } + float rotationAngle = internalCubeAngle * timeLine.value(); + if( rotationAngle > internalCubeAngle * 0.5f ) + { + rotationAngle -= internalCubeAngle; + if( !desktopChangedWhileRotating ) + { + desktopChangedWhileRotating = true; + if( rotationDirection == Left ) + { + frontDesktop++; + } + else if( rotationDirection == Right ) + { + frontDesktop--; + } + if( frontDesktop > effects->numberOfDesktops() ) + frontDesktop = 1; + else if( frontDesktop == 0 ) + frontDesktop = effects->numberOfDesktops(); + } + } + if( rotationDirection == Left ) + { + rotationAngle *= -1; + } + if( stop ) + rotationAngle = manualAngle * (1.0 - timeLine.value()); + else + rotationAngle += manualAngle * (1.0 - timeLine.value()); + glTranslatef( rect.width()/2, rect.height()/2, -point-zTranslate ); + glRotatef( rotationAngle, 0.0, 1.0, 0.0 ); + glTranslatef( -rect.width()/2, -rect.height()/2, point+zTranslate ); + } + + if( topCapBefore || topCapAfter ) + { + if( (topCapAfter && !reflectionPainting) || (topCapBefore && reflectionPainting) ) + { + // paint the bottom cap + bottomCap = true; + glTranslatef( 0.0, rect.height(), 0.0 ); + paintCap( point, zTexture ); + glTranslatef( 0.0, -rect.height(), 0.0 ); + bottomCap = false; + } + if( (topCapBefore && !reflectionPainting) || (topCapAfter && reflectionPainting) ) + { + // paint the top cap + paintCap( point, zTexture ); + } + } + + for( int i=0; i<effects->numberOfDesktops(); i++ ) + { + if( !topCapAfter && !topCapBefore && i == effects->numberOfDesktops()/2 -1 && !slide ) + { + // paint the bottom cap + bottomCap = true; + glTranslatef( 0.0, rect.height(), 0.0 ); + paintCap( point, zTexture ); + glTranslatef( 0.0, -rect.height(), 0.0 ); + bottomCap = false; + // paint the top cap + paintCap( point, zTexture ); + } + if( i%2 == 0 && i != effects->numberOfDesktops() -1) + { + // desktops on the right (including back) + desktopIndex = rightSteps - rightSideCounter; + rightSideCounter++; + } + else + { + // desktops on the left (including front) + desktopIndex = leftSteps + leftSideCounter; + leftSideCounter++; + } + + // start painting the cube + painting_desktop = (desktopIndex + frontDesktop )%effects->numberOfDesktops(); + if( painting_desktop == 0 ) + { + painting_desktop = effects->numberOfDesktops(); + } + if( slide ) + { + // only paint required desktops during slide phase + if( painting_desktop != frontDesktop ) + { + int leftDesktop = frontDesktop - 1; + int rightDesktop = frontDesktop + 1; + if( leftDesktop == 0 ) + leftDesktop = effects->numberOfDesktops(); + if( rightDesktop > effects->numberOfDesktops() ) + rightDesktop = 1; + if( !desktopChangedWhileRotating && rotationDirection == Left && painting_desktop != rightDesktop ) + { + continue; + } + if( desktopChangedWhileRotating && rotationDirection == Left && painting_desktop != leftDesktop ) + { + continue; + } + if( !desktopChangedWhileRotating && rotationDirection == Right && painting_desktop != leftDesktop ) + { + continue; + } + if( desktopChangedWhileRotating && rotationDirection == Right && painting_desktop != rightDesktop ) + { + continue; + } + } + } + ScreenPaintData newData = data; + RotationData rot = RotationData(); + rot.axis = RotationData::YAxis; + rot.angle = internalCubeAngle * desktopIndex; + rot.xRotationPoint = rect.width()/2; + rot.zRotationPoint = -point; + newData.rotation = &rot; + newData.zTranslate = -zTranslate; + effects->paintScreen( mask, region, newData ); + } + if( topCapBefore || topCapAfter ) + { + if( (topCapAfter && !reflectionPainting) || (topCapBefore && reflectionPainting) ) + { + // paint the top cap + paintCap( point, zTexture ); + } + if( (topCapBefore && !reflectionPainting) || (topCapAfter && reflectionPainting) ) + { + // paint the bottom cap + bottomCap = true; + glTranslatef( 0.0, rect.height(), 0.0 ); + paintCap( point, zTexture ); + glTranslatef( 0.0, -rect.height(), 0.0 ); + bottomCap = false; + } + } + cube_painting = false; + painting_desktop = effects->currentDesktop(); + } + +void CubeEffect::paintCap( float z, float zTexture ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop()); + if( ( !paintCaps ) || effects->numberOfDesktops() <= 2 ) + return; + float opacity = cubeOpacity; + if( start ) + opacity = 1.0 - (1.0 - opacity)*timeLine.value(); + if( stop ) + opacity = 1.0 - (1.0 - opacity)*( 1.0 - timeLine.value() ); + glColor4f( capColor.redF(), capColor.greenF(), capColor.blueF(), opacity ); + float angle = 360.0f/effects->numberOfDesktops(); + glPushMatrix(); + float zTranslate = zPosition + zoom; + if( start ) + zTranslate *= timeLine.value(); + if( stop ) + zTranslate *= ( 1.0 - timeLine.value() ); + glTranslatef( rect.width()/2, 0.0, -z-zTranslate ); + glRotatef( (1-frontDesktop)*angle, 0.0, 1.0, 0.0 ); + + if( !capListCreated ) + { + capListCreated = true; + glNewList( capList, GL_COMPILE_AND_EXECUTE ); + bool texture = false; + if( texturedCaps && effects->numberOfDesktops() > 3 && capTexture ) + { + texture = true; + paintCapStep( z, zTexture, true ); + } + else + paintCapStep( z, zTexture, false ); + glEndList(); + } + else + glCallList( capList ); + glPopMatrix(); + } + +void CubeEffect::paintCapStep( float z, float zTexture, bool texture ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop()); + float angle = 360.0f/effects->numberOfDesktops(); + if( texture ) + capTexture->bind(); + for( int i=0; i<effects->numberOfDesktops(); i++ ) + { + int triangleRows = effects->numberOfDesktops()*5; + float zTriangleDistance = z/(float)triangleRows; + float widthTriangle = tan( angle*0.5 * M_PI/180.0 ) * zTriangleDistance; + float currentWidth = 0.0; + glBegin( GL_TRIANGLES ); + float cosValue = cos( i*angle * M_PI/180.0 ); + float sinValue = sin( i*angle * M_PI/180.0 ); + for( int j=0; j<triangleRows; j++ ) + { + float previousWidth = currentWidth; + currentWidth = tan( angle*0.5 * M_PI/180.0 ) * zTriangleDistance * (j+1); + int evenTriangles = 0; + int oddTriangles = 0; + for( int k=0; k<floor(currentWidth/widthTriangle*2-1+0.5f); k++ ) + { + float x1 = -previousWidth; + float x2 = -currentWidth; + float x3 = 0.0; + float z1 = 0.0; + float z2 = 0.0; + float z3 = 0.0; + if( k%2 == 0 ) + { + x1 += evenTriangles*widthTriangle*2; + x2 += evenTriangles*widthTriangle*2; + x3 = x2+widthTriangle*2; + z1 = j*zTriangleDistance; + z2 = (j+1)*zTriangleDistance; + z3 = (j+1)*zTriangleDistance; + float xRot = cosValue * x1 - sinValue * z1; + float zRot = sinValue * x1 + cosValue * z1; + x1 = xRot; + z1 = zRot; + xRot = cosValue * x2 - sinValue * z2; + zRot = sinValue * x2 + cosValue * z2; + x2 = xRot; + z2 = zRot; + xRot = cosValue * x3 - sinValue * z3; + zRot = sinValue * x3 + cosValue * z3; + x3 = xRot; + z3 = zRot; + evenTriangles++; + } + else + { + x1 += oddTriangles*widthTriangle*2; + x2 += (oddTriangles+1)*widthTriangle*2; + x3 = x1+widthTriangle*2; + z1 = j*zTriangleDistance; + z2 = (j+1)*zTriangleDistance; + z3 = j*zTriangleDistance; + float xRot = cosValue * x1 - sinValue * z1; + float zRot = sinValue * x1 + cosValue * z1; + x1 = xRot; + z1 = zRot; + xRot = cosValue * x2 - sinValue * z2; + zRot = sinValue * x2 + cosValue * z2; + x2 = xRot; + z2 = zRot; + xRot = cosValue * x3 - sinValue * z3; + zRot = sinValue * x3 + cosValue * z3; + x3 = xRot; + z3 = zRot; + oddTriangles++; + } + float texX1 = 0.0; + float texX2 = 0.0; + float texX3 = 0.0; + float texY1 = 0.0; + float texY2 = 0.0; + float texY3 = 0.0; + if( texture ) + { + texX1 = x1/(rect.width())+0.5; + texY1 = 0.5 - z1/zTexture * 0.5; + texX2 = x2/(rect.width())+0.5; + texY2 = 0.5 - z2/zTexture * 0.5; + texX3 = x3/(rect.width())+0.5; + texY3 = 0.5 - z3/zTexture * 0.5; + glTexCoord2f( texX1, texY1 ); + } + glVertex3f( x1, 0.0, z1 ); + if( texture ) + { + glTexCoord2f( texX2, texY2 ); + } + glVertex3f( x2, 0.0, z2 ); + if( texture ) + { + glTexCoord2f( texX3, texY3 ); + } + glVertex3f( x3, 0.0, z3 ); + } + } + glEnd(); + } + if( texture ) + { + capTexture->unbind(); + } + } + +void CubeEffect::postPaintScreen() + { + effects->postPaintScreen(); + if( activated ) + { + //kDebug(); + if( start ) + { + if( timeLine.value() == 1.0 ) + { + start = false; + timeLine.setProgress(0.0); + // more rotations? + if( !rotations.empty() ) + { + rotationDirection = rotations.dequeue(); + rotating = true; + // change the curve shape if current shape is not easeInOut + if( currentShape != TimeLine::EaseInOutCurve ) + { + // more rotations follow -> linear curve + if( !rotations.empty() ) + { + currentShape = TimeLine::LinearCurve; + } + // last rotation step -> easeOut curve + else + { + currentShape = TimeLine::EaseOutCurve; + } + timeLine.setCurveShape( currentShape ); + } + else + { + // if there is at least one more rotation, we can change to easeIn + if( !rotations.empty() ) + { + currentShape = TimeLine::EaseInCurve; + timeLine.setCurveShape( currentShape ); + } + } + } + } + effects->addRepaintFull(); + return; // schedule_close could have been called, start has to finish first + } + if( stop ) + { + if( timeLine.value() == 1.0 ) + { + stop = false; + timeLine.setProgress(0.0); + activated = false; + // set the new desktop + if( keyboard_grab ) + effects->ungrabKeyboard(); + keyboard_grab = false; + effects->destroyInputWindow( input ); + + effects->setActiveFullScreenEffect( 0 ); + + // delete the GL lists + glDeleteLists( capList, 1 ); + } + effects->addRepaintFull(); + } + if( rotating || verticalRotating ) + { + if( rotating && timeLine.value() == 1.0 ) + { + timeLine.setProgress(0.0); + rotating = false; + desktopChangedWhileRotating = false; + manualAngle = 0.0; + // more rotations? + if( !rotations.empty() ) + { + rotationDirection = rotations.dequeue(); + rotating = true; + // change the curve shape if current shape is not easeInOut + if( currentShape != TimeLine::EaseInOutCurve ) + { + // more rotations follow -> linear curve + if( !rotations.empty() ) + { + currentShape = TimeLine::LinearCurve; + } + // last rotation step -> easeOut curve + else + { + currentShape = TimeLine::EaseOutCurve; + } + timeLine.setCurveShape( currentShape ); + } + else + { + // if there is at least one more rotation, we can change to easeIn + if( !rotations.empty() ) + { + currentShape = TimeLine::EaseInCurve; + timeLine.setCurveShape( currentShape ); + } + } + } + else + { + // reset curve shape if there are no more rotations + if( currentShape != TimeLine::EaseInOutCurve ) + { + currentShape = TimeLine::EaseInOutCurve; + timeLine.setCurveShape( currentShape ); + } + } + } + if( verticalRotating && verticalTimeLine.value() == 1.0 ) + { + verticalTimeLine.setProgress(0.0); + verticalRotating = false; + manualVerticalAngle = 0.0; + // more rotations? + if( !verticalRotations.empty() ) + { + verticalRotationDirection = verticalRotations.dequeue(); + verticalRotating = true; + if( verticalRotationDirection == Upwards ) + { + if( verticalPosition == Normal ) + verticalPosition = Up; + if( verticalPosition == Down ) + verticalPosition = Normal; + } + if( verticalRotationDirection == Downwards ) + { + if( verticalPosition == Normal ) + verticalPosition = Down; + if( verticalPosition == Up ) + verticalPosition = Normal; + } + } + } + effects->addRepaintFull(); + return; // rotation has to end before cube is closed + } + if( schedule_close ) + { + schedule_close = false; + if( !slide ) + { + effects->setCurrentDesktop( frontDesktop ); + stop = true; + } + else + { + activated = false; + slide = false; + timeLine.setDuration( rotationDuration ); + effects->setActiveFullScreenEffect( 0 ); + } + effects->addRepaintFull(); + } + } + } + +void CubeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { + if( activated ) + { + //kDebug(); + if( cube_painting ) + { + if( ( w->isDesktop() || w->isDock() ) && w->screen() != activeScreen && w->isOnDesktop( effects->currentDesktop() ) ) + { + windowsOnOtherScreens.append( w ); + } + if( (start || stop) && w->screen() != activeScreen && w->isOnDesktop( effects->currentDesktop() ) + && !w->isDesktop() && !w->isDock() ) + { + windowsOnOtherScreens.append( w ); + } + if( w->isOnDesktop( painting_desktop )) + { + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + if( w->x() < rect.x() ) + { + data.quads = data.quads.splitAtX( -w->x() ); + } + if( w->x() + w->width() > rect.x() + rect.width() ) + { + data.quads = data.quads.splitAtX( rect.width() - w->x() ); + } + if( w->y() < rect.y() ) + { + data.quads = data.quads.splitAtY( -w->y() ); + } + if( w->y() + w->height() > rect.y() + rect.height() ) + { + data.quads = data.quads.splitAtY( rect.height() - w->y() ); + } + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + else + { + // check for windows belonging to the previous desktop + int prev_desktop = painting_desktop -1; + if( prev_desktop == 0 ) + prev_desktop = effects->numberOfDesktops(); + if( w->isOnDesktop( prev_desktop ) ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, prev_desktop); + if( w->x()+w->width() > rect.x() + rect.width() ) + { + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + data.quads = data.quads.splitAtX( rect.width() - w->x() ); + if( w->y() < rect.y() ) + { + data.quads = data.quads.splitAtY( -w->y() ); + } + if( w->y() + w->height() > rect.y() + rect.height() ) + { + data.quads = data.quads.splitAtY( rect.height() - w->y() ); + } + data.setTransformed(); + effects->prePaintWindow( w, data, time ); + return; + } + } + // check for windows belonging to the next desktop + int next_desktop = painting_desktop +1; + if( next_desktop > effects->numberOfDesktops() ) + next_desktop = 1; + if( w->isOnDesktop( next_desktop ) ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, next_desktop); + if( w->x() < rect.x() ) + { + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + data.quads = data.quads.splitAtX( -w->x() ); + if( w->y() < rect.y() ) + { + data.quads = data.quads.splitAtY( -w->y() ); + } + if( w->y() + w->height() > rect.y() + rect.height() ) + { + data.quads = data.quads.splitAtY( rect.height() - w->y() ); + } + data.setTransformed(); + effects->prePaintWindow( w, data, time ); + return; + } + } + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + } + } + effects->prePaintWindow( w, data, time ); + } + +void CubeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + if( activated && cube_painting ) + { + //kDebug() << w->caption(); + float opacity = cubeOpacity; + if( start ) + { + opacity = 1.0 - (1.0 - opacity)*timeLine.value(); + if( reflectionPainting ) + opacity = 0.5 + ( cubeOpacity - 0.5 )*timeLine.value(); + // fade in windows belonging to different desktops + if( painting_desktop == effects->currentDesktop() && (!w->isOnDesktop( painting_desktop )) ) + opacity = timeLine.value() * cubeOpacity; + } + if( stop ) + { + opacity = 1.0 - (1.0 - opacity)*( 1.0 - timeLine.value() ); + if( reflectionPainting ) + opacity = 0.5 + ( cubeOpacity - 0.5 )*( 1.0 - timeLine.value() ); + // fade out windows belonging to different desktops + if( painting_desktop == effects->currentDesktop() && (!w->isOnDesktop( painting_desktop )) ) + opacity = cubeOpacity * (1.0 - timeLine.value()); + } + bool slideOpacity = false; + // fade in windows from different desktops in first slide step + if( slide && painting_desktop == oldDesktop && (!w->isOnDesktop( painting_desktop )) ) + { + opacity = timeLine.value(); + slideOpacity = true; + } + // fade out windows from different desktops in last slide step + if( slide && rotations.empty() && painting_desktop == effects->currentDesktop() && (!w->isOnDesktop( painting_desktop )) ) + { + opacity = 1.0 - timeLine.value(); + slideOpacity = true; + } + // check for windows belonging to the previous desktop + int prev_desktop = painting_desktop -1; + if( prev_desktop == 0 ) + prev_desktop = effects->numberOfDesktops(); + int next_desktop = painting_desktop +1; + if( next_desktop > effects->numberOfDesktops() ) + next_desktop = 1; + if( w->isOnDesktop( prev_desktop ) && ( mask & PAINT_WINDOW_TRANSFORMED ) ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, prev_desktop); + data.xTranslate = -rect.width(); + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( quad.right() > rect.width() - w->x() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + if( w->isOnDesktop( next_desktop ) && ( mask & PAINT_WINDOW_TRANSFORMED ) ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, next_desktop); + data.xTranslate = rect.width(); + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( w->x() + quad.right() <= rect.x() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + + if( start || stop ) + { + // we have to change opacity values for fade in/out of windows which are shown on front-desktop + if( prev_desktop == effects->currentDesktop() && w->x() < rect.x() ) + { + if( start ) + opacity = timeLine.value() * cubeOpacity; + if( stop ) + opacity = cubeOpacity * (1.0 - timeLine.value()); + } + if( next_desktop == effects->currentDesktop() && w->x() + w->width() > rect.x() + rect.width() ) + { + if( start ) + opacity = timeLine.value() * cubeOpacity; + if( stop ) + opacity = cubeOpacity * (1.0 - timeLine.value()); + } + } + if( !slide || (slide && !w->isDesktop()) || slideOpacity ) + data.opacity *= opacity; + + if( w->isOnDesktop(painting_desktop) && w->x() < rect.x() ) + { + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( quad.right() > -w->x() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + if( w->isOnDesktop(painting_desktop) && w->x() + w->width() > rect.x() + rect.width() ) + { + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( quad.right() <= rect.width() - w->x() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + if( w->y() < rect.y() ) + { + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( quad.bottom() > -w->y() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + if( w->y() + w->height() > rect.y() + rect.height() ) + { + WindowQuadList new_quads; + foreach( WindowQuad quad, data.quads ) + { + if( quad.bottom() <= rect.height() - w->y() ) + { + new_quads.append( quad ); + } + } + data.quads = new_quads; + } + } + effects->paintWindow( w, mask, region, data ); + } + +bool CubeEffect::borderActivated( ElectricBorder border ) + { + if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) + return false; + if( border == borderActivate && !activated ) + { + kDebug() << "border activated"; + toggle(); + return true; + } + return false; + } + +void CubeEffect::toggle() + { + if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) + return; + if( !activated ) + { + setActive( true ); + } + else + { + setActive( false ); + } + } + +void CubeEffect::grabbedKeyboardEvent( QKeyEvent* e ) + { + if( stop ) + return; + // taken from desktopgrid.cpp + if( e->type() == QEvent::KeyPress ) + { + int desktop = -1; + // switch by F<number> or just <number> + if( e->key() >= Qt::Key_F1 && e->key() <= Qt::Key_F35 ) + desktop = e->key() - Qt::Key_F1 + 1; + else if( e->key() >= Qt::Key_0 && e->key() <= Qt::Key_9 ) + desktop = e->key() == Qt::Key_0 ? 10 : e->key() - Qt::Key_0; + if( desktop != -1 ) + { + if( desktop <= effects->numberOfDesktops()) + { + // we have to rotate to chosen desktop + // and end effect when rotation finished + rotateToDesktop( desktop ); + setActive( false ); + } + return; + } + switch( e->key()) + { // wrap only on autorepeat + case Qt::Key_Left: + // rotate to previous desktop + kDebug() << "left"; + if( !rotating && !start ) + { + rotating = true; + rotationDirection = Left; + } + else + { + if( rotations.count() < effects->numberOfDesktops() ) + rotations.enqueue( Left ); + } + break; + case Qt::Key_Right: + // rotate to next desktop + kDebug() << "right"; + if( !rotating && !start ) + { + rotating = true; + rotationDirection = Right; + } + else + { + if( rotations.count() < effects->numberOfDesktops() ) + rotations.enqueue( Right ); + } + break; + case Qt::Key_Up: + kDebug() << "up"; + if( verticalPosition != Up ) + { + if( !verticalRotating ) + { + verticalRotating = true; + verticalRotationDirection = Upwards; + if( verticalPosition == Normal ) + verticalPosition = Up; + if( verticalPosition == Down ) + verticalPosition = Normal; + } + else + { + verticalRotations.enqueue( Upwards ); + } + } + else if( manualVerticalAngle < 0.0 && !verticalRotating ) + { + // rotate to up position from the manual position + verticalRotating = true; + verticalRotationDirection = Upwards; + verticalPosition = Up; + manualVerticalAngle += 90.0; + } + break; + case Qt::Key_Down: + kDebug() << "down"; + if( verticalPosition != Down ) + { + if( !verticalRotating ) + { + verticalRotating = true; + verticalRotationDirection = Downwards; + if( verticalPosition == Normal ) + verticalPosition = Down; + if( verticalPosition == Up ) + verticalPosition = Normal; + } + else + { + verticalRotations.enqueue( Downwards ); + } + } + else if( manualVerticalAngle > 0.0 && !verticalRotating ) + { + // rotate to down position from the manual position + verticalRotating = true; + verticalRotationDirection = Downwards; + verticalPosition = Down; + manualVerticalAngle -= 90.0; + } + break; + case Qt::Key_Escape: + rotateToDesktop( effects->currentDesktop() ); + setActive( false ); + return; + case Qt::Key_Enter: + case Qt::Key_Return: + case Qt::Key_Space: + setActive( false ); + return; + case Qt::Key_Plus: + zoom -= 10.0; + zoom = qMax( -zPosition, zoom ); + break; + case Qt::Key_Minus: + zoom += 10.0f; + break; + default: + break; + } + effects->addRepaintFull(); + } + } + +void CubeEffect::rotateToDesktop( int desktop ) + { + int tempFrontDesktop = frontDesktop; + if( !rotations.empty() ) + { + // all scheduled rotations will be removed as a speed up + rotations.clear(); + } + if( rotating && !desktopChangedWhileRotating ) + { + // front desktop will change during the actual rotation - this has to be considered + if( rotationDirection == Left ) + { + tempFrontDesktop++; + } + else if( rotationDirection == Right ) + { + tempFrontDesktop--; + } + if( tempFrontDesktop > effects->numberOfDesktops() ) + tempFrontDesktop = 1; + else if( tempFrontDesktop == 0 ) + tempFrontDesktop = effects->numberOfDesktops(); + } + // find the fastest rotation path from tempFrontDesktop to desktop + int rightRotations = tempFrontDesktop - desktop; + if( rightRotations < 0 ) + rightRotations += effects->numberOfDesktops(); + int leftRotations = desktop - tempFrontDesktop; + if( leftRotations < 0 ) + leftRotations += effects->numberOfDesktops(); + if( leftRotations <= rightRotations ) + { + for( int i=0; i<leftRotations; i++ ) + { + rotations.enqueue( Left ); + } + } + else + { + for( int i=0; i<rightRotations; i++ ) + { + rotations.enqueue( Right ); + } + } + if( !start && !rotating && !rotations.empty() ) + { + rotating = true; + rotationDirection = rotations.dequeue(); + } + // change timeline curve if more rotations are following + if( !rotations.empty() ) + { + currentShape = TimeLine::EaseInCurve; + timeLine.setCurveShape( currentShape ); + // change timeline duration in slide mode + if( slide ) + timeLine.setDuration( rotationDuration / (rotations.count()+1) ); + } + } + +void CubeEffect::setActive( bool active ) + { + if( active ) + { + activated = true; + activeScreen = effects->activeScreen(); + if( !slide ) + { + keyboard_grab = effects->grabKeyboard( this ); + input = effects->createInputWindow( this, 0, 0, displayWidth(), displayHeight(), + Qt::OpenHandCursor ); + frontDesktop = effects->currentDesktop(); + zoom = 0.0; + start = true; + } + effects->setActiveFullScreenEffect( this ); + kDebug() << "Cube is activated"; + verticalPosition = Normal; + verticalRotating = false; + manualAngle = 0.0; + manualVerticalAngle = 0.0; + if( reflection && !slide ) + { + // clip parts above the reflection area + double eqn[4] = {0.0, 1.0, 0.0, 0.0}; + glPushMatrix(); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && bigCube ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + glTranslatef( 0.0, rect.height(), 0.0 ); + glClipPlane( GL_CLIP_PLANE0, eqn ); + glPopMatrix(); + } + // create the needed GL lists + capList = glGenLists(1); + capListCreated = false; + + effects->addRepaintFull(); + } + else + { + schedule_close = true; + // we have to add a repaint, to start the deactivating + effects->addRepaintFull(); + } + } + +void CubeEffect::mouseChanged( const QPoint& pos, const QPoint& oldpos, Qt::MouseButtons buttons, + Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers ) + { + if( !activated ) + return; + if( tabBoxMode ) + return; + if( stop || slide ) + return; + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && (slide || bigCube ) ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + if( buttons.testFlag( Qt::LeftButton ) ) + { + bool repaint = false; + // vertical movement only if there is not a rotation + if( !verticalRotating ) + { + // display height corresponds to 180* + int deltaY = pos.y() - oldpos.y(); + float deltaVerticalDegrees = (float)deltaY/rect.height()*180.0f; + manualVerticalAngle -= deltaVerticalDegrees; + if( deltaVerticalDegrees != 0.0 ) + repaint = true; + } + // horizontal movement only if there is not a rotation + if( !rotating ) + { + // display width corresponds to sum of angles of the polyhedron + int deltaX = oldpos.x() - pos.x(); + float deltaDegrees = (float)deltaX/rect.width() * 360.0f; + manualAngle -= deltaDegrees; + if( deltaDegrees != 0.0 ) + repaint = true; + } + if( repaint ) + effects->addRepaintFull(); + } + if( !oldbuttons.testFlag( Qt::LeftButton ) && buttons.testFlag( Qt::LeftButton ) ) + { + XDefineCursor( display(), input, QCursor( Qt::ClosedHandCursor).handle() ); + } + if( oldbuttons.testFlag( Qt::LeftButton) && !buttons.testFlag( Qt::LeftButton ) ) + { + XDefineCursor( display(), input, QCursor( Qt::OpenHandCursor).handle() ); + if( closeOnMouseRelease ) + setActive( false ); + } + if( oldbuttons.testFlag( Qt::RightButton) && !buttons.testFlag( Qt::RightButton ) ) + { + // end effect on right mouse button + setActive( false ); + } + } + +void CubeEffect::desktopChanged( int old ) + { + if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) + return; + if( activated ) + return; + if( !animateDesktopChange ) + return; + slide = true; + oldDesktop = old; + setActive( true ); + frontDesktop = old; + rotateToDesktop( effects->currentDesktop() ); + setActive( false ); + } + + +void CubeEffect::tabBoxAdded( int mode ) + { + if( activated ) + return; + if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) + return; + if( useForTabBox && mode != TabBoxWindowsMode ) + { + effects->refTabBox(); + tabBoxMode = true; + setActive( true ); + rotateToDesktop( effects->currentTabBoxDesktop() ); + } + } + +void CubeEffect::tabBoxUpdated() + { + if( activated ) + rotateToDesktop( effects->currentTabBoxDesktop() ); + } + +void CubeEffect::tabBoxClosed() + { + if( activated ) + { + effects->unrefTabBox(); + tabBoxMode = false; + setActive( false ); + } + } + +} // namespace Index: effects/dimscreen.h =================================================================== --- kwin/effects/dimscreen.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/dimscreen.h (.../work/~seli/kwin11.1) (revision 880714) @@ -39,6 +39,7 @@ DimScreenEffect(); ~DimScreenEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); Index: effects/thumbnailaside_config.cpp =================================================================== --- kwin/effects/thumbnailaside_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/thumbnailaside_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -28,12 +28,9 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QWidget> #include <QGridLayout> -#include <QLabel> -#include <QComboBox> KWIN_EFFECT_CONFIG_FACTORY Index: effects/wobblywindows.h =================================================================== --- kwin/effects/wobblywindows.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/wobblywindows.h (.../work/~seli/kwin11.1) (revision 880714) @@ -39,6 +39,7 @@ WobblyWindowsEffect(); virtual ~WobblyWindowsEffect(); + virtual void reconfigure( ReconfigureFlags ); 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 ); Index: effects/boxswitch.h =================================================================== --- kwin/effects/boxswitch.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/boxswitch.h (.../work/~seli/kwin11.1) (revision 880714) @@ -42,7 +42,8 @@ public: BoxSwitchEffect(); ~BoxSwitchEffect(); - + + virtual void reconfigure( ReconfigureFlags ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); Index: effects/presentwindows_config.h =================================================================== --- kwin/effects/presentwindows_config.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/presentwindows_config.h (.../work/~seli/kwin11.1) (revision 880714) @@ -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 @@ -23,13 +24,19 @@ #include <kcmodule.h> -class QCheckBox; -class QComboBox; -class KShortcutsEditor; +#include "ui_presentwindows_config.h" +#include "presentwindows.h" namespace KWin { +class PresentWindowsEffectConfigForm : public QWidget, public Ui::PresentWindowsEffectConfigForm +{ + Q_OBJECT + public: + explicit PresentWindowsEffectConfigForm(QWidget* parent); +}; + class PresentWindowsEffectConfig : public KCModule { Q_OBJECT @@ -37,18 +44,14 @@ explicit PresentWindowsEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); ~PresentWindowsEffectConfig(); + public slots: virtual void save(); virtual void load(); virtual void defaults(); - protected: - void addItems(QComboBox* combo); - private: - QCheckBox* mDrawWindowText; - QComboBox* mActivateCombo; - QComboBox* mActivateAllCombo; - KShortcutsEditor* mShortcutEditor; + PresentWindowsEffectConfigForm* m_ui; + KActionCollection* m_actionCollection; }; } // namespace Index: effects/magnifier_config.cpp =================================================================== --- kwin/effects/magnifier_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/magnifier_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -28,12 +28,9 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QWidget> #include <QGridLayout> -#include <QLabel> -#include <QComboBox> KWIN_EFFECT_CONFIG_FACTORY Index: effects/snow.cpp =================================================================== --- kwin/effects/snow.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/snow.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -53,16 +53,12 @@ srandom( std::time( NULL ) ); lastFlakeTime = QTime::currentTime(); nextFlakeMillis = 0; - KConfigGroup conf = effects->effectConfig("Snow"); - mNumberFlakes = conf.readEntry("Number", 50); - mMinFlakeSize = conf.readEntry("MinFlakes", 10); - mMaxFlakeSize = conf.readEntry("MaxFlakes", 50); - KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = static_cast< KAction* >( actionCollection->addAction( "Snow" )); a->setText( i18n("Snow" )); a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::META + Qt::Key_F12 )); connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle())); + reconfigure( ReconfigureAll ); } SnowEffect::~SnowEffect() @@ -71,6 +67,14 @@ delete flakes; } +void SnowEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = effects->effectConfig("Snow"); + mNumberFlakes = conf.readEntry("Number", 50); + mMinFlakeSize = conf.readEntry("MinFlakes", 10); + mMaxFlakeSize = conf.readEntry("MaxFlakes", 50); + } + void SnowEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if ( active ) Index: effects/mousemark_config.cpp =================================================================== --- kwin/effects/mousemark_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/mousemark_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -28,12 +28,9 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QWidget> #include <QGridLayout> -#include <QLabel> -#include <QComboBox> KWIN_EFFECT_CONFIG_FACTORY Index: effects/videorecord_config.cpp =================================================================== --- kwin/effects/videorecord_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/videorecord_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,7 +27,6 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <KUrlRequester> #include <QLabel> #include <KGlobalSettings> Index: effects/presentwindows.cpp =================================================================== --- kwin/effects/presentwindows.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/presentwindows.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -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 @@ -42,32 +43,27 @@ PresentWindowsEffect::PresentWindowsEffect() : mShowWindowsFromAllDesktops ( false ) , mActivated( false ) - , mActiveness( 0.0 ) - , mRearranging( 1.0 ) + , mActiveness() + , mRearranging() , hasKeyboardGrab( false ) , mHighlightedWindow( NULL ) #ifdef KWIN_HAVE_OPENGL_COMPOSITING , filterTexture( NULL ) #endif + , borderActivate( ElectricNone ) + , borderActivateAll( ElectricNone ) + , mTabBoxMode( false ) { - KConfigGroup conf = effects->effectConfig("PresentWindows"); - KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = (KAction*)actionCollection->addAction( "Expose" ); - a->setText( i18n("Toggle Expose Effect" )); + a->setText( i18n("Toggle Present Windows (Current desktop)" )); a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F9)); connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleActive())); KAction* b = (KAction*)actionCollection->addAction( "ExposeAll" ); - b->setText( i18n("Toggle Expose Effect (incl. other desktops)" )); + b->setText( i18n("Toggle Present Windows (All desktops)" )); b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F10)); connect(b, SIGNAL(triggered(bool)), this, SLOT(toggleActiveAllDesktops())); - - borderActivate = (ElectricBorder)conf.readEntry("BorderActivate", (int)ElectricNone); - borderActivateAll = (ElectricBorder)conf.readEntry("BorderActivateAll", (int)ElectricTopLeft); - drawWindowCaptions = conf.readEntry("DrawWindowCaptions", true); - - effects->reserveElectricBorder( borderActivate ); - effects->reserveElectricBorder( borderActivateAll ); + reconfigure( ReconfigureAll ); } PresentWindowsEffect::~PresentWindowsEffect() @@ -77,27 +73,46 @@ discardFilterTexture(); } +void PresentWindowsEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = effects->effectConfig("PresentWindows"); + effects->unreserveElectricBorder( borderActivate ); + effects->unreserveElectricBorder( borderActivateAll ); + borderActivate = (ElectricBorder)conf.readEntry("BorderActivate", (int)ElectricNone); + borderActivateAll = (ElectricBorder)conf.readEntry("BorderActivateAll", (int)ElectricTopLeft); + effects->reserveElectricBorder( borderActivate ); + effects->reserveElectricBorder( borderActivateAll ); + layoutMode = conf.readEntry( "LayoutMode", int( LayoutNatural )); + drawWindowCaptions = conf.readEntry("DrawWindowCaptions", true); + drawWindowIcons = conf.readEntry("DrawWindowIcons", true); + tabBox = conf.readEntry("TabBox", false); + accuracy = conf.readEntry("Accuracy", 1) * 20; + fillGaps = conf.readEntry("FillGaps", true); + mActiveness.setCurveShape( TimeLine::EaseInOutCurve ); + mActiveness.setDuration( animationTime( conf, "RearrangeDuration", 250 )); + mRearranging.setCurveShape( TimeLine::EaseInOutCurve ); + mRearranging.setDuration( animationTime( conf, "RearrangeDuration", 250 )); + mRearranging.setProgress( 1.0 ); + } + void PresentWindowsEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { - // How long does it take for the effect to get it's full strength (in ms) - const double changeTime = 125; if(mActivated) { - mActiveness = qMin(1.0, mActiveness + time/changeTime); - if( mRearranging < 1 ) - mRearranging = qMin(1.0, mRearranging + time/changeTime); + mActiveness.addTime(time); + mRearranging.addTime(time); } - else if(mActiveness > 0.0) + else if(mActiveness.value() > 0.0) { - mActiveness = qMax(0.0, mActiveness - time/changeTime); - if(mActiveness <= 0.0) + mActiveness.removeTime(time); + if(mActiveness.value() <= 0.0) effectTerminated(); } // We need to mark the screen windows as transformed. Otherwise the whole // screen won't be repainted, resulting in artefacts - if( mActiveness > 0.0f ) + if( mActiveness.value() > 0.0 ) data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; effects->prePaintScreen(data, time); @@ -105,7 +120,7 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) { - if( mActiveness > 0.0f ) + if( mActiveness.value() > 0.0 ) { if( mWindowData.contains(w) ) { @@ -115,11 +130,11 @@ w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); // If it's minimized window or on another desktop and effect is not // fully active, then apply some transparency - if( mActiveness < 1.0f && (w->isMinimized() || !w->isOnCurrentDesktop() )) + if( mActiveness.value() < 1.0 && (w->isMinimized() || !w->isOnCurrentDesktop() )) data.setTranslucent(); // Change window's highlight WindowData& windata = mWindowData[w]; - const double highlightchangetime = 100; + const double highlightchangetime = animationTime( 100 ); if( w == mHighlightedWindow ) windata.highlight = qMin(1.0, windata.highlight + time / highlightchangetime); else @@ -155,11 +170,11 @@ void PresentWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { - if(mActiveness > 0.0f && mWindowData.contains(w)) + if(mActiveness.value() > 0.0 && mWindowData.contains(w)) { // Change window's position and scale const WindowData& windata = mWindowData[w]; - if( mRearranging < 1 ) // rearranging + if( mRearranging.value() < 1.0 ) // rearranging { if( windata.old_area.isEmpty()) // no old position { @@ -167,40 +182,41 @@ data.yScale = windata.scale; data.xTranslate = windata.area.left() - w->x(); data.yTranslate = windata.area.top() - w->y(); - data.opacity *= interpolate(0.0, 1.0, mRearranging); + data.opacity *= interpolate(0.0, 1.0, mRearranging.value()); } else { - data.xScale = interpolate(windata.old_scale, windata.scale, mRearranging); - data.yScale = interpolate(windata.old_scale, windata.scale, mRearranging); + data.xScale = interpolate(windata.old_scale, windata.scale, mRearranging.value()); + data.yScale = interpolate(windata.old_scale, windata.scale, mRearranging.value()); data.xTranslate = (int)interpolate(windata.old_area.left() - w->x(), - windata.area.left() - w->x(), mRearranging); + windata.area.left() - w->x(), mRearranging.value()); data.yTranslate = (int)interpolate(windata.old_area.top() - w->y(), - windata.area.top() - w->y(), mRearranging); + windata.area.top() - w->y(), mRearranging.value()); } } else { - data.xScale = interpolate(data.xScale, windata.scale, mActiveness); - data.yScale = interpolate(data.yScale, windata.scale, mActiveness); - data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->x(), mActiveness); - data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->y(), mActiveness); + data.xScale = interpolate(data.xScale, windata.scale, mActiveness.value()); + data.yScale = interpolate(data.yScale, windata.scale, mActiveness.value()); + data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->x(), mActiveness.value()); + data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->y(), mActiveness.value()); } // Darken all windows except for the one under the cursor - data.brightness *= interpolate(1.0, 0.7, mActiveness * (1.0f - windata.highlight)); + data.brightness *= interpolate(1.0, 0.7, mActiveness.value() * (1.0f - windata.highlight)); // If it's minimized window or on another desktop and effect is not // fully active, then apply some transparency - if( mActiveness < 1.0f && (w->isMinimized() || !w->isOnCurrentDesktop() )) - data.opacity *= interpolate(0.0, 1.0, mActiveness); + if( mActiveness.value() < 1.0 && (w->isMinimized() || !w->isOnCurrentDesktop() )) + data.opacity *= interpolate(0.0, 1.0, mActiveness.value()); } // Call the next effect. effects->paintWindow( w, mask, region, data ); - if(mActiveness > 0.0f && mWindowData.contains(w)) + if(mActiveness.value() > 0.0 && mWindowData.contains(w)) { const WindowData& windata = mWindowData[w]; - paintWindowIcon( w, data ); + if (drawWindowIcons) + paintWindowIcon( w, data ); if (drawWindowCaptions) { @@ -208,7 +224,7 @@ double centerx = w->x() + data.xTranslate + w->width() * data.xScale * 0.5f; double centery = w->y() + data.yTranslate + w->height() * data.yScale * 0.5f; int maxwidth = (int)(w->width() * data.xScale - 20); - double opacity = (0.7 + 0.2*windata.highlight) * data.opacity * mActiveness; + double opacity = (0.7 + 0.2*windata.highlight) * data.opacity * mActiveness.value(); QColor textcolor( 255, 255, 255, (int)(255*opacity) ); QColor bgcolor( 0, 0, 0, (int)(255*opacity) ); QFont f; @@ -222,11 +238,11 @@ void PresentWindowsEffect::postPaintScreen() { - if( mActivated && mActiveness < 1.0 ) // activating effect + if( mActivated && mActiveness.value() < 1.0 ) // activating effect effects->addRepaintFull(); - if( mActivated && mRearranging < 1.0 ) // rearranging + if( mActivated && mRearranging.value() < 1.0 ) // rearranging effects->addRepaintFull(); - if( !mActivated && mActiveness > 0.0 ) // deactivating effect + if( !mActivated && mActiveness.value() > 0.0 ) // deactivating effect effects->addRepaintFull(); foreach( const WindowData& d, mWindowData ) { @@ -282,6 +298,14 @@ setActive(false); } +void PresentWindowsEffect::windowAdded( EffectWindow* w ) + { + if( w->isSpecialWindow() || w->isUtility() ) + return; + mWindowsToPresent.append( w ); + rearrangeWindows(); + } + void PresentWindowsEffect::windowClosed( EffectWindow* w ) { if( mHighlightedWindow == w ) @@ -296,6 +320,11 @@ return; if( mActivated == active ) return; + if( mTabBoxMode && mActivated ) + { + effects->closeTabBox(); + return; + } mActivated = active; if( mActivated ) { @@ -303,32 +332,47 @@ windowFilter.clear(); mWindowsToPresent.clear(); const EffectWindowList& originalwindowlist = effects->stackingOrder(); - // Filter out special windows such as panels and taskbars - foreach( EffectWindow* window, originalwindowlist ) + if( mTabBoxMode ) { - if( window->isSpecialWindow() ) - continue; - if( window->isDeleted()) - continue; - if( !mShowWindowsFromAllDesktops && !window->isOnCurrentDesktop() ) - continue; - mWindowsToPresent.append(window); + EffectWindowList tabBoxWindows = effects->currentTabBoxWindowList(); + int selectedWindow = tabBoxWindows.indexOf( effects->currentTabBoxWindow() ); + for( int i=selectedWindow; i<tabBoxWindows.count(); i++ ) + mWindowsToPresent.append( tabBoxWindows[ i ] ); + for( int i=selectedWindow-1; i>=0; i-- ) + mWindowsToPresent.append( tabBoxWindows[ i ] ); } + else + { + // Filter out special windows such as panels and taskbars + foreach( EffectWindow* window, originalwindowlist ) + { + if( window->isSpecialWindow() || window->isUtility() ) + continue; + if( window->isDeleted()) + continue; + if( !mShowWindowsFromAllDesktops && !window->isOnCurrentDesktop() ) + continue; + mWindowsToPresent.append(window); + } + } if( mWindowsToPresent.isEmpty()) { mActivated = false; // don't activate with nothing to show return; } - mActiveness = 0; + mActiveness.setProgress(0.0); effectActivated(); rearrangeWindows(); - setHighlightedWindow( effects->activeWindow()); + if( mTabBoxMode ) + setHighlightedWindow( effects->currentTabBoxWindow() ); + else + setHighlightedWindow( effects->activeWindow() ); } else { mWindowsToPresent.clear(); - mRearranging = 1; // turn off - mActiveness = 1; // go back from arranged position + mRearranging.setProgress(1.0); // turn off + mActiveness.setProgress(1.0); // go back from arranged position discardFilterTexture(); mHighlightedWindow = NULL; windowFilter.clear(); @@ -342,7 +386,6 @@ mInput = effects->createFullScreenInputWindow( this, Qt::PointingHandCursor ); hasKeyboardGrab = effects->grabKeyboard( this ); effects->setActiveFullScreenEffect( this ); - setHighlightedWindow( effects->activeWindow()); screenGridSizes.clear(); for( int i = 0; i < effects->numScreens(); i++ ) @@ -413,47 +456,73 @@ // Initialize new entries foreach( EffectWindow* w, windowlist ) if( !mWindowData.contains( w )) - { mWindowData[ w ].highlight = 0; - } } else firstTime = true; bool rearranging = false; + int iterations = mTabBoxMode ? 1 : effects->numScreens(); // Only use one screen for window switching QVector<int> newNumOfWindows( effects->numScreens(), 0 ); QVector<GridSize> newScreenGridSizes( effects->numScreens() ); - for( int i = 0; i < effects->numScreens(); i++ ) + for( int i = 0; i < iterations; i++ ) { + int screen; + EffectWindowList screenList; + if( mTabBoxMode ) + { + screen = effects->activeScreen(); + screenList = windowlist; + } + else + { + screen = i; + screenList = windowlists[i]; + } + newScreenGridSizes.append( GridSize() ); // Do not rearrange if filtering only removed windows, so that the remaining ones don't possibly - // jump into the freed slots if they'd be a better match. + // jump into the freed slots if they'd be a better match. This only works with the regular grid // This can probably still lead to such things when removing the filter again, but that'd need // more complex remembering of window positions. - newNumOfWindows[i] = windowlists[i].count(); - newScreenGridSizes[i].columns = int( ceil( sqrt( (double)windowlists[i].count()))); - newScreenGridSizes[i].rows = int( ceil( windowlists[i].count() / double( newScreenGridSizes[i].columns ))); - if( newNumOfWindows[i] && ( firstTime || newNumOfWindows[i] > numOfWindows[i] || - ( newNumOfWindows[i] < numOfWindows[i] && ( newScreenGridSizes[i].rows != screenGridSizes[i].rows || - newScreenGridSizes[i].columns != screenGridSizes[i].columns )))) + bool doRearrange = false; + if( layoutMode != LayoutRegularGrid ) + doRearrange = true; + else { + newNumOfWindows[screen] = screenList.count(); + newScreenGridSizes[screen].columns = int( ceil( sqrt( (double)screenList.count()))); + newScreenGridSizes[screen].rows = int( ceil( screenList.count() / double( newScreenGridSizes[screen].columns ))); + if( newNumOfWindows[screen] && ( firstTime || newNumOfWindows[screen] > numOfWindows[screen] || + ( newNumOfWindows[screen] < numOfWindows[screen] && ( newScreenGridSizes[screen].rows != screenGridSizes[screen].rows || + newScreenGridSizes[screen].columns != screenGridSizes[screen].columns )))) + doRearrange = true; + } + if( doRearrange ) + { if( !firstTime && !rearranging ) { rearranging = true; prepareToRearrange(); } + // No point calculating if there is no windows + if( !screenList.size() ) + continue; // Calculate new positions and scales for windows -// calculateWindowTransformationsDumb( windowlist ); // Haven't added screen support to these yet -// calculateWindowTransformationsKompose( windowlist ); - calculateWindowTransformationsClosest( windowlists[i], i ); + if( layoutMode == LayoutRegularGrid || mTabBoxMode ) // Force the grid for window switching + calculateWindowTransformationsClosest( screenList, screen ); + else if( layoutMode == LayoutFlexibleGrid ) + calculateWindowTransformationsKompose( screenList, screen ); + else + calculateWindowTransformationsNatural( screenList, screen ); } } numOfWindows = newNumOfWindows; screenGridSizes = newScreenGridSizes; - if( !mWindowData.isEmpty() && mHighlightedWindow == NULL ) + if( !mWindowData.isEmpty() && mHighlightedWindow == NULL && !mTabBoxMode ) // Tab box takes care of this itself setHighlightedWindow( findFirstWindow()); // Schedule entire desktop to be repainted @@ -471,46 +540,9 @@ (*it).old_area = (*it).area; (*it).old_scale = (*it).scale; } - mRearranging = 0; // start animation again + mRearranging.setProgress(0.0); // start animation again } -void PresentWindowsEffect::calculateWindowTransformationsDumb(EffectWindowList windowlist) - { - // Calculate number of rows/cols - int rows = windowlist.count() / 4 + 1; - int cols = windowlist.count() / rows + windowlist.count() % rows; - // Get rect which we can use on current desktop. This excludes e.g. panels - QRect placementRect = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop()); - // Size of one cell - int cellwidth = placementRect.width() / cols; - int cellheight = placementRect.height() / rows; - kDebug(1212) << "Got " << windowlist.count() << " clients, using " << rows << "x" << cols << " grid"; - - // Calculate position and scale factor for each window - int i = 0; - foreach( EffectWindow* window, windowlist ) - { - - // Row/Col of this window - int r = i / cols; - int c = i % cols; - mWindowData[window].slot = i; - mWindowData[window].x = c; - mWindowData[window].y = r; - mWindowData[window].highlight = 0.0f; - mWindowData[window].scale = qMin(cellwidth / (double)window->width(), cellheight / (double)window->height()); - mWindowData[window].area.setLeft(placementRect.left() + cellwidth * c); - mWindowData[window].area.setTop(placementRect.top() + cellheight * r); - mWindowData[window].area.setWidth((int)(window->width() * mWindowData[window].scale)); - mWindowData[window].area.setHeight((int)(window->height() * mWindowData[window].scale)); - - kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" << - mWindowData[window].area.left() << "; " << mWindowData[window].area.right() << - "), scale: " << mWindowData[window].scale << endl; - i++; - } - } - double PresentWindowsEffect::windowAspectRatio(EffectWindow* c) { return c->width() / (double)c->height(); @@ -526,10 +558,10 @@ return (int)((w / (double)c->width()) * c->height()); } -void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist) +void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist, int screen) { - // Get rect which we can use on current desktop. This excludes e.g. panels - QRect availRect = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop()); + QRect availRect = effects->clientArea( ScreenArea, screen, effects->currentDesktop()); + qSort( windowlist ); // The location of the windows should not depend on the stacking order // Following code is taken from Kompose 0.5.4, src/komposelayout.cpp @@ -547,7 +579,7 @@ rows = (int)ceil( sqrt((double)windowlist.count()) ); columns = (int)ceil( (double)windowlist.count() / (double)rows ); } - kDebug(1212) << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients"; + //kDebug(1212) << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients"; // Calculate width & height int w = (availRect.width() - (columns+1) * spacing ) / columns; @@ -616,6 +648,12 @@ widgeth = usableH; widgetw = (int)widthForHeight; } + // Don't upscale large-ish windows + if( widgetw > window->width() && ( window->width() > 300 || window->height() > 300 )) + { + widgetw = window->width(); + widgeth = window->height(); + } } // Set the Widget's size @@ -659,9 +697,9 @@ mWindowData[window].scale = geom.width() / (double)window->width(); mWindowData[window].highlight = 0.0f; - kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" << - mWindowData[window].area.left() << "; " << mWindowData[window].area.right() << - "), scale: " << mWindowData[window].scale << endl; + //kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" << + // mWindowData[window].area.left() << "; " << mWindowData[window].area.right() << + // "), scale: " << mWindowData[window].scale << endl; } if ( maxRowHeights[i]-h > 0 ) topOffset += maxRowHeights[i]-h; @@ -670,7 +708,7 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowList windowlist, int screen) { - QRect area = effects->clientArea( PlacementArea, screen, effects->currentDesktop()); + QRect area = effects->clientArea( ScreenArea, screen, effects->currentDesktop()); int columns = int( ceil( sqrt( (double)windowlist.count()))); int rows = int( ceil( windowlist.count() / double( columns ))); foreach( EffectWindow* w, windowlist ) @@ -717,7 +755,6 @@ if( scale > 2.0 || ( scale > 1.0 && ( w->width() > 300 || w->height() > 300 ))) { scale = ( w->width() > 300 || w->height() > 300 ) ? 1.0 : 2.0; - QPoint center = geom.center(); geom = QRect( geom.center().x() - int( w->width() * scale ) / 2, geom.center().y() - int( w->height() * scale ) / 2, scale * w->width(), scale * w->height() ); } @@ -737,43 +774,75 @@ } int slotwidth = area.width() / columns; int slotheight = area.height() / rows; - foreach( EffectWindow* w, windowlist ) + if( mTabBoxMode ) { - WindowData *windowData = &mWindowData[ w ]; - if( windowData->slot != -1 ) - continue; // it already has a slot - QPoint pos = w->geometry().center(); - if( pos.x() < area.left()) - pos.setX( area.left()); - if( pos.x() > area.right()) - pos.setX( area.right()); - if( pos.y() < area.top()) - pos.setY( area.top()); - if( pos.y() > area.bottom()) - pos.setY( area.bottom()); - int distance = INT_MAX; - for( int x = 0; - x < columns; - ++x ) - for( int y = 0; - y < rows; - ++y ) - { - int slot = x + y * columns; - if( taken[ slot ] ) - continue; - int xdiff = pos.x() - ( area.x() + slotwidth * x + slotwidth / 2 ); // slotwidth/2 for center - int ydiff = pos.y() - ( area.y() + slotheight * y + slotheight / 2 ); - int dist = int( sqrt( (double)(xdiff * xdiff + ydiff * ydiff) )); - if( dist < distance ) + for( int i=0; i<windowlist.count(); i++ ) + { + EffectWindow *w = windowlist[ i ]; + WindowData *windowData = &mWindowData[ w ]; + if( windowData->slot != -1 ) + continue; // it already has a slot + int x = i%columns; + int y = i/columns; + QPoint pos = w->geometry().center(); + if( pos.x() < area.left()) + pos.setX( area.left()); + if( pos.x() > area.right()) + pos.setX( area.right()); + if( pos.y() < area.top()) + pos.setY( area.top()); + if( pos.y() > area.bottom()) + pos.setY( area.bottom()); + //int distance = INT_MAX; + int xdiff = pos.x() - ( area.x() + slotwidth * x + slotwidth / 2 ); // slotwidth/2 for center + int ydiff = pos.y() - ( area.y() + slotheight * y + slotheight / 2 ); + int dist = int( sqrt( (double)(xdiff * xdiff + ydiff * ydiff) )); + windowData->slot = i; + windowData->x = x; + windowData->y = y; + windowData->slot_distance = dist; + } + } + else + { + foreach( EffectWindow* w, windowlist ) + { + WindowData *windowData = &mWindowData[ w ]; + if( windowData->slot != -1 ) + continue; // it already has a slot + QPoint pos = w->geometry().center(); + if( pos.x() < area.left()) + pos.setX( area.left()); + if( pos.x() > area.right()) + pos.setX( area.right()); + if( pos.y() < area.top()) + pos.setY( area.top()); + if( pos.y() > area.bottom()) + pos.setY( area.bottom()); + int distance = INT_MAX; + for( int x = 0; + x < columns; + ++x ) + for( int y = 0; + y < rows; + ++y ) { - distance = dist; - windowData->slot = slot; - windowData->x = x; - windowData->y = y; - windowData->slot_distance = distance; + int slot = x + y * columns; + if( taken[ slot ] ) + continue; + int xdiff = pos.x() - ( area.x() + slotwidth * x + slotwidth / 2 ); // slotwidth/2 for center + int ydiff = pos.y() - ( area.y() + slotheight * y + slotheight / 2 ); + int dist = int( sqrt( (double)(xdiff * xdiff + ydiff * ydiff) )); + if( dist < distance ) + { + distance = dist; + windowData->slot = slot; + windowData->x = x; + windowData->y = y; + windowData->slot_distance = distance; + } } - } + } } } @@ -794,6 +863,252 @@ } } +void PresentWindowsEffect::calculateWindowTransformationsNatural(EffectWindowList windowlist, int screen) + { + // As we are using pseudo-random movement (See "slot") we need to make sure the list + // is always sorted the same way no matter which window is currently active. + qSort( windowlist ); + + QRect area = effects->clientArea( ScreenArea, screen, effects->currentDesktop()); + QRect bounds = area;//mWindowData[0].area; + int direction = 0; + foreach( EffectWindow* w, windowlist ) + { + bounds = bounds.united( w->geometry() ); + mWindowData[ w ].area = w->geometry(); + mWindowData[ w ].scale = 1.0; + // Reuse the unused "slot" as a preferred direction attribute. This is used when the window + // is on the edge of the screen to try to use as much screen real estate as possible. + mWindowData[ w ].slot = direction; + direction++; + if( direction == 4 ) + direction = 0; + } + + // Iterate over all windows, if two overlap push them apart _slightly_ as we try to + // brute-force the most optimal positions over many iterations. + bool overlap; + do + { + overlap = false; + foreach( EffectWindow* w, windowlist ) + { + foreach( EffectWindow* e, windowlist ) + { + if( w != e && mWindowData[ w ].area.adjusted( -5, -5, 5, 5 ).intersects( + mWindowData[ e ].area.adjusted( -5, -5, 5, 5 ))) + { + overlap = true; + + // Determine pushing direction + QPoint diff( mWindowData[ e ].area.center() - mWindowData[ w ].area.center() ); + // Prevent dividing by zero and non-movement + if( diff.x() == 0 && diff.y() == 0 ) + diff.setX( 1 ); + // Try to keep screen aspect ratio + //if( bounds.height() / bounds.width() > area.height() / area.width() ) + // diff.setY( diff.y() / 2 ); + //else + // diff.setX( diff.x() / 2 ); + // Approximate a vector of between 10px and 20px in magnitude in the same direction + diff *= accuracy / double( diff.manhattanLength() ); + // Move both windows apart + mWindowData[ w ].area.translate( -diff ); + mWindowData[ e ].area.translate( diff ); + + // Try to keep the bounding rect the same aspect as the screen so that more + // screen real estate is utilised. We do this by splitting the screen into nine + // equal sections, if the window center is in any of the corner sections pull the + // window towards the outer corner. If it is in any of the other edge sections + // alternate between each corner on that edge. We don't want to determine it + // randomly as it will not produce consistant locations when using the filter. + // Only move one window so we don't cause large amounts of unnecessary zooming + // in some situations. We need to do this even when expanding later just in case + // all windows are the same size. + // (We are using an old bounding rect for this, hopefully it doesn't matter) + int xSection = ( mWindowData[ w ].area.x() - bounds.x() ) / ( bounds.width() / 3 ); + int ySection = ( mWindowData[ w ].area.y() - bounds.y() ) / ( bounds.height() / 3 ); + diff = QPoint( 0, 0 ); + if( xSection != 1 || ySection != 1 ) // Remove this if you want the center to pull as well + { + if( xSection == 1 ) + xSection = ( mWindowData[ w ].slot / 2 ? 2 : 0 ); + if( ySection == 1 ) + ySection = ( mWindowData[ w ].slot % 2 ? 2 : 0 ); + } + if( xSection == 0 && ySection == 0 ) + diff = QPoint( bounds.topLeft() - mWindowData[ w ].area.center() ); + if( xSection == 2 && ySection == 0 ) + diff = QPoint( bounds.topRight() - mWindowData[ w ].area.center() ); + if( xSection == 2 && ySection == 2 ) + diff = QPoint( bounds.bottomRight() - mWindowData[ w ].area.center() ); + if( xSection == 0 && ySection == 2 ) + diff = QPoint( bounds.bottomLeft() - mWindowData[ w ].area.center() ); + if( diff.x() != 0 || diff.y() != 0 ) + { + diff *= accuracy / double( diff.manhattanLength() ); + mWindowData[ w ].area.translate( diff ); + } + + // Update bounding rect + bounds = bounds.united( mWindowData[ w ].area ); + bounds = bounds.united( mWindowData[ e ].area ); + } + } + } + } while( overlap ); + + // Work out scaling by getting the most top-left and most bottom-right window coords. + // The 20's and 10's are so that the windows don't touch the edge of the screen. + double scale; + if( bounds == area ) + scale = 1.0; // Don't add borders to the screen + else if( area.width() / double( bounds.width() ) < area.height() / double( bounds.height() )) + scale = ( area.width() - 20 ) / double( bounds.width() ); + else + scale = ( area.height() - 20 ) / double( bounds.height() ); + // Make bounding rect fill the screen size for later steps + bounds = QRect( + bounds.x() - ( area.width() - 20 - bounds.width() * scale ) / 2 - 10 / scale, + bounds.y() - ( area.height() - 20 - bounds.height() * scale ) / 2 - 10 / scale, + area.width() / scale, + area.height() / scale + ); + + // Move all windows back onto the screen and set their scale + foreach( EffectWindow* w, windowlist ) + { + mWindowData[ w ].scale = scale; + mWindowData[ w ].area = QRect( + ( mWindowData[ w ].area.x() - bounds.x() ) * scale + area.x(), + ( mWindowData[ w ].area.y() - bounds.y() ) * scale + area.y(), + mWindowData[ w ].area.width() * scale, + mWindowData[ w ].area.height() * scale + ); + } + + // Try to fill the gaps by enlarging windows if they have the space + if( fillGaps ) + { + // Don't expand onto or over the border + QRegion borderRegion( area.adjusted( -200, -200, 200, 200 )); + borderRegion ^= area.adjusted( 10 / scale, 10 / scale, -10 / scale, -10 / scale ); + + bool moved; + do + { + moved = false; + foreach( EffectWindow* w, windowlist ) + { + QRect oldRect; + // This may cause some slight distortion if the windows are enlarged a large amount + int widthDiff = accuracy; + int heightDiff = windowHeightForWidth( w, mWindowData[ w ].area.width() + widthDiff ) - mWindowData[ w ].area.height(); + int xDiff = widthDiff / 2; // Also move a bit in the direction of the enlarge, allows the + int yDiff = heightDiff / 2; // center windows to be enlarged if there is gaps on the side. + + // Attempt enlarging to the top-right + oldRect = mWindowData[ w ].area; + mWindowData[ w ].area = QRect( + mWindowData[ w ].area.x() + xDiff, + mWindowData[ w ].area.y() - yDiff - heightDiff, + mWindowData[ w ].area.width() + widthDiff, + mWindowData[ w ].area.height() + heightDiff + ); + if( isOverlappingAny( w, windowlist, borderRegion )) + mWindowData[ w ].area = oldRect; + else + { + mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() ); + moved = true; + } + + // Attempt enlarging to the bottom-right + oldRect = mWindowData[ w ].area; + mWindowData[ w ].area = QRect( + mWindowData[ w ].area.x() + xDiff, + mWindowData[ w ].area.y() + yDiff, + mWindowData[ w ].area.width() + widthDiff, + mWindowData[ w ].area.height() + heightDiff + ); + if( isOverlappingAny( w, windowlist, borderRegion )) + mWindowData[ w ].area = oldRect; + else + { + mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() ); + moved = true; + } + + // Attempt enlarging to the bottom-left + oldRect = mWindowData[ w ].area; + mWindowData[ w ].area = QRect( + mWindowData[ w ].area.x() - xDiff - widthDiff, + mWindowData[ w ].area.y() + yDiff, + mWindowData[ w ].area.width() + widthDiff, + mWindowData[ w ].area.height() + heightDiff + ); + if( isOverlappingAny( w, windowlist, borderRegion )) + mWindowData[ w ].area = oldRect; + else + { + mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() ); + moved = true; + } + + // Attempt enlarging to the top-left + oldRect = mWindowData[ w ].area; + mWindowData[ w ].area = QRect( + mWindowData[ w ].area.x() - xDiff - widthDiff, + mWindowData[ w ].area.y() - yDiff - heightDiff, + mWindowData[ w ].area.width() + widthDiff, + mWindowData[ w ].area.height() + heightDiff + ); + if( isOverlappingAny( w, windowlist, borderRegion )) + mWindowData[ w ].area = oldRect; + else + { + mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() ); + moved = true; + } + } + } while( moved ); + + // The expanding code above can actually enlarge windows over 1.0/2.0 scale, we don't like this + // We can't add this to the loop above as it would cause a never-ending loop so we have to make + // do with the less-than-optimal space usage with using this method. + foreach( EffectWindow* w, windowlist ) + { + if( mWindowData[ w ].scale > 2.0 || + ( mWindowData[ w ].scale > 1.0 && ( w->width() > 300 || w->height() > 300 ))) + { + mWindowData[ w ].scale = ( w->width() > 300 || w->height() > 300 ) ? 1.0 : 2.0; + mWindowData[ w ].area = QRect( + mWindowData[ w ].area.center().x() - int( w->width() * mWindowData[ w ].scale ) / 2, + mWindowData[ w ].area.center().y() - int( w->height() * mWindowData[ w ].scale ) / 2, + w->width() * mWindowData[ w ].scale, + w->height() * mWindowData[ w ].scale + ); + } + } + } + } + +bool PresentWindowsEffect::isOverlappingAny( EffectWindow* w, const EffectWindowList& windowlist, const QRegion& border ) + { + if( border.intersects( mWindowData[ w ].area )) + return true; + // Is there a better way to do this? + foreach( EffectWindow* e, windowlist ) + { + if( w == e ) + continue; + if( mWindowData[ w ].area.adjusted( -5, -5, 5, 5 ).intersects( + mWindowData[ e ].area.adjusted( -5, -5, 5, 5 ))) + return true; + } + return false; + } + bool PresentWindowsEffect::borderActivated( ElectricBorder border ) { if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) @@ -885,11 +1200,147 @@ return; effects->addRepaintFull(); // everything is transformed anyway mHighlightedWindow = w; + if( mTabBoxMode ) + effects->setTabBoxWindow( w ); } // returns a window which is to relative position <xdiff,ydiff> from the given window EffectWindow* PresentWindowsEffect::relativeWindow( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const { + // Using the grid to determine the window only works on grid layouts and only have one screen. + // On multi-screen setups the grid coords are reused on each screen and each screen may also + // have a different grid size. + if( layoutMode != LayoutNatural && effects->numScreens() < 2 ) + return relativeWindowGrid( w, xdiff, ydiff, wrap ); + + // Attempt to find the window from its rect instead + EffectWindow* next; + QRect area = effects->clientArea( FullArea, 0, effects->currentDesktop() ); + QRect detectRect; + + // Detect across the width of the desktop + if( xdiff != 0 ) + { + if( xdiff > 0 ) + { // Detect right + for( int i = 0; i < xdiff; i++ ) + { + detectRect = QRect( 0, mWindowData[ w ].area.y(), area.width(), mWindowData[ w ].area.height() ); + next = NULL; + foreach( EffectWindow* e, mWindowsToPresent ) + { + if( mWindowData[ e ].area.intersects( detectRect ) && + mWindowData[ e ].area.x() > mWindowData[ w ].area.x() ) + { + if( next == NULL ) + next = e; + else if( mWindowData[ e ].area.x() < mWindowData[ next ].area.x() ) + next = e; + } + } + if( next == NULL ) + { + if( wrap ) // We are at the right-most window, now get the left-most one to wrap + return relativeWindow( w, -1000, 0, false ); + break; // No more windows to the right + } + w = next; + } + return w; + } + else + { // Detect left + for( int i = 0; i < -xdiff; i++ ) + { + detectRect = QRect( 0, mWindowData[ w ].area.y(), area.width(), mWindowData[ w ].area.height() ); + next = NULL; + foreach( EffectWindow* e, mWindowsToPresent ) + { + if( mWindowData[ e ].area.intersects( detectRect ) && + mWindowData[ e ].area.x() + mWindowData[ e ].area.width() < mWindowData[ w ].area.x() + mWindowData[ w ].area.width() ) + { + if( next == NULL ) + next = e; + else if( mWindowData[ e ].area.x() + mWindowData[ e ].area.width() > mWindowData[ next ].area.x() + mWindowData[ next ].area.width() ) + next = e; + } + } + if( next == NULL ) + { + if( wrap ) // We are at the left-most window, now get the right-most one to wrap + return relativeWindow( w, 1000, 0, false ); + break; // No more windows to the left + } + w = next; + } + return w; + } + } + + // Detect across the height of the desktop + if( ydiff != 0 ) + { + if( ydiff > 0 ) + { // Detect down + for( int i = 0; i < ydiff; i++ ) + { + detectRect = QRect( mWindowData[ w ].area.x(), 0, mWindowData[ w ].area.width(), area.height() ); + next = NULL; + foreach( EffectWindow* e, mWindowsToPresent ) + { + if( mWindowData[ e ].area.intersects( detectRect ) && + mWindowData[ e ].area.y() > mWindowData[ w ].area.y() ) + { + if( next == NULL ) + next = e; + else if( mWindowData[ e ].area.y() < mWindowData[ next ].area.y() ) + next = e; + } + } + if( next == NULL ) + { + if( wrap ) // We are at the bottom-most window, now get the top-most one to wrap + return relativeWindow( w, 0, -1000, false ); + break; // No more windows to the bottom + } + w = next; + } + return w; + } + else + { // Detect up + for( int i = 0; i < -ydiff; i++ ) + { + detectRect = QRect( mWindowData[ w ].area.x(), 0, mWindowData[ w ].area.width(), area.height() ); + next = NULL; + foreach( EffectWindow* e, mWindowsToPresent ) + { + if( mWindowData[ e ].area.intersects( detectRect ) && + mWindowData[ e ].area.y() + mWindowData[ e ].area.height() < mWindowData[ w ].area.y() + mWindowData[ w ].area.height() ) + { + if( next == NULL ) + next = e; + else if( mWindowData[ e ].area.y() + mWindowData[ e ].area.height() > mWindowData[ next ].area.y() + mWindowData[ next ].area.height() ) + next = e; + } + } + if( next == NULL ) + { + if( wrap ) // We are at the top-most window, now get the bottom-most one to wrap + return relativeWindow( w, 0, 1000, false ); + break; // No more windows to the top + } + w = next; + } + return w; + } + } + + abort(); // Should never get here + } + +EffectWindow* PresentWindowsEffect::relativeWindowGrid( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const + { if( mWindowData.count() == 0 ) return NULL; if( w == NULL ) @@ -986,11 +1437,26 @@ // returns the window that is the most to the topleft, if any EffectWindow* PresentWindowsEffect::findFirstWindow() const { + if( layoutMode == LayoutNatural || effects->numScreens() > 1 ) + { + EffectWindow* topLeft = NULL; + foreach( EffectWindow* w, mWindowsToPresent ) + { + if( topLeft == NULL ) + topLeft = w; + else if( w->x() < topLeft->x() || w->y() < topLeft->y() ) + topLeft = w; + } + return topLeft; + } + + // The following only works on grid layouts on a single screen + int minslot = INT_MAX; EffectWindow* ret = NULL; for( DataHash::ConstIterator it = mWindowData.begin(); - it != mWindowData.end(); - ++it ) + it != mWindowData.end(); + ++it ) { if( (*it).slot < minslot ) { @@ -1086,27 +1552,13 @@ glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // Render some background - glColor4f( 0, 0, 0, 0.5 * mActiveness ); + glColor4f( 0, 0, 0, 0.5 * mActiveness.value() ); renderRoundBox( QRect( x-3, y-3, width+6, height+6 ), 3 ); // Render the icon - glColor4f( 1, 1, 1, 1 * mActiveness ); + glColor4f( 1, 1, 1, 1 * mActiveness.value() ); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); data.iconTexture->bind(); - const float verts[ 4 * 2 ] = - { - x, y, - x, y + height, - x + width, y + height, - x + width, y - }; - const float texcoords[ 4 * 2 ] = - { - 0, 1, - 0, 0, - 1, 0, - 1, 1 - }; - renderGLGeometry( 4, verts, texcoords ); + data.iconTexture->render( infiniteRegion(), QRect( x, y, width, height )); data.iconTexture->unbind(); glPopAttrib(); } @@ -1123,5 +1575,38 @@ #endif } +void PresentWindowsEffect::tabBoxAdded( int mode ) + { + if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this ) + return; + if( mActivated ) + return; + if( !tabBox ) + return; + if( mode == TabBoxWindowsMode && effects->currentTabBoxWindowList().count() > 0 ) + { + mTabBoxMode = true; + setActive( true ); + if( mActivated ) + effects->refTabBox(); + } + } + +void PresentWindowsEffect::tabBoxClosed() + { + if( mActivated ) + { + mTabBoxMode = false; + effects->unrefTabBox(); + setActive( false ); + } + } + +void PresentWindowsEffect::tabBoxUpdated() + { + if( mActivated ) + setHighlightedWindow( effects->currentTabBoxWindow() ); + } + } // namespace #include "presentwindows.moc" Index: effects/invert_config.cpp =================================================================== --- kwin/effects/invert_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/invert_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,7 +27,6 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QVBoxLayout> #ifndef KDE_USE_FINAL Index: effects/coverswitch.cpp =================================================================== --- kwin/effects/coverswitch.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/coverswitch.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -21,7 +21,6 @@ #include <kwinconfig.h> #include <QFont> -#include <QBitmap> #include <klocale.h> #include <kapplication.h> #include <kcolorscheme.h> @@ -52,8 +51,17 @@ , startRequested( false ) , twinview( false ) { + reconfigure( ReconfigureAll ); + } + +CoverSwitchEffect::~CoverSwitchEffect() + { + } + +void CoverSwitchEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig( "CoverSwitch" ); - animationDuration = conf.readEntry( "Duration", 200 ); + animationDuration = animationTime( conf, "Duration", 200 ); animateSwitch = conf.readEntry( "AnimateSwitch", true ); animateStart = conf.readEntry( "AnimateStart", true ); animateStop = conf.readEntry( "AnimateStop", true ); @@ -62,10 +70,6 @@ timeLine.setDuration( animationDuration ); } -CoverSwitchEffect::~CoverSwitchEffect() - { - } - void CoverSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if( mActivated || stop || stopRequested ) Index: effects/diminactive.h =================================================================== --- kwin/effects/diminactive.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/diminactive.h (.../work/~seli/kwin11.1) (revision 880714) @@ -34,6 +34,7 @@ { public: DimInactiveEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void windowActivated( EffectWindow* c ); private: Index: effects/cube.desktop =================================================================== --- kwin/effects/cube.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,52 @@ +[Desktop Entry] +Name=Desktop Cube +Name[et]=Töölauakuubik +Name[ga]=Ciúb Deisce +Name[gl]=Cubo do escritorio +Name[gu]=ડેસ્કટોપ ટ્યુબ +Name[ja]=デスクトップキューブ +Name[km]=គូបផ្ទៃតុ +Name[nds]=Wörpel-Schriefdisch +Name[nn]=Skrivebordskube +Name[pt]=Cubo de Ecrãs +Name[pt_BR]=Cubo de Ecrãs +Name[sl]=Kocka z namizji +Name[sr]=Коцка површи +Name[sr@latin]=Kocka površi +Name[sv]=Skrivbordskub +Name[te]=డెస్క్ టాప్ క్యూబ్ +Name[tr]=Masaüstü Küpü +Name[uk]=Куб стільниць +Name[zh_TW]=桌面立方體 +Icon=preferences-system-windows-effect-cube +Comment=Map virtual desktops on a cube +Comment[et]=Virtuaalsete töölaudade asetamine kuubikule +Comment[gl]=Mostra os escritorios virtuais nun cubo +Comment[gu]=વર્ચ્યુઅલ ડેસ્કટોપને ક્યુબ સાથે જોડો +Comment[ja]=仮想デスクトップをキューブの側面に位置付けます +Comment[km]=ផ្ទៃតុនិម្មិតផែនទីនៅលើគូប +Comment[nds]=Schriefdischen op Wörpelflagen afbillen +Comment[nn]=Virtuelle skrivebord viste på ein kube +Comment[pt]=Mapear os ecrãs virtuais sobre um cubo +Comment[pt_BR]=Mapear os ecrãs virtuais sobre um cubo +Comment[sl]=Navidezna namizja preslika na kocko +Comment[sr]=Слика виртуелне површи на коцку +Comment[sr@latin]=Slika virtuelne površi na kocku +Comment[sv]=Avbilda virtuella skrivbord på en kub +Comment[te]=క్యూబ్పైన వర్చ్యువల్ డెస్క్ టాప్స్ ను మాప్చేయుము +Comment[tr]=Sanal masaüstlerini bir küp olarak göster +Comment[uk]=Призначити віртуальні стільниці до сторін куба +Comment[zh_TW]=將虛擬桌面映射到一立方體 + +Type=Service +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Martin Gräßlin +X-KDE-PluginInfo-Email=ubuntu@martin-graesslin.com +X-KDE-PluginInfo-Name=kwin4_effect_cube +X-KDE-PluginInfo-Version=0.1.0 +X-KDE-PluginInfo-Category=Window Management +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +X-KDE-Library=kwin4_effect_builtins +X-KDE-Ordering=50 Index: effects/zoom_config.cpp =================================================================== --- kwin/effects/zoom_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/zoom_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,7 +27,6 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QVBoxLayout> #ifndef KDE_USE_FINAL Index: effects/scalein.cpp =================================================================== --- kwin/effects/scalein.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/scalein.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -62,7 +62,7 @@ bool ScaleInEffect::isScaleWindow( EffectWindow* w ) { // TODO: isSpecialWindow is rather generic, maybe tell windowtypes separately? - if ( w->isPopupMenu() || w->isSpecialWindow() ) + if ( w->isPopupMenu() || w->isSpecialWindow() || w->isUtility() ) return false; return true; } @@ -78,6 +78,7 @@ { if( c->isOnCurrentDesktop()) { + mTimeLineWindows[ c ].setDuration( animationTime( 250 )); mTimeLineWindows[ c ].setProgress( 0.0 ); c->addRepaintFull(); } Index: effects/cube.h =================================================================== --- kwin/effects/cube.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,129 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_CUBE_H +#define KWIN_CUBE_H + +#include <kwineffects.h> +#include <kwinglutils.h> +#include <QObject> +#include <QQueue> + +namespace KWin +{ + +class CubeEffect + : public QObject, public Effect + { + Q_OBJECT + public: + CubeEffect(); + ~CubeEffect(); + virtual void reconfigure( ReconfigureFlags ); + virtual void prePaintScreen( ScreenPrePaintData& data, int time ); + virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); + virtual void postPaintScreen(); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual bool borderActivated( ElectricBorder border ); + virtual void grabbedKeyboardEvent( QKeyEvent* e ); + virtual void mouseChanged( const QPoint& pos, const QPoint& oldpos, Qt::MouseButtons buttons, + Qt::MouseButtons oldbuttons, Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers ); + virtual void desktopChanged( int old ); + virtual void tabBoxAdded( int mode ); + virtual void tabBoxUpdated(); + virtual void tabBoxClosed(); + protected slots: + void toggle(); + protected: + enum RotationDirection + { + Left, + Right, + Upwards, + Downwards + }; + enum VerticalRotationPosition + { + Up, + Normal, + Down + }; + virtual void paintScene( int mask, QRegion region, ScreenPaintData& data ); + virtual void paintCap( float z, float zTexture ); + virtual void paintCapStep( float z, float zTexture, bool texture ); + void loadConfig( QString config ); + void rotateToDesktop( int desktop ); + void setActive( bool active ); + bool activated; + bool cube_painting; + bool keyboard_grab; + bool schedule_close; + ElectricBorder borderActivate; + int painting_desktop; + Window input; + int frontDesktop; + float cubeOpacity; + bool displayDesktopName; + bool reflection; + bool rotating; + bool verticalRotating; + bool desktopChangedWhileRotating; + bool paintCaps; + TimeLine timeLine; + TimeLine verticalTimeLine; + RotationDirection rotationDirection; + RotationDirection verticalRotationDirection; + VerticalRotationPosition verticalPosition; + QQueue<RotationDirection> rotations; + QQueue<RotationDirection> verticalRotations; + QColor backgroundColor; + QColor capColor; + GLTexture* wallpaper; + bool texturedCaps; + GLTexture* capTexture; + float manualAngle; + float manualVerticalAngle; + TimeLine::CurveShape currentShape; + bool start; + bool stop; + bool reflectionPainting; + bool slide; + int oldDesktop; + int rotationDuration; + QList<EffectWindow*> windowsOnOtherScreens; + int activeScreen; + bool animateDesktopChange; + bool bigCube; + bool bottomCap; + bool closeOnMouseRelease; + float zoom; + float zPosition; + bool useForTabBox; + bool tabBoxMode; + + // GL lists + bool capListCreated; + GLuint capList; + }; + +} // namespace + +#endif Index: effects/maketransparent_config.cpp =================================================================== --- kwin/effects/maketransparent_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/maketransparent_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,8 +27,6 @@ #include <kconfiggroup.h> #include <QGridLayout> -#include <QLabel> -#include <QSpinBox> #include <QCheckBox> #ifndef KDE_USE_FINAL @@ -95,7 +93,7 @@ m_ui->dropdownmenus->setValue( (int)( conf.readEntry( "DropdownMenus", 1.0) * 100 ) ); m_ui->popupmenus->setValue( (int)( conf.readEntry( "PopupMenus", 1.0) * 100 ) ); m_ui->tornoffmenus->setValue( (int)( conf.readEntry( "TornOffMenus", 1.0) * 100 ) ); - m_ui->duration->setValue( conf.readEntry( "Duration", 1800) ); + m_ui->duration->setValue( conf.readEntry( "Duration", 0) ); setIndividualMenuConfig( m_ui->individualmenuconfig->isChecked() ? Qt::Checked : Qt::Unchecked ); emit changed(false); @@ -137,7 +135,7 @@ m_ui->dropdownmenus->setValue( 100 ); m_ui->popupmenus->setValue( 100 ); m_ui->tornoffmenus->setValue( 100 ); - m_ui->duration->setValue( 1500 ); + m_ui->duration->setValue( 0 ); emit changed(true); } Index: effects/showfps.cpp =================================================================== --- kwin/effects/showfps.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/showfps.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -65,6 +65,11 @@ i < MAX_FPS; ++i ) frames[ i ] = 0; + reconfigure( ReconfigureAll ); + } + +void ShowFpsEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup config( KGlobal::config(), "EffectShowFps" ); alpha = config.readEntry( "Alpha", 0.5 ); x = config.readEntry( "X", -10000 ); Index: effects/snow.h =================================================================== --- kwin/effects/snow.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/snow.h (.../work/~seli/kwin11.1) (revision 880714) @@ -39,6 +39,7 @@ public: SnowEffect(); virtual ~SnowEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); Index: effects/cube_config.ui =================================================================== --- kwin/effects/cube_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,512 @@ +<ui version="4.0" > + <class>KWin::CubeEffectConfigForm</class> + <widget class="QWidget" name="KWin::CubeEffectConfigForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>568</width> + <height>595</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QTabWidget" name="tabWidget" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>546</width> + <height>552</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_5" > + <item row="1" column="1" > + <widget class="QGroupBox" name="groupBox_5" > + <property name="title" > + <string>Background</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>Background Color:</string> + </property> + <property name="buddy" > + <cstring>backgroundColorButton</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="KColorButton" name="backgroundColorButton" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Wallpaper:</string> + </property> + <property name="buddy" > + <cstring>wallpaperRequester</cstring> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2" > + <widget class="KUrlRequester" name="wallpaperRequester" /> + </item> + </layout> + </widget> + </item> + <item row="3" column="0" colspan="2" > + <widget class="QGroupBox" name="groupBox_8" > + <property name="title" > + <string>Activation</string> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <item row="0" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Screen edge:</string> + </property> + <property name="buddy" > + <cstring>screenEdgeCombo</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QComboBox" name="screenEdgeCombo" /> + </item> + <item row="1" column="0" colspan="2" > + <widget class="KWin::GlobalShortcutsEditor" native="1" name="editor" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item rowspan="2" row="0" column="0" > + <widget class="QGroupBox" name="groupBox_7" > + <property name="title" > + <string>Appearance</string> + </property> + <layout class="QGridLayout" name="gridLayout_2" > + <item row="0" column="0" colspan="2" > + <widget class="QCheckBox" name="displayDesktopNameBox" > + <property name="text" > + <string>Display desktop name</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2" > + <widget class="QCheckBox" name="reflectionBox" > + <property name="text" > + <string>Reflection</string> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Rotation duration:</string> + </property> + <property name="buddy" > + <cstring>rotationDurationSpin</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QSpinBox" name="rotationDurationSpin" > + <property name="minimumSize" > + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="specialValueText" > + <string>Default</string> + </property> + <property name="suffix" > + <string> msec</string> + </property> + <property name="maximum" > + <number>5000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2" > + <spacer name="verticalSpacer_2" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="0" column="1" > + <widget class="QGroupBox" name="groupBox_4" > + <property name="title" > + <string>Opacity</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3" > + <item> + <layout class="QVBoxLayout" name="verticalLayout_5" > + <item> + <widget class="QSlider" name="cubeOpacitySlider" > + <property name="minimumSize" > + <size> + <width>200</width> + <height>0</height> + </size> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="singleStep" > + <number>1</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>10</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6" > + <item> + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Transparent</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>Opaque</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QSpinBox" name="cubeOpacitySpin" > + <property name="minimumSize" > + <size> + <width>75</width> + <height>0</height> + </size> + </property> + <property name="suffix" > + <string> %</string> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="value" > + <number>100</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>553</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 2</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3" > + <item> + <widget class="QGroupBox" name="groupBox_3" > + <property name="title" > + <string>Caps</string> + </property> + <layout class="QGridLayout" name="gridLayout_4" > + <item row="0" column="0" > + <widget class="QCheckBox" name="cubeCapsBox" > + <property name="text" > + <string>Show caps</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="capColorLabel" > + <property name="text" > + <string>Cap Color:</string> + </property> + <property name="buddy" > + <cstring>capColorButton</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="KColorButton" name="capColorButton" /> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="capsImageBox" > + <property name="text" > + <string>Display image on caps</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Zoom</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QSlider" name="zPositionSlider" > + <property name="toolTip" > + <string>Define how far away the object should appear</string> + </property> + <property name="maximum" > + <number>3000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + <property name="pageStep" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>100</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <widget class="QLabel" name="label_8" > + <property name="text" > + <string>Near</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_9" > + <property name="text" > + <string>Far</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_9" > + <property name="title" > + <string>Additional options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QCheckBox" name="animateDesktopChangeBox" > + <property name="toolTip" > + <string/> + </property> + <property name="text" > + <string>Show cube when desktop changed</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="bigCubeBox" > + <property name="toolTip" > + <string>Cube appears on all screens in a multi screen setup. +If not set cube will appear on only one screen and scaled so that all screens fit on that screen.</string> + </property> + <property name="text" > + <string>Span cube on all screens in multi screen setup</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="closeOnMouseReleaseBox" > + <property name="toolTip" > + <string>Cube is deactivated after rotating the cube with the mouse. +Otherwise cube will stay in the position.</string> + </property> + <property name="text" > + <string>Close after mouse dragging</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="walkThroughDesktopBox" > + <property name="text" > + <string>Use for walk through desktop list</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KColorButton</class> + <extends>QPushButton</extends> + <header>kcolorbutton.h</header> + </customwidget> + <customwidget> + <class>KUrlRequester</class> + <extends>QFrame</extends> + <header>kurlrequester.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>KWin::GlobalShortcutsEditor</class> + <extends>QWidget</extends> + <header location="global" >kwineffects.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>tabWidget</tabstop> + <tabstop>displayDesktopNameBox</tabstop> + <tabstop>reflectionBox</tabstop> + <tabstop>rotationDurationSpin</tabstop> + <tabstop>cubeOpacitySlider</tabstop> + <tabstop>cubeOpacitySpin</tabstop> + <tabstop>backgroundColorButton</tabstop> + <tabstop>wallpaperRequester</tabstop> + <tabstop>screenEdgeCombo</tabstop> + <tabstop>cubeCapsBox</tabstop> + <tabstop>capColorButton</tabstop> + <tabstop>capsImageBox</tabstop> + <tabstop>zPositionSlider</tabstop> + <tabstop>animateDesktopChangeBox</tabstop> + <tabstop>bigCubeBox</tabstop> + <tabstop>closeOnMouseReleaseBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>cubeOpacitySpin</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>386</x> + <y>175</y> + </hint> + <hint type="destinationlabel" > + <x>235</x> + <y>162</y> + </hint> + </hints> + </connection> + <connection> + <sender>cubeOpacitySlider</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySpin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>133</x> + <y>162</y> + </hint> + <hint type="destinationlabel" > + <x>386</x> + <y>175</y> + </hint> + </hints> + </connection> + </connections> +</ui> Index: effects/wobblywindows_config.cpp =================================================================== --- kwin/effects/wobblywindows_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/wobblywindows_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -24,12 +24,9 @@ #include <klocale.h> #include <kdebug.h> -#include <KActionCollection> #include <kaction.h> -#include <KGlobalAccel> #include <kconfiggroup.h> -#include <QGridLayout> #ifndef KDE_USE_FINAL KWIN_EFFECT_CONFIG_FACTORY #endif Index: effects/sphere_config.desktop =================================================================== --- kwin/effects/sphere_config.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere_config.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,26 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kcm_kwin4_effect_builtins +X-KDE-ParentComponents=kwin4_effect_sphere +X-KDE-PluginKeyword=sphere + +Name=Desktop Sphere +Name[et]=Töölauasfäär +Name[ga]=Sféar Deisce +Name[gl]=Escritorio en esfera +Name[gu]=ડેસ્કટોપ ગોળો +Name[km]=ស៊្វែរផ្ទៃតុ +Name[nds]=Schriefdischkugel +Name[nn]=Skrivebordskule +Name[pt]=Esfera de Ecrãs +Name[pt_BR]=Esfera de Ecrãs +Name[sl]=Krogla z namizji +Name[sr]=Сфера површи +Name[sr@latin]=Sfera površi +Name[sv]=Skrivbordsklot +Name[te]=డెస్క్ టాప్ గొళం +Name[tr]=Masaüstü Küresi +Name[uk]=Стільнична сфера +Name[zh_TW]=桌面球體 Index: effects/maketransparent.h =================================================================== --- kwin/effects/maketransparent.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/maketransparent.h (.../work/~seli/kwin11.1) (revision 880714) @@ -31,6 +31,7 @@ { public: MakeTransparentEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last ); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); Index: effects/cylinder.h =================================================================== --- kwin/effects/cylinder.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,54 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_CYLINDER_H +#define KWIN_CYLINDER_H + +#include <kwineffects.h> +#include <kwinglutils.h> + +namespace KWin +{ + +class CylinderEffect + : public CubeEffect + { + public: + CylinderEffect(); + ~CylinderEffect(); + virtual void reconfigure( ReconfigureFlags ); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void desktopChanged( int old ); + + static bool supported(); + protected: + virtual void paintScene( int mask, QRegion region, ScreenPaintData& data ); + virtual void paintCap( float z, float zTexture ); + private: + bool loadData(); + bool mInited; + bool mValid; + GLShader* mShader; + }; + +} // namespace + +#endif Index: effects/maketransparent_config.ui =================================================================== --- kwin/effects/maketransparent_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/maketransparent_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -346,9 +346,6 @@ <property name="pageStep" > <number>100</number> </property> - <property name="value" > - <number>1500</number> - </property> <property name="orientation" > <enum>Qt::Horizontal</enum> </property> @@ -370,6 +367,9 @@ <height>0</height> </size> </property> + <property name="specialValueText" > + <string>Default</string> + </property> <property name="suffix" > <string>msec</string> </property> @@ -379,9 +379,6 @@ <property name="singleStep" > <number>100</number> </property> - <property name="value" > - <number>1500</number> - </property> </widget> </item> </layout> @@ -398,8 +395,8 @@ <slot>setValue(int)</slot> <hints> <hint type="sourcelabel" > - <x>433</x> - <y>282</y> + <x>476</x> + <y>280</y> </hint> <hint type="destinationlabel" > <x>246</x> @@ -418,8 +415,8 @@ <y>283</y> </hint> <hint type="destinationlabel" > - <x>433</x> - <y>282</y> + <x>476</x> + <y>280</y> </hint> </hints> </connection> Index: effects/cylinder_config.ui =================================================================== --- kwin/effects/cylinder_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,489 @@ +<ui version="4.0" > + <class>KWin::CylinderEffectConfigForm</class> + <widget class="QWidget" name="KWin::CylinderEffectConfigForm" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>568</width> + <height>595</height> + </rect> + </property> + <layout class="QVBoxLayout" > + <item> + <widget class="QTabWidget" name="tabWidget" > + <property name="currentIndex" > + <number>0</number> + </property> + <widget class="QWidget" name="tab" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>546</width> + <height>552</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 1</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_5" > + <item row="1" column="1" > + <widget class="QGroupBox" name="groupBox_5" > + <property name="title" > + <string>Background</string> + </property> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" > + <widget class="QLabel" name="label_6" > + <property name="text" > + <string>Background Color:</string> + </property> + <property name="buddy" > + <cstring>backgroundColorButton</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="KColorButton" name="backgroundColorButton" /> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Wallpaper:</string> + </property> + <property name="buddy" > + <cstring>wallpaperRequester</cstring> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2" > + <widget class="KUrlRequester" name="wallpaperRequester" /> + </item> + </layout> + </widget> + </item> + <item row="3" column="0" colspan="2" > + <widget class="QGroupBox" name="groupBox_8" > + <property name="title" > + <string>Activation</string> + </property> + <layout class="QGridLayout" name="gridLayout_3" > + <item row="0" column="0" > + <widget class="QLabel" name="label_2" > + <property name="text" > + <string>Screen edge:</string> + </property> + <property name="buddy" > + <cstring>screenEdgeCombo</cstring> + </property> + </widget> + </item> + <item row="0" column="1" > + <widget class="QComboBox" name="screenEdgeCombo" /> + </item> + <item row="1" column="0" colspan="2" > + <widget class="KWin::GlobalShortcutsEditor" native="1" name="editor" > + <property name="minimumSize" > + <size> + <width>0</width> + <height>200</height> + </size> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item rowspan="2" row="0" column="0" > + <widget class="QGroupBox" name="groupBox_7" > + <property name="title" > + <string>Appearance</string> + </property> + <layout class="QGridLayout" name="gridLayout_2" > + <item row="0" column="0" colspan="2" > + <widget class="QCheckBox" name="displayDesktopNameBox" > + <property name="text" > + <string>Display desktop name</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2" > + <widget class="QCheckBox" name="reflectionBox" > + <property name="text" > + <string>Reflection</string> + </property> + </widget> + </item> + <item row="2" column="0" > + <widget class="QLabel" name="label" > + <property name="text" > + <string>Rotation duration:</string> + </property> + <property name="buddy" > + <cstring>rotationDurationSpin</cstring> + </property> + </widget> + </item> + <item row="2" column="1" > + <widget class="QSpinBox" name="rotationDurationSpin" > + <property name="minimumSize" > + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="specialValueText" > + <string>Default</string> + </property> + <property name="suffix" > + <string> msec</string> + </property> + <property name="maximum" > + <number>5000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2" > + <spacer name="verticalSpacer_2" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="0" column="1" > + <widget class="QGroupBox" name="groupBox_4" > + <property name="title" > + <string>Opacity</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3" > + <item> + <layout class="QVBoxLayout" name="verticalLayout_5" > + <item> + <widget class="QSlider" name="cubeOpacitySlider" > + <property name="minimumSize" > + <size> + <width>200</width> + <height>0</height> + </size> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="singleStep" > + <number>1</number> + </property> + <property name="value" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>10</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_6" > + <item> + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Transparent</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>Opaque</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="QSpinBox" name="cubeOpacitySpin" > + <property name="minimumSize" > + <size> + <width>75</width> + <height>0</height> + </size> + </property> + <property name="suffix" > + <string> %</string> + </property> + <property name="maximum" > + <number>100</number> + </property> + <property name="value" > + <number>100</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>553</height> + </rect> + </property> + <attribute name="title" > + <string>Tab 2</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_3" > + <item> + <widget class="QGroupBox" name="groupBox_3" > + <property name="title" > + <string>Caps</string> + </property> + <layout class="QGridLayout" name="gridLayout_4" > + <item row="0" column="0" > + <widget class="QCheckBox" name="cubeCapsBox" > + <property name="text" > + <string>Show caps</string> + </property> + </widget> + </item> + <item row="1" column="0" > + <widget class="QLabel" name="capColorLabel" > + <property name="text" > + <string>Cap Color:</string> + </property> + <property name="buddy" > + <cstring>capColorButton</cstring> + </property> + </widget> + </item> + <item row="1" column="1" > + <widget class="KColorButton" name="capColorButton" /> + </item> + <item row="2" column="0" > + <widget class="QCheckBox" name="capsImageBox" > + <property name="text" > + <string>Display image on caps</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2" > + <property name="title" > + <string>Zoom</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2" > + <item> + <widget class="QSlider" name="zPositionSlider" > + <property name="toolTip" > + <string>Define how far away the object should appear</string> + </property> + <property name="maximum" > + <number>3000</number> + </property> + <property name="singleStep" > + <number>10</number> + </property> + <property name="pageStep" > + <number>100</number> + </property> + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition" > + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval" > + <number>100</number> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2" > + <item> + <widget class="QLabel" name="label_8" > + <property name="text" > + <string>Near</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2" > + <property name="orientation" > + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label_9" > + <property name="text" > + <string>Far</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_9" > + <property name="title" > + <string>Additional options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QCheckBox" name="closeOnMouseReleaseBox" > + <property name="toolTip" > + <string>Cylinder is deactivated after rotating the cylinder with the mouse. +Otherwise cylinder will stay in the position.</string> + </property> + <property name="text" > + <string>Close after mouse dragging</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="walkThroughDesktopBox" > + <property name="text" > + <string>Use for walk through desktop list</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer" > + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>KColorButton</class> + <extends>QPushButton</extends> + <header>kcolorbutton.h</header> + </customwidget> + <customwidget> + <class>KUrlRequester</class> + <extends>QFrame</extends> + <header>kurlrequester.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>KWin::GlobalShortcutsEditor</class> + <extends>QWidget</extends> + <header location="global" >kwineffects.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>tabWidget</tabstop> + <tabstop>displayDesktopNameBox</tabstop> + <tabstop>reflectionBox</tabstop> + <tabstop>rotationDurationSpin</tabstop> + <tabstop>cubeOpacitySlider</tabstop> + <tabstop>cubeOpacitySpin</tabstop> + <tabstop>backgroundColorButton</tabstop> + <tabstop>wallpaperRequester</tabstop> + <tabstop>screenEdgeCombo</tabstop> + <tabstop>cubeCapsBox</tabstop> + <tabstop>capColorButton</tabstop> + <tabstop>capsImageBox</tabstop> + <tabstop>zPositionSlider</tabstop> + <tabstop>closeOnMouseReleaseBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>cubeOpacitySpin</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>386</x> + <y>175</y> + </hint> + <hint type="destinationlabel" > + <x>235</x> + <y>162</y> + </hint> + </hints> + </connection> + <connection> + <sender>cubeOpacitySlider</sender> + <signal>valueChanged(int)</signal> + <receiver>cubeOpacitySpin</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel" > + <x>133</x> + <y>162</y> + </hint> + <hint type="destinationlabel" > + <x>386</x> + <y>175</y> + </hint> + </hints> + </connection> + </connections> +</ui> Index: effects/shadow.h =================================================================== --- kwin/effects/shadow.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/shadow.h (.../work/~seli/kwin11.1) (revision 880714) @@ -48,6 +48,7 @@ public: ShadowEffect(); virtual ~ShadowEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); Index: effects/lookingglass.cpp =================================================================== --- kwin/effects/lookingglass.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/lookingglass.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -43,7 +43,6 @@ zoom = 1.0f; target_zoom = 1.0f; - KConfigGroup conf = EffectsHandler::effectConfig("LookingGlass"); actionCollection = new KActionCollection( this ); actionCollection->setConfigGlobal(true); actionCollection->setConfigGroup("LookingGlass"); @@ -55,18 +54,22 @@ 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)); + reconfigure( ReconfigureAll ); + } + +LookingGlassEffect::~LookingGlassEffect() + { + } + +void LookingGlassEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = EffectsHandler::effectConfig("LookingGlass"); initialradius = conf.readEntry("Radius", 200); radius = initialradius; - kDebug(1212) << QString("Radius from config: %1").arg(radius) << endl; - actionCollection->readSettings(); } -LookingGlassEffect::~LookingGlassEffect() - { - } - void LookingGlassEffect::toggle() { if( target_zoom == 1.0f ) @@ -98,7 +101,7 @@ { if( zoom != target_zoom ) { - double diff = time / 500.0; + double diff = time / animationTime( 500.0 ); if( target_zoom > zoom ) zoom = qMin( zoom * qMax( 1.0 + diff, 1.2 ), target_zoom ); else Index: effects/maketransparent.cpp =================================================================== --- kwin/effects/maketransparent.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/maketransparent.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -32,6 +32,12 @@ , current( NULL ) , previous( NULL ) { + reconfigure( ReconfigureAll ); + active = effects->activeWindow(); + } + +void MakeTransparentEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig("MakeTransparent"); decoration = conf.readEntry( "Decoration", 1.0 ); moveresize = conf.readEntry( "MoveResize", 0.8 ); @@ -52,11 +58,10 @@ popupmenus = menus; tornoffmenus = menus; } - active = effects->activeWindow(); moveresize_timeline.setCurveShape( TimeLine::EaseOutCurve ); - moveresize_timeline.setDuration( conf.readEntry( "Duration", 800 ) ); + moveresize_timeline.setDuration( animationTime( conf, "Duration", 800 ) ); activeinactive_timeline.setCurveShape( TimeLine::EaseInOutCurve ); - activeinactive_timeline.setDuration( conf.readEntry( "Duration", 800 ) ); + activeinactive_timeline.setDuration( animationTime( conf, "Duration", 800 ) ); } void MakeTransparentEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) Index: effects/login.cpp =================================================================== --- kwin/effects/login.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/login.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -39,7 +39,7 @@ { if( progress != 1 ) { - progress = qBound( 0., progress + time / 2000., 1. ); + progress = qBound( 0., progress + time / animationTime( 2000. ), 1. ); if( progress == 1 ) { login_window->unrefWindow(); Index: effects/presentwindows_config.cpp =================================================================== --- kwin/effects/presentwindows_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/presentwindows_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -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 @@ -19,160 +20,183 @@ *********************************************************************/ #include "presentwindows_config.h" - #include <kwineffects.h> -#include <klocale.h> -#include <kdebug.h> #include <kconfiggroup.h> #include <KActionCollection> #include <kaction.h> -#include <KShortcutsEditor> -#include <KGlobalAccel> -#include <QWidget> -#include <QGridLayout> -#include <QLabel> -#include <QComboBox> -#include <QCheckBox> - +#include <QVBoxLayout> +#include <QColor> +#ifndef KDE_USE_FINAL KWIN_EFFECT_CONFIG_FACTORY +#endif namespace KWin { -PresentWindowsEffectConfig::PresentWindowsEffectConfig(QWidget* parent, const QVariantList& args) : - KCModule(EffectFactory::componentData(), parent, args) +PresentWindowsEffectConfigForm::PresentWindowsEffectConfigForm(QWidget* parent) : QWidget(parent) +{ + setupUi(this); +} + +PresentWindowsEffectConfig::PresentWindowsEffectConfig(QWidget* parent, const QVariantList& args) + : KCModule( EffectFactory::componentData(), parent, args ) { - kDebug(); + m_ui = new PresentWindowsEffectConfigForm( this ); - QGridLayout* layout = new QGridLayout(this); + QVBoxLayout* layout = new QVBoxLayout( this ); - mDrawWindowText = new QCheckBox(i18n("Draw window caption on top of window"), this); - connect(mDrawWindowText, SIGNAL(stateChanged(int)), this, SLOT(changed())); - layout->addWidget(mDrawWindowText, 0, 0); + layout->addWidget( m_ui ); - layout->addWidget(new QLabel(i18n("Activate when cursor is at a specific edge " - "or corner of the screen:"), this), 1, 0, 1, 3); - layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Fixed), 2, 0, 2, 1); + m_actionCollection = new KActionCollection( this, componentData() ); + m_actionCollection->setConfigGroup( "PresentWindows" ); + m_actionCollection->setConfigGlobal( true ); - layout->addWidget(new QLabel(i18n("for windows on current desktop: "), this), 2, 1); - mActivateCombo = new QComboBox; - addItems(mActivateCombo); - connect(mActivateCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); - layout->addWidget(mActivateCombo, 2, 2); + KAction* a = (KAction*) m_actionCollection->addAction( "ExposeAll" ); + a->setText( i18n( "Toggle Present Windows (All desktops)" )); + a->setProperty( "isConfigurationAction", true ); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F10 )); - layout->addWidget(new QLabel(i18n("for windows on all desktops: "), this), 3, 1); - mActivateAllCombo = new QComboBox; - addItems(mActivateAllCombo); - connect(mActivateAllCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); - layout->addWidget(mActivateAllCombo, 3, 2); + KAction* b = (KAction*) m_actionCollection->addAction( "Expose" ); + b->setText( i18n( "Toggle Present Windows (Current desktop)" )); + b->setProperty( "isConfigurationAction", true ); + b->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F9 )); - layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding), 4, 0, 1, 3); + m_ui->shortcutEditor->addCollection( m_actionCollection ); - // Shortcut config - KActionCollection* actionCollection = new KActionCollection( this, componentData() ); - KAction* a = (KAction*)actionCollection->addAction( "Expose" ); - a->setText( i18n("Toggle Expose Effect" )); - a->setProperty("isConfigurationAction", true); - a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F9)); + m_ui->screenEdgeAllCombo->addItem( i18n( "Top" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Top-right" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Right" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom-right" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom-left" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Left" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "Top-left" )); + m_ui->screenEdgeAllCombo->addItem( i18n( "None" )); - KAction* b = (KAction*)actionCollection->addAction( "ExposeAll" ); - b->setText( i18n("Toggle Expose Effect (incl. other desktops)" )); - b->setProperty("isConfigurationAction", true); - b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F10)); + m_ui->screenEdgeCombo->addItem( i18n( "Top" )); + m_ui->screenEdgeCombo->addItem( i18n( "Top-right" )); + m_ui->screenEdgeCombo->addItem( i18n( "Right" )); + m_ui->screenEdgeCombo->addItem( i18n( "Bottom-right" )); + m_ui->screenEdgeCombo->addItem( i18n( "Bottom" )); + m_ui->screenEdgeCombo->addItem( i18n( "Bottom-left" )); + m_ui->screenEdgeCombo->addItem( i18n( "Left" )); + m_ui->screenEdgeCombo->addItem( i18n( "Top-left" )); + m_ui->screenEdgeCombo->addItem( i18n( "None" )); - mShortcutEditor = new KShortcutsEditor(actionCollection, this, - KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed); - connect(mShortcutEditor, SIGNAL(keyChange()), this, SLOT(changed())); - layout->addWidget(mShortcutEditor, 5, 0, 1, 3); + connect( m_ui->layoutCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->rearrangeDurationSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() )); + connect( m_ui->displayTitleBox, SIGNAL( stateChanged( int )), this, SLOT( changed() )); + connect( m_ui->displayIconBox, SIGNAL( stateChanged( int )), this, SLOT( changed() )); + connect( m_ui->switchingBox, SIGNAL( stateChanged( int )), this, SLOT( changed() )); + connect( m_ui->accuracySlider, SIGNAL( valueChanged( int )), this, SLOT( changed() )); + connect( m_ui->fillGapsBox, SIGNAL( stateChanged( int )), this, SLOT( changed() )); + connect( m_ui->screenEdgeAllCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->screenEdgeCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() )); - layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding), 6, 0, 1, 3); - load(); } PresentWindowsEffectConfig::~PresentWindowsEffectConfig() { - kDebug(); - // Undo (only) unsaved changes to global key shortcuts - mShortcutEditor->undoChanges(); + // If save() is called undoChanges() has no effect + m_ui->shortcutEditor->undoChanges(); } -void PresentWindowsEffectConfig::addItems(QComboBox* combo) - { - combo->addItem(i18n("Top")); - combo->addItem(i18n("Top-right")); - combo->addItem(i18n("Right")); - combo->addItem(i18n("Bottom-right")); - combo->addItem(i18n("Bottom")); - combo->addItem(i18n("Bottom-left")); - combo->addItem(i18n("Left")); - combo->addItem(i18n("Top-left")); - combo->addItem(i18n("None")); - } - void PresentWindowsEffectConfig::load() { - kDebug() ; KCModule::load(); - KConfigGroup conf = EffectsHandler::effectConfig("PresentWindows"); - int activateBorder = conf.readEntry("BorderActivate", (int)ElectricNone); - if(activateBorder == (int)ElectricNone) - activateBorder--; - mActivateCombo->setCurrentIndex(activateBorder); + KConfigGroup conf = EffectsHandler::effectConfig( "PresentWindows" ); + + int layoutMode = conf.readEntry( "LayoutMode", int( PresentWindowsEffect::LayoutNatural )); + m_ui->layoutCombo->setCurrentIndex( layoutMode ); - int activateAllBorder = conf.readEntry("BorderActivateAll", (int)ElectricTopLeft); - if(activateAllBorder == (int)ElectricNone) + m_ui->rearrangeDurationSpin->setValue( conf.readEntry( "RearrangeDuration", 0 )); + + bool displayTitle = conf.readEntry( "DrawWindowCaptions", true ); + m_ui->displayTitleBox->setChecked( displayTitle ); + + bool displayIcon = conf.readEntry( "DrawWindowIcons", true ); + m_ui->displayIconBox->setChecked( displayIcon ); + + bool switching = conf.readEntry( "TabBox", false ); + m_ui->switchingBox->setChecked( switching ); + + int accuracy = conf.readEntry( "Accuracy", 1 ); + m_ui->accuracySlider->setSliderPosition( accuracy ); + + bool fillGaps = conf.readEntry( "FillGaps", true ); + m_ui->fillGapsBox->setChecked( fillGaps ); + + int activateAllBorder = conf.readEntry( "BorderActivateAll", int( ElectricTopLeft )); + if( activateAllBorder == int( ElectricNone )) activateAllBorder--; - mActivateAllCombo->setCurrentIndex(activateAllBorder); + m_ui->screenEdgeAllCombo->setCurrentIndex( activateAllBorder ); - bool drawWindowCaptions = conf.readEntry("DrawWindowCaptions", true); - mDrawWindowText->setChecked(drawWindowCaptions); + int activateBorder = conf.readEntry( "BorderActivate", int( ElectricNone )); + if( activateBorder == int( ElectricNone )) + activateBorder--; + m_ui->screenEdgeCombo->setCurrentIndex( activateBorder ); emit changed(false); } void PresentWindowsEffectConfig::save() { - kDebug() ; KCModule::save(); - KConfigGroup conf = EffectsHandler::effectConfig("PresentWindows"); + KConfigGroup conf = EffectsHandler::effectConfig( "PresentWindows" ); - int activateBorder = mActivateCombo->currentIndex(); - if(activateBorder == (int)ELECTRIC_COUNT) - activateBorder = (int)ElectricNone; - conf.writeEntry("BorderActivate", activateBorder); + int layoutMode = m_ui->layoutCombo->currentIndex(); + conf.writeEntry( "LayoutMode", layoutMode ); - int activateAllBorder = mActivateAllCombo->currentIndex(); - if(activateAllBorder == (int)ELECTRIC_COUNT) - activateAllBorder = (int)ElectricNone; - conf.writeEntry("BorderActivateAll", activateAllBorder); + conf.writeEntry( "RearrangeDuration", m_ui->rearrangeDurationSpin->value() ); - bool drawWindowCaptions = mDrawWindowText->isChecked(); - conf.writeEntry("DrawWindowCaptions", drawWindowCaptions); + conf.writeEntry( "DrawWindowCaptions", m_ui->displayTitleBox->isChecked() ); + conf.writeEntry( "DrawWindowIcons", m_ui->displayIconBox->isChecked() ); + conf.writeEntry( "TabBox", m_ui->switchingBox->isChecked() ); + int accuracy = m_ui->accuracySlider->value(); + conf.writeEntry( "Accuracy", accuracy ); + + conf.writeEntry( "FillGaps", m_ui->fillGapsBox->isChecked() ); + + int activateAllBorder = m_ui->screenEdgeAllCombo->currentIndex(); + if( activateAllBorder == int( ELECTRIC_COUNT )) + activateAllBorder = int( ElectricNone ); + conf.writeEntry( "BorderActivateAll", activateAllBorder ); + + int activateBorder = m_ui->screenEdgeCombo->currentIndex(); + if( activateBorder == int( ELECTRIC_COUNT )) + activateBorder = int( ElectricNone ); + conf.writeEntry( "BorderActivate", activateBorder ); + + m_ui->shortcutEditor->save(); + conf.sync(); - mShortcutEditor->save(); // undo() will restore to this state from now on - emit changed(false); EffectsHandler::sendReloadMessage( "presentwindows" ); } void PresentWindowsEffectConfig::defaults() { - kDebug() ; - mActivateCombo->setCurrentIndex( (int)ElectricNone - 1 ); - mActivateAllCombo->setCurrentIndex( (int)ElectricTopLeft ); - mDrawWindowText->setChecked(true); - mShortcutEditor->allDefault(); + m_ui->layoutCombo->setCurrentIndex( int( PresentWindowsEffect::LayoutNatural )); + m_ui->rearrangeDurationSpin->setValue( 0 ); + m_ui->displayTitleBox->setChecked( true ); + m_ui->displayIconBox->setChecked( true ); + m_ui->switchingBox->setChecked( false ); + m_ui->accuracySlider->setSliderPosition( 1 ); + m_ui->fillGapsBox->setChecked( true ); + m_ui->screenEdgeAllCombo->setCurrentIndex( int( ElectricTopLeft )); + m_ui->screenEdgeCombo->setCurrentIndex( int( ElectricNone - 1 )); + m_ui->shortcutEditor->allDefault(); emit changed(true); } - } // namespace #include "presentwindows_config.moc" Index: effects/flipswitch.h =================================================================== --- kwin/effects/flipswitch.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/flipswitch.h (.../work/~seli/kwin11.1) (revision 880714) @@ -33,6 +33,7 @@ FlipSwitchEffect(); ~FlipSwitchEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); Index: effects/thumbnailaside.cpp =================================================================== --- kwin/effects/thumbnailaside.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/thumbnailaside.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -33,18 +33,22 @@ ThumbnailAsideEffect::ThumbnailAsideEffect() { - KConfigGroup conf = EffectsHandler::effectConfig("ThumbnailAside"); - KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = (KAction*)actionCollection->addAction( "ToggleCurrentThumbnail" ); a->setText( i18n("Toggle Thumbnail for Current Window" )); a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_T)); connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleCurrentThumbnail())); + reconfigure( ReconfigureAll ); + } +void ThumbnailAsideEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = EffectsHandler::effectConfig("ThumbnailAside"); maxwidth = conf.readEntry("MaxWidth", 200); spacing = conf.readEntry("Spacing", 10); opacity = conf.readEntry("Opacity", 50) / 100.0; screen = conf.readEntry("Screen",-1); // Xinerama screen TODO add gui option + arrange(); } void ThumbnailAsideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) Index: effects/flipswitch_config.ui =================================================================== --- kwin/effects/flipswitch_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/flipswitch_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -35,14 +35,17 @@ </item> <item row="1" column="1" > <widget class="QSpinBox" name="spinFlipDuration" > + <property name="specialValueText" > + <string>Default</string> + </property> <property name="suffix" > <string> msec</string> </property> <property name="maximum" > <number>5000</number> </property> - <property name="value" > - <number>200</number> + <property name="singleStep" > + <number>10</number> </property> </widget> </item> Index: effects/diminactive.cpp =================================================================== --- kwin/effects/diminactive.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/diminactive.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -30,12 +30,16 @@ DimInactiveEffect::DimInactiveEffect() { + reconfigure( ReconfigureAll ); + active = effects->activeWindow(); + } + +void DimInactiveEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = EffectsHandler::effectConfig("DimInactive"); - dim_panels = conf.readEntry("DimPanels", false); dim_by_group = conf.readEntry("DimByGroup", true); dim_strength = conf.readEntry("Strength", 25); - active = effects->activeWindow(); } void DimInactiveEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) Index: effects/cylinder_config.cpp =================================================================== --- kwin/effects/cylinder_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,247 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "cylinder_config.h" +#include <kwineffects.h> + +#include <kconfiggroup.h> +#include <kcolorscheme.h> +#include <KActionCollection> +#include <kaction.h> +#include <KFileDialog> +#include <KImageFilePreview> + +#include <QGridLayout> +#include <QColor> +#ifndef KDE_USE_FINAL +KWIN_EFFECT_CONFIG_FACTORY +#endif + +namespace KWin +{ + +CylinderEffectConfigForm::CylinderEffectConfigForm(QWidget* parent) : QWidget(parent) +{ + setupUi(this); +} + +CylinderEffectConfig::CylinderEffectConfig(QWidget* parent, const QVariantList& args) : + KCModule(EffectFactory::componentData(), parent, args) + { + m_ui = new CylinderEffectConfigForm(this); + + QGridLayout* layout = new QGridLayout(this); + + layout->addWidget(m_ui, 0, 0); + + m_ui->tabWidget->setTabText( 0, i18n("Basic") ); + m_ui->tabWidget->setTabText( 1, i18n("Advanced") ); + + m_ui->screenEdgeCombo->addItem(i18n("Top")); + m_ui->screenEdgeCombo->addItem(i18n("Top-right")); + m_ui->screenEdgeCombo->addItem(i18n("Right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-left")); + m_ui->screenEdgeCombo->addItem(i18n("Left")); + m_ui->screenEdgeCombo->addItem(i18n("Top-left")); + m_ui->screenEdgeCombo->addItem(i18n("None")); + + m_actionCollection = new KActionCollection( this, componentData() ); + m_actionCollection->setConfigGroup( "Cube" ); + m_actionCollection->setConfigGlobal(true); + + KAction* a = (KAction*) m_actionCollection->addAction( "Cube" ); + a->setText( i18n("Desktop Cube" )); + a->setProperty("isConfigurationAction", true); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F11 )); + + m_ui->editor->addCollection(m_actionCollection); + + connect(m_ui->screenEdgeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + connect(m_ui->rotationDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->displayDesktopNameBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->reflectionBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->backgroundColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(capsSelectionChanged())); + connect(m_ui->capsImageBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->capColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->wallpaperRequester, SIGNAL(textChanged(QString)), this, SLOT(changed())); + connect(m_ui->closeOnMouseReleaseBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->zPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->walkThroughDesktopBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + + load(); + } + +void CylinderEffectConfig::load() + { + KCModule::load(); + + KConfigGroup conf = EffectsHandler::effectConfig( "Cylinder" ); + + int duration = conf.readEntry( "RotationDuration", 0 ); + float opacity = conf.readEntry( "Opacity", 80 ); + bool desktopName = conf.readEntry( "DisplayDesktopName", true ); + bool reflection = conf.readEntry( "Reflection", true ); + int activateBorder = conf.readEntry( "BorderActivate", (int)ElectricNone ); + QColor background = conf.readEntry( "BackgroundColor", QColor( Qt::black ) ); + QColor capColor = conf.readEntry( "CapColor", KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + bool texturedCaps = conf.readEntry( "TexturedCaps", true ); + bool caps = conf.readEntry( "Caps", true ); + bool closeOnMouseRelease = conf.readEntry( "CloseOnMouseRelease", false ); + bool walkThroughDesktop = conf.readEntry( "TabBox", false ); + m_ui->zPositionSlider->setValue( conf.readEntry( "ZPosition", 100 ) ); + m_ui->wallpaperRequester->setPath( conf.readEntry( "Wallpaper", "" ) ); + if( activateBorder == (int)ElectricNone ) + activateBorder--; + m_ui->screenEdgeCombo->setCurrentIndex( activateBorder ); + + m_ui->rotationDurationSpin->setValue( duration ); + m_ui->cubeOpacitySlider->setValue( opacity ); + m_ui->cubeOpacitySpin->setValue( opacity ); + if( desktopName ) + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Unchecked ); + } + if( reflection ) + { + m_ui->reflectionBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->reflectionBox->setCheckState( Qt::Unchecked ); + } + if( caps ) + { + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->cubeCapsBox->setCheckState( Qt::Unchecked ); + } + if( texturedCaps ) + { + m_ui->capsImageBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->capsImageBox->setCheckState( Qt::Unchecked ); + } + if( closeOnMouseRelease ) + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + } + if( walkThroughDesktop ) + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + } + m_ui->backgroundColorButton->setColor( background ); + m_ui->capColorButton->setColor( capColor ); + capsSelectionChanged(); + + emit changed(false); + } + +void CylinderEffectConfig::save() + { + KConfigGroup conf = EffectsHandler::effectConfig( "Cylinder" ); + + conf.writeEntry( "RotationDuration", m_ui->rotationDurationSpin->value() ); + conf.writeEntry( "DisplayDesktopName", m_ui->displayDesktopNameBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Reflection", m_ui->reflectionBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Opacity", m_ui->cubeOpacitySpin->value() ); + conf.writeEntry( "BackgroundColor", m_ui->backgroundColorButton->color() ); + conf.writeEntry( "Caps", m_ui->cubeCapsBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CapColor", m_ui->capColorButton->color() ); + conf.writeEntry( "TexturedCaps", m_ui->capsImageBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CloseOnMouseRelease", m_ui->closeOnMouseReleaseBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Wallpaper", m_ui->wallpaperRequester->url().path() ); + conf.writeEntry( "ZPosition", m_ui->zPositionSlider->value() ); + conf.writeEntry( "TabBox", m_ui->walkThroughDesktopBox->checkState() == Qt::Checked ? true : false ); + + int activateBorder = m_ui->screenEdgeCombo->currentIndex(); + if( activateBorder == (int)ELECTRIC_COUNT ) + activateBorder = (int)ElectricNone; + conf.writeEntry( "BorderActivate", activateBorder ); + + m_ui->editor->save(); + + conf.sync(); + + emit changed(false); + EffectsHandler::sendReloadMessage( "cylinder" ); + } + +void CylinderEffectConfig::defaults() + { + m_ui->rotationDurationSpin->setValue( 0 ); + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + m_ui->reflectionBox->setCheckState( Qt::Checked ); + m_ui->cubeOpacitySpin->setValue( 80 ); + m_ui->cubeOpacitySlider->setValue( 80 ); + m_ui->screenEdgeCombo->setCurrentIndex( (int)ElectricNone -1 ); + m_ui->backgroundColorButton->setColor( QColor( Qt::black ) ); + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + m_ui->capColorButton->setColor( KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + m_ui->capsImageBox->setCheckState( Qt::Checked ); + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + m_ui->wallpaperRequester->setPath( "" ); + m_ui->zPositionSlider->setValue( 100 ); + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + m_ui->editor->allDefault(); + emit changed(true); + } + +void CylinderEffectConfig::capsSelectionChanged() + { + if( m_ui->cubeCapsBox->checkState() == Qt::Checked ) + { + // activate cap color + m_ui->capColorButton->setEnabled( true ); + m_ui->capColorLabel->setEnabled( true ); + m_ui->capsImageBox->setEnabled( true ); + } + else + { + // deactivate cap color + m_ui->capColorButton->setEnabled( false ); + m_ui->capColorLabel->setEnabled( false ); + m_ui->capsImageBox->setEnabled( false ); + } + } + +} // namespace + +#include "cylinder_config.moc" Index: effects/cylinder.desktop =================================================================== --- kwin/effects/cylinder.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,51 @@ +[Desktop Entry] +Name=Desktop Cylinder +Name[et]=Töölauasilinder +Name[gl]=Escritorio cilíndrico +Name[gu]=ડેસ્કટોપ સિલિન્ડર +Name[ja]=デスクトップシリンダー +Name[km]=ស៊ីឡាំងផ្ទៃតុ +Name[nds]=Zylinner-Schriefdisch +Name[nn]=Skrivebordsylinder +Name[pt]=Cilindro de Ecrãs +Name[pt_BR]=Cilindro de Ecrãs +Name[sl]=Valj z namizji +Name[sr]=Ваљак површи +Name[sr@latin]=Valjak površi +Name[sv]=Skrivbordscylinder +Name[te]=డెస్క్ టాప్ సిలెండర్ +Name[tr]=Masaüstü Silindiri +Name[uk]=Циліндр стільниць +Name[zh_TW]=桌面圓柱 +Icon=preferences-system-windows-effect-cylinder +Comment=Map virtual desktops on a cylinder +Comment[et]=Virtuaalsete töölaudade asetamine silindrile +Comment[gl]=Mostra os escritorios virtuais nun cilindro +Comment[gu]=વર્ચ્યુઅલ ડેસ્કટોપને સિલિન્ડર પર જોડો +Comment[ja]=仮想デスクトップをシリンダーに位置付けます +Comment[km]=ផ្ទៃតុនិម្មិតផែនទីនៅលើស៊ីឡាំង +Comment[nds]=Schriefdischen op en Zylinner afbillen +Comment[nn]=Virtuelle skrivebord viste på ein sylinder +Comment[pt]=Mapear os ecrãs virtuais sobre um cilindro +Comment[pt_BR]=Mapear os ecrãs virtuais sobre um cilindro +Comment[sl]=Navidezna namizja preslika na valj +Comment[sr]=Слика виртуелне површи на ваљак +Comment[sr@latin]=Slika virtuelne površi na valjak +Comment[sv]=Avbilda virtuella skrivbord på en cylinder +Comment[te]=సిలెండర్పైన వర్చ్యువల్ డెస్క్ టాప్లను మాప్చేయుము +Comment[tr]=Sanal masaüstlerini bir silindir olarak göster +Comment[uk]=Призначити віртуальні стільниці до циліндра +Comment[zh_TW]=將虛擬桌面映射到一圓柱 + +Type=Service +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Martin Gräßlin +X-KDE-PluginInfo-Email=ubuntu@martin-graesslin.com +X-KDE-PluginInfo-Name=kwin4_effect_cylinder +X-KDE-PluginInfo-Version=0.1.0 +X-KDE-PluginInfo-Category=Window Management +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +X-KDE-Library=kwin4_effect_builtins +X-KDE-Ordering=50 Index: effects/magnifier.cpp =================================================================== --- kwin/effects/magnifier.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/magnifier.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -43,8 +43,6 @@ : zoom( 1 ) , target_zoom( 1 ) { - KConfigGroup conf = EffectsHandler::effectConfig("Magnifier"); - KActionCollection* actionCollection = new KActionCollection( this ); KAction* a; a = static_cast< KAction* >( actionCollection->addAction( KStandardAction::ZoomIn, this, SLOT( zoomIn()))); @@ -53,7 +51,12 @@ 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)); + reconfigure( ReconfigureAll ); + } +void MagnifierEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = EffectsHandler::effectConfig("Magnifier"); int width, height; width = conf.readEntry("Width", 200); height = conf.readEntry("Height", 200); @@ -64,7 +67,7 @@ { if( zoom != target_zoom ) { - double diff = time / 500.0; + double diff = time / animationTime( 500.0 ); if( target_zoom > zoom ) zoom = qMin( zoom * qMax( 1 + diff, 1.2 ), target_zoom ); else Index: effects/wobblywindows_constants.h =================================================================== --- kwin/effects/wobblywindows_constants.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/wobblywindows_constants.h (.../work/~seli/kwin11.1) (revision 880714) @@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. *********************************************************************/ -#include <QtGlobal> static const qreal STIFFNESS = 0.06; static const qreal DRAG = 0.92; Index: effects/sphere_config.h =================================================================== --- kwin/effects/sphere_config.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere_config.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,60 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_SPHERE_CONFIG_H +#define KWIN_SPHERE_CONFIG_H + +#include <kcmodule.h> + +#include "ui_sphere_config.h" + +class KFileDialog; + +namespace KWin +{ + +class SphereEffectConfigForm : public QWidget, public Ui::SphereEffectConfigForm +{ + Q_OBJECT + public: + explicit SphereEffectConfigForm(QWidget* parent); +}; + +class SphereEffectConfig : public KCModule + { + Q_OBJECT + public: + explicit SphereEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); + + public slots: + virtual void save(); + virtual void load(); + virtual void defaults(); + + private slots: + void capsSelectionChanged(); + private: + SphereEffectConfigForm* m_ui; + KActionCollection* m_actionCollection; + }; + +} // namespace + +#endif Index: effects/lookingglass_config.cpp =================================================================== --- kwin/effects/lookingglass_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/lookingglass_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -28,12 +28,9 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QWidget> #include <QGridLayout> -#include <QLabel> -#include <QComboBox> KWIN_EFFECT_CONFIG_FACTORY Index: effects/cylinder_config.desktop =================================================================== --- kwin/effects/cylinder_config.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder_config.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,26 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kcm_kwin4_effect_builtins +X-KDE-ParentComponents=kwin4_effect_cylinder +X-KDE-PluginKeyword=cylinder + +Name=Desktop Cylinder +Name[et]=Töölauasilinder +Name[gl]=Escritorio cilíndrico +Name[gu]=ડેસ્કટોપ સિલિન્ડર +Name[ja]=デスクトップシリンダー +Name[km]=ស៊ីឡាំងផ្ទៃតុ +Name[nds]=Zylinner-Schriefdisch +Name[nn]=Skrivebordsylinder +Name[pt]=Cilindro de Ecrãs +Name[pt_BR]=Cilindro de Ecrãs +Name[sl]=Valj z namizji +Name[sr]=Ваљак површи +Name[sr@latin]=Valjak površi +Name[sv]=Skrivbordscylinder +Name[te]=డెస్క్ టాప్ సిలెండర్ +Name[tr]=Masaüstü Silindiri +Name[uk]=Циліндр стільниць +Name[zh_TW]=桌面圓柱 Index: effects/sharpen_config.cpp =================================================================== --- kwin/effects/sharpen_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/sharpen_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,7 +27,6 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QVBoxLayout> #ifndef KDE_USE_FINAL Index: effects/cube_config.desktop =================================================================== --- kwin/effects/cube_config.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cube_config.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,27 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kcm_kwin4_effect_builtins +X-KDE-ParentComponents=kwin4_effect_cube +X-KDE-PluginKeyword=cube + +Name=Desktop Cube +Name[et]=Töölauakuubik +Name[ga]=Ciúb Deisce +Name[gl]=Cubo do escritorio +Name[gu]=ડેસ્કટોપ ટ્યુબ +Name[ja]=デスクトップキューブ +Name[km]=គូបផ្ទៃតុ +Name[nds]=Wörpel-Schriefdisch +Name[nn]=Skrivebordskube +Name[pt]=Cubo de Ecrãs +Name[pt_BR]=Cubo de Ecrãs +Name[sl]=Kocka z namizji +Name[sr]=Коцка површи +Name[sr@latin]=Kocka površi +Name[sv]=Skrivbordskub +Name[te]=డెస్క్ టాప్ క్యూబ్ +Name[tr]=Masaüstü Küpü +Name[uk]=Куб стільниць +Name[zh_TW]=桌面立方體 Index: effects/explosioneffect.cpp =================================================================== --- kwin/effects/explosioneffect.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/explosioneffect.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -127,7 +127,7 @@ mValid = loadData(); if( mValid ) { - mWindows[ w ] += time / 700.0; // complete change in 700ms + mWindows[ w ] += time / animationTime( 700.0 ); // complete change in 700ms if( mWindows[ w ] < 1 ) { data.setTranslucent(); Index: effects/showfps.h =================================================================== --- kwin/effects/showfps.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/showfps.h (.../work/~seli/kwin11.1) (revision 880714) @@ -34,6 +34,7 @@ { public: ShowFpsEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); Index: effects/cylinder_config.h =================================================================== --- kwin/effects/cylinder_config.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/cylinder_config.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,60 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_CYLINDER_CONFIG_H +#define KWIN_CYLINDER_CONFIG_H + +#include <kcmodule.h> + +#include "ui_cylinder_config.h" + +class KFileDialog; + +namespace KWin +{ + +class CylinderEffectConfigForm : public QWidget, public Ui::CylinderEffectConfigForm +{ + Q_OBJECT + public: + explicit CylinderEffectConfigForm(QWidget* parent); +}; + +class CylinderEffectConfig : public KCModule + { + Q_OBJECT + public: + explicit CylinderEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList()); + + public slots: + virtual void save(); + virtual void load(); + virtual void defaults(); + + private slots: + void capsSelectionChanged(); + private: + CylinderEffectConfigForm* m_ui; + KActionCollection* m_actionCollection; + }; + +} // namespace + +#endif Index: effects/desktopgrid_config.cpp =================================================================== --- kwin/effects/desktopgrid_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/desktopgrid_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,7 +27,6 @@ #include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <kconfiggroup.h> #include <QVBoxLayout> Index: effects/mousemark.h =================================================================== --- kwin/effects/mousemark.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/mousemark.h (.../work/~seli/kwin11.1) (revision 880714) @@ -33,6 +33,7 @@ Q_OBJECT public: MouseMarkEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void mouseChanged( const QPoint& pos, const QPoint& old, Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons, Index: effects/dimscreen.cpp =================================================================== --- kwin/effects/dimscreen.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/dimscreen.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -32,10 +32,10 @@ DimScreenEffect::DimScreenEffect() : mActivated( false ) - , animationDuration( 300 ) , animation( false ) , deactivate( false ) { + reconfigure( ReconfigureAll ); #ifdef KWIN_HAVE_XRENDER_COMPOSITING alphaFormat = XRenderFindStandardFormat( display(), PictStandardARGB32 ); #endif @@ -45,6 +45,11 @@ { } +void DimScreenEffect::reconfigure( ReconfigureFlags ) + { + animationDuration = Effect::animationTime( 300 ); + } + void DimScreenEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { effects->prePaintScreen( data, time ); Index: effects/wobblywindows.cpp =================================================================== --- kwin/effects/wobblywindows.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/wobblywindows.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -185,6 +185,26 @@ WobblyWindowsEffect::WobblyWindowsEffect() { + reconfigure( ReconfigureAll ); +} + +WobblyWindowsEffect::~WobblyWindowsEffect() +{ + if (!windows.empty()) + { + // we should be empty at this point... + // emit a warning and clean the list. + kDebug() << "Windows list not empty. Left items : " << windows.count(); + QHash< const EffectWindow*, WindowWobblyInfos >::iterator i; + for (i = windows.begin(); i != windows.end(); ++i) + { + freeWobblyInfo(i.value()); + } + } +} + +void WobblyWindowsEffect::reconfigure( ReconfigureFlags ) +{ KConfigGroup conf = effects->effectConfig("Wobbly"); @@ -285,20 +305,6 @@ #endif } -WobblyWindowsEffect::~WobblyWindowsEffect() -{ - if (!windows.empty()) - { - // we should be empty at this point... - // emit a warning and clean the list. - kDebug() << "Windows list not empty. Left items : " << windows.count(); - QHash< const EffectWindow*, WindowWobblyInfos >::iterator i; - for (i = windows.begin(); i != windows.end(); ++i) - { - freeWobblyInfo(i.value()); - } - } -} void WobblyWindowsEffect::setParameterSet(ParameterSet& pset) { Index: effects/sphere_config.cpp =================================================================== --- kwin/effects/sphere_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,247 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "sphere_config.h" +#include <kwineffects.h> + +#include <kconfiggroup.h> +#include <kcolorscheme.h> +#include <KActionCollection> +#include <kaction.h> +#include <KFileDialog> +#include <KImageFilePreview> + +#include <QGridLayout> +#include <QColor> +#ifndef KDE_USE_FINAL +KWIN_EFFECT_CONFIG_FACTORY +#endif + +namespace KWin +{ + +SphereEffectConfigForm::SphereEffectConfigForm(QWidget* parent) : QWidget(parent) +{ + setupUi(this); +} + +SphereEffectConfig::SphereEffectConfig(QWidget* parent, const QVariantList& args) : + KCModule(EffectFactory::componentData(), parent, args) + { + m_ui = new SphereEffectConfigForm(this); + + QGridLayout* layout = new QGridLayout(this); + + layout->addWidget(m_ui, 0, 0); + + m_ui->tabWidget->setTabText( 0, i18n("Basic") ); + m_ui->tabWidget->setTabText( 1, i18n("Advanced") ); + + m_ui->screenEdgeCombo->addItem(i18n("Top")); + m_ui->screenEdgeCombo->addItem(i18n("Top-right")); + m_ui->screenEdgeCombo->addItem(i18n("Right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-right")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom")); + m_ui->screenEdgeCombo->addItem(i18n("Bottom-left")); + m_ui->screenEdgeCombo->addItem(i18n("Left")); + m_ui->screenEdgeCombo->addItem(i18n("Top-left")); + m_ui->screenEdgeCombo->addItem(i18n("None")); + + m_actionCollection = new KActionCollection( this, componentData() ); + m_actionCollection->setConfigGroup( "Cube" ); + m_actionCollection->setConfigGlobal(true); + + KAction* a = (KAction*) m_actionCollection->addAction( "Cube" ); + a->setText( i18n("Desktop Cube" )); + a->setProperty("isConfigurationAction", true); + a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F11 )); + + m_ui->editor->addCollection(m_actionCollection); + + connect(m_ui->screenEdgeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + connect(m_ui->rotationDurationSpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeOpacitySpin, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->displayDesktopNameBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->backgroundColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->cubeCapsBox, SIGNAL(stateChanged(int)), this, SLOT(capsSelectionChanged())); + connect(m_ui->capsImageBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->capColorButton, SIGNAL(changed(QColor)), this, SLOT(changed())); + connect(m_ui->wallpaperRequester, SIGNAL(textChanged(QString)), this, SLOT(changed())); + connect(m_ui->closeOnMouseReleaseBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + connect(m_ui->zPositionSlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->capDeformationSlider, SIGNAL(valueChanged(int)), this, SLOT(changed())); + connect(m_ui->walkThroughDesktopBox, SIGNAL(stateChanged(int)), this, SLOT(changed())); + + load(); + } + +void SphereEffectConfig::load() + { + KCModule::load(); + + KConfigGroup conf = EffectsHandler::effectConfig( "Sphere" ); + + int duration = conf.readEntry( "RotationDuration", 0 ); + float opacity = conf.readEntry( "Opacity", 80 ); + bool desktopName = conf.readEntry( "DisplayDesktopName", true ); + int activateBorder = conf.readEntry( "BorderActivate", (int)ElectricNone ); + QColor background = conf.readEntry( "BackgroundColor", QColor( Qt::black ) ); + QColor capColor = conf.readEntry( "CapColor", KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + bool texturedCaps = conf.readEntry( "TexturedCaps", true ); + bool caps = conf.readEntry( "Caps", true ); + bool closeOnMouseRelease = conf.readEntry( "CloseOnMouseRelease", false ); + bool walkThroughDesktop = conf.readEntry( "TabBox", false ); + m_ui->zPositionSlider->setValue( conf.readEntry( "ZPosition", 450 ) ); + m_ui->capDeformationSlider->setValue( conf.readEntry( "CapDeformation", 0 ) ); + m_ui->wallpaperRequester->setPath( conf.readEntry( "Wallpaper", "" ) ); + if( activateBorder == (int)ElectricNone ) + activateBorder--; + m_ui->screenEdgeCombo->setCurrentIndex( activateBorder ); + + m_ui->rotationDurationSpin->setValue( duration ); + m_ui->cubeOpacitySlider->setValue( opacity ); + m_ui->cubeOpacitySpin->setValue( opacity ); + if( desktopName ) + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->displayDesktopNameBox->setCheckState( Qt::Unchecked ); + } + if( caps ) + { + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->cubeCapsBox->setCheckState( Qt::Unchecked ); + } + if( texturedCaps ) + { + m_ui->capsImageBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->capsImageBox->setCheckState( Qt::Unchecked ); + } + if( closeOnMouseRelease ) + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + } + if( walkThroughDesktop ) + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Checked ); + } + else + { + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + } + m_ui->backgroundColorButton->setColor( background ); + m_ui->capColorButton->setColor( capColor ); + capsSelectionChanged(); + + emit changed(false); + } + +void SphereEffectConfig::save() + { + KConfigGroup conf = EffectsHandler::effectConfig( "Sphere" ); + + conf.writeEntry( "RotationDuration", m_ui->rotationDurationSpin->value() ); + conf.writeEntry( "DisplayDesktopName", m_ui->displayDesktopNameBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Opacity", m_ui->cubeOpacitySpin->value() ); + conf.writeEntry( "BackgroundColor", m_ui->backgroundColorButton->color() ); + conf.writeEntry( "Caps", m_ui->cubeCapsBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CapColor", m_ui->capColorButton->color() ); + conf.writeEntry( "TexturedCaps", m_ui->capsImageBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "CloseOnMouseRelease", m_ui->closeOnMouseReleaseBox->checkState() == Qt::Checked ? true : false ); + conf.writeEntry( "Wallpaper", m_ui->wallpaperRequester->url().path() ); + conf.writeEntry( "ZPosition", m_ui->zPositionSlider->value() ); + conf.writeEntry( "CapDeformation", m_ui->capDeformationSlider->value() ); + conf.writeEntry( "TabBox", m_ui->walkThroughDesktopBox->checkState() == Qt::Checked ? true : false ); + + int activateBorder = m_ui->screenEdgeCombo->currentIndex(); + if( activateBorder == (int)ELECTRIC_COUNT ) + activateBorder = (int)ElectricNone; + conf.writeEntry( "BorderActivate", activateBorder ); + + m_ui->editor->save(); + + conf.sync(); + + emit changed(false); + EffectsHandler::sendReloadMessage( "sphere" ); + } + +void SphereEffectConfig::defaults() + { + m_ui->rotationDurationSpin->setValue( 0 ); + m_ui->displayDesktopNameBox->setCheckState( Qt::Checked ); + m_ui->cubeOpacitySpin->setValue( 80 ); + m_ui->cubeOpacitySlider->setValue( 80 ); + m_ui->screenEdgeCombo->setCurrentIndex( (int)ElectricNone -1 ); + m_ui->backgroundColorButton->setColor( QColor( Qt::black ) ); + m_ui->cubeCapsBox->setCheckState( Qt::Checked ); + m_ui->capColorButton->setColor( KColorScheme( QPalette::Active, KColorScheme::Window ).background().color() ); + m_ui->capsImageBox->setCheckState( Qt::Checked ); + m_ui->closeOnMouseReleaseBox->setCheckState( Qt::Unchecked ); + m_ui->wallpaperRequester->setPath( "" ); + m_ui->zPositionSlider->setValue( 450 ); + m_ui->capDeformationSlider->setValue( 0 ); + m_ui->walkThroughDesktopBox->setCheckState( Qt::Unchecked ); + m_ui->editor->allDefault(); + emit changed(true); + } + +void SphereEffectConfig::capsSelectionChanged() + { + if( m_ui->cubeCapsBox->checkState() == Qt::Checked ) + { + // activate cap color + m_ui->capColorButton->setEnabled( true ); + m_ui->capColorLabel->setEnabled( true ); + m_ui->capsImageBox->setEnabled( true ); + m_ui->capDeformationSlider->setEnabled( true ); + m_ui->capDeformationLabel->setEnabled( true ); + m_ui->capDeformationSphereLabel->setEnabled( true ); + m_ui->capDeformationPlaneLabel->setEnabled( true ); + } + else + { + // deactivate cap color + m_ui->capColorButton->setEnabled( false ); + m_ui->capColorLabel->setEnabled( false ); + m_ui->capsImageBox->setEnabled( false ); + m_ui->capDeformationSlider->setEnabled( false ); + m_ui->capDeformationLabel->setEnabled( false ); + m_ui->capDeformationSphereLabel->setEnabled( false ); + m_ui->capDeformationPlaneLabel->setEnabled( false ); + } + } + +} // namespace + +#include "sphere_config.moc" Index: effects/minimizeanimation.cpp =================================================================== --- kwin/effects/minimizeanimation.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/minimizeanimation.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -110,12 +110,14 @@ void MinimizeAnimationEffect::windowMinimized( EffectWindow* w ) { mTimeLineWindows[w].setCurveShape(TimeLine::EaseInCurve); + mTimeLineWindows[w].setDuration( animationTime( 250 )); mTimeLineWindows[w].setProgress(0.0f); } void MinimizeAnimationEffect::windowUnminimized( EffectWindow* w ) { mTimeLineWindows[w].setCurveShape(TimeLine::EaseOutCurve); + mTimeLineWindows[w].setDuration( animationTime( 250 )); mTimeLineWindows[w].setProgress(1.0f); } Index: effects/diminactive_config.cpp =================================================================== --- kwin/effects/diminactive_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/diminactive_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -25,15 +25,11 @@ #include <klocale.h> #include <kdebug.h> #include <kconfiggroup.h> -#include <KActionCollection> #include <kaction.h> #include <KShortcutsEditor> -#include <KGlobalAccel> #include <QWidget> #include <QGridLayout> -#include <QLabel> -#include <QComboBox> KWIN_EFFECT_CONFIG_FACTORY Index: effects/presentwindows.desktop =================================================================== --- kwin/effects/presentwindows.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/presentwindows.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -119,10 +119,10 @@ 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_presentwindows -X-KDE-PluginInfo-Version=0.1.0 +X-KDE-PluginInfo-Version=0.2.0 X-KDE-PluginInfo-Category=Appearance X-KDE-PluginInfo-Depends= X-KDE-PluginInfo-License=GPL Index: effects/desktopgrid.h =================================================================== --- kwin/effects/desktopgrid.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/desktopgrid.h (.../work/~seli/kwin11.1) (revision 880714) @@ -34,6 +34,7 @@ public: DesktopGridEffect(); ~DesktopGridEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); @@ -58,6 +59,7 @@ void paintScreenDesktop( int desktop, int mask, QRegion region, ScreenPaintData data ); void slideDesktopChanged( int old ); void setHighlightedDesktop( int desktop ); + void calcDesktopLayout(int* x, int* y, Qt::Orientation* orientation) const; bool activated; TimeLine mTimeLine; int painting_desktop; @@ -74,7 +76,7 @@ bool slide_painting_sticky; QPoint slide_painting_diff; ElectricBorder borderActivate; - + bool auto_layout; }; } // namespace Index: effects/sphere.cpp =================================================================== --- kwin/effects/sphere.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,217 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +#include "cube.h" +#include "sphere.h" + +#include <kdebug.h> +#include <KStandardDirs> +#include <kconfiggroup.h> + +#include <math.h> + +#include <GL/gl.h> + +namespace KWin +{ + +KWIN_EFFECT( sphere, SphereEffect ) +KWIN_EFFECT_SUPPORTED( sphere, SphereEffect::supported() ) + +SphereEffect::SphereEffect() + : CubeEffect() + , mInited( false ) + , mValid( true ) + , mShader( 0 ) + { + if( wallpaper ) + wallpaper->discard(); + reconfigure( ReconfigureAll ); + } + +SphereEffect::~SphereEffect() + { + delete mShader; + } + +void SphereEffect::reconfigure( ReconfigureFlags ) + { + loadConfig( "Sphere" ); + reflection = false; + animateDesktopChange = false; + KConfigGroup conf = effects->effectConfig( "Sphere" ); + zPosition = conf.readEntry( "ZPosition", 450.0 ); + capDeformationFactor = conf.readEntry( "CapDeformation", 0 )/100.0f; + bigCube = true; + } + +bool SphereEffect::supported() + { + return GLShader::fragmentShaderSupported() && + (effects->compositingType() == OpenGLCompositing); + } + +bool SphereEffect::loadData() + { + mInited = true; + QString fragmentshader = KGlobal::dirs()->findResource("data", "kwin/cylinder.frag"); + QString vertexshader = KGlobal::dirs()->findResource("data", "kwin/sphere.vert"); + if( fragmentshader.isEmpty() || vertexshader.isEmpty() ) + { + kError() << "Couldn't locate shader files" << endl; + return false; + } + + mShader = new GLShader( vertexshader, fragmentshader ); + if( !mShader->isValid() ) + { + kError() << "The shader failed to load!" << endl; + return false; + } + else + { + mShader->bind(); + mShader->setUniform( "winTexture", 0 ); + mShader->setUniform( "opacity", cubeOpacity ); + QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop()); + if( effects->numScreens() > 1 && (slide || bigCube ) ) + rect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() ); + mShader->setUniform( "width", (float)rect.width() ); + mShader->setUniform( "height", (float)rect.height() ); + mShader->unbind(); + } + return true; + } + +void SphereEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { + if( activated ) + { + if( cube_painting ) + { + if( w->isOnDesktop( painting_desktop )) + { + data.quads = data.quads.makeGrid( 40 ); + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + if( w->x() < rect.width()/2 && w->x() + w->width() > rect.width()/ 2 ) + data.quads = data.quads.splitAtX( rect.width()/2 - w->x() ); + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + else + { + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + } + } + effects->prePaintWindow( w, data, time ); + } + +void SphereEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + if( activated && cube_painting ) + { + if( mValid && !mInited ) + mValid = loadData(); + bool useShader = mValid; + if( useShader ) + { + mShader->bind(); + mShader->setUniform( "windowWidth", (float)w->width() ); + mShader->setUniform( "windowHeight", (float)w->height() ); + mShader->setUniform( "xCoord", (float)w->x() ); + mShader->setUniform( "yCoord", (float)w->y() ); + mShader->setUniform( "cubeAngle", (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f ); + data.shader = mShader; + } + CubeEffect::paintWindow( w, mask, region, data ); + if( useShader ) + { + mShader->unbind(); + } + } + else + effects->paintWindow( w, mask, region, data ); + } + +void SphereEffect::paintCap( float z, float zTexture ) + { + if( bottomCap ) + { + glPushMatrix(); + glScalef( 1.0, -1.0, 1.0 ); + } + CubeEffect::paintCap( z, zTexture ); + if( bottomCap ) + glPopMatrix(); + } + +void SphereEffect::paintCapStep( float z, float zTexture, bool texture ) + { + QRect rect = effects->clientArea( FullArea, activeScreen, painting_desktop ); + float cubeAngle = (effects->numberOfDesktops() - 2 )/(float)effects->numberOfDesktops() * 180.0f; + float radius = (rect.width()*0.5)/cos(cubeAngle*0.5*M_PI/180.0); + float angle = acos( (rect.height()*0.5)/radius )*180.0/M_PI; + angle /= 30; + if( texture ) + capTexture->bind(); + glPushMatrix(); + glTranslatef( 0.0, -rect.height()*0.5, 0.0 ); + glBegin( GL_QUADS ); + for( int i=0; i<30; i++ ) + { + float topAngle = angle*i*M_PI/180.0; + float bottomAngle = angle*(i+1)*M_PI/180.0; + float yTop = rect.height() - radius * cos( topAngle ); + yTop -= (yTop-rect.height()*0.5)*capDeformationFactor; + float yBottom = rect.height() -radius * cos( bottomAngle ); + yBottom -= (yBottom-rect.height()*0.5)*capDeformationFactor; + for( int j=0; j<36; j++ ) + { + float x = radius * sin( topAngle ) * sin( (90.0+j*10.0)*M_PI/180.0 ); + float z = radius * sin( topAngle ) * cos( (90.0+j*10.0)*M_PI/180.0 ); + if( texture ) + glTexCoord2f( x/(rect.width())+0.5, 0.5 - z/zTexture * 0.5 ); + glVertex3f( x, yTop, z ); + x = radius * sin( bottomAngle ) * sin( (90.0+j*10.0)*M_PI/180.00 ); + z = radius * sin( bottomAngle ) * cos( (90.0+j*10.0)*M_PI/180.0 ); + if( texture ) + glTexCoord2f( x/(rect.width())+0.5, 0.5 - z/zTexture * 0.5 ); + glVertex3f( x, yBottom, z ); + x = radius * sin( bottomAngle ) * sin( (90.0+(j+1)*10.0)*M_PI/180.0 ); + z = radius * sin( bottomAngle ) * cos( (90.0+(j+1)*10.0)*M_PI/180.0 ); + if( texture ) + glTexCoord2f( x/(rect.width())+0.5, 0.5 - z/zTexture * 0.5 ); + glVertex3f( x, yBottom, z ); + x = radius * sin( topAngle ) * sin( (90.0+(j+1)*10.0)*M_PI/180.0 ); + z = radius * sin( topAngle ) * cos( (90.0+(j+1)*10.0)*M_PI/180.0 ); + if( texture ) + glTexCoord2f( x/(rect.width())+0.5, 0.5 - z/zTexture * 0.5 ); + glVertex3f( x, yTop, z ); + } + } + glEnd(); + glPopMatrix(); + if( texture ) + { + capTexture->unbind(); + } + } + + +} // namespace Index: effects/data/cubecap.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: effects/data/cubecap.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: effects/data/cylinder.frag =================================================================== --- kwin/effects/data/cylinder.frag (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/data/cylinder.frag (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,15 @@ +uniform sampler2D winTexture; +uniform float windowWidth; +uniform float windowHeight; +uniform float opacity; + +vec2 pix2tex(vec2 pix) +{ + return vec2(pix.x / windowWidth, pix.y / windowHeight); +} + +void main() +{ + gl_FragColor.rgba = texture2D(winTexture, pix2tex(gl_TexCoord[0].xy)).rgba; + gl_FragColor.a *= opacity; +} Index: effects/data/cylinder.vert =================================================================== --- kwin/effects/data/cylinder.vert (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/data/cylinder.vert (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,56 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +uniform float width; +uniform float cubeAngle; +uniform float xCoord; + +void main() +{ + gl_TexCoord[0].xy = gl_Vertex.xy; + vec4 vertex = gl_Vertex.xyzw; + float radian = radians(cubeAngle*0.5); + // height of the triangle compound of one side of the cube and the two bisecting lines + float midpoint = width*0.5*tan(radian); + // radius of the circle + float radius = (width*0.5)/cos(radian); + + // the calculation does the following: + // At every x position we move on to the circle und create a new circular segment + // The distance between the new chord and the desktop (z=0) is the wanted z value + // The length of the new chord is 2*distance(x,middle of desktop(width*0.5)) + // Now we calculate the angle between chord and radius as acos(distance/radius) + // With this angle we can can calculate the height of the new triangle (radius-distance*2-radius) + // The height is the opposite leg of the triangle compound of distance-*height*-radius + // New height minus old height (midpoint) is the looked for z-value + + // distance from midpoint of desktop to x coord + float distance = width*0.5 - (vertex.x+xCoord); + if( (vertex.x+xCoord) > width*0.5 ) + { + distance = (vertex.x+xCoord) - width*0.5; + } + float angle = acos( distance/radius ); + float h = radius; + // if distance == 0 -> angle=90 -> tan(90) singularity + if( distance != 0.0 ) + h = tan( angle ) * distance; + vertex.z = h - midpoint; + gl_Position = gl_ModelViewProjectionMatrix * vertex; +} Index: effects/data/sphere.vert =================================================================== --- kwin/effects/data/sphere.vert (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/data/sphere.vert (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,40 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ +uniform float width; +uniform float height; +uniform float cubeAngle; +uniform float xCoord; +uniform float yCoord; + +void main() +{ + gl_TexCoord[0].xy = gl_Vertex.xy; + vec3 vertex = vec3( gl_Vertex.xy - vec2( width*0.5 - xCoord, height*0.5 - yCoord ), gl_Vertex.z ); + float radian = radians(cubeAngle*0.5); + float radius = (width*0.5)/cos(radian); + float zenithAngle = acos( vertex.y/radius ); + float azimuthAngle = asin( vertex.x/radius ); + vertex.z = radius * sin( zenithAngle ) * cos( azimuthAngle ) - radius*cos( radians( 90.0 - cubeAngle*0.5 ) ); + vertex.x = radius * sin( zenithAngle ) * sin( azimuthAngle ); + + vertex.xy += vec2( width*0.5 - xCoord, height*0.5 - yCoord ); + + gl_Position = gl_ModelViewProjectionMatrix * vec4( vertex, 1.0 ); +} Index: effects/CMakeLists.txt =================================================================== --- kwin/effects/CMakeLists.txt (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/CMakeLists.txt (.../work/~seli/kwin11.1) (revision 880714) @@ -85,6 +85,7 @@ maketransparent_config.cpp maketransparent_config.ui presentwindows_config.cpp + presentwindows_config.ui shadow_config.cpp showfps_config.cpp showfps_config.ui @@ -108,6 +109,8 @@ SET(kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources} blur.cpp coverswitch.cpp + cube.cpp + cylinder.cpp explosioneffect.cpp flipswitch.cpp invert.cpp @@ -115,6 +118,7 @@ magnifier.cpp mousemark.cpp sharpen.cpp + sphere.cpp snow.cpp trackmouse.cpp wobblywindows.cpp @@ -122,6 +126,8 @@ install( FILES blur.desktop coverswitch.desktop + cube.desktop + cylinder.desktop explosion.desktop flipswitch.desktop invert.desktop @@ -129,6 +135,7 @@ magnifier.desktop mousemark.desktop sharpen.desktop + sphere.desktop snow.desktop trackmouse.desktop wobblywindows.desktop @@ -153,10 +160,15 @@ data/snowflake.png data/circle.png data/circle-edgy.png + sphere.desktop DESTINATION ${DATA_INSTALL_DIR}/kwin ) SET(kwin4_effect_builtins_config_sources ${kwin4_effect_builtins_config_sources} coverswitch_config.cpp coverswitch_config.ui + cube_config.cpp + cube_config.ui + cylinder_config.cpp + cylinder_config.ui flipswitch_config.cpp flipswitch_config.ui invert_config.cpp @@ -169,12 +181,16 @@ sharpen_config.cpp snow_config.cpp snow_config.ui + sphere_config.cpp + sphere_config.ui trackmouse_config.cpp wobblywindows_config.cpp wobblywindows_config.ui ) install( FILES coverswitch_config.desktop + cube_config.desktop + cylinder_config.desktop flipswitch_config.desktop invert_config.desktop lookingglass_config.desktop @@ -182,6 +198,7 @@ mousemark_config.desktop sharpen_config.desktop snow_config.desktop + sphere_config.desktop trackmouse_config.desktop wobblywindows_config.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kwin ) Index: effects/test/demo_liquid.cpp =================================================================== --- kwin/effects/test/demo_liquid.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/test/demo_liquid.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -23,7 +23,6 @@ #include <kwinglutils.h> -#include <KStandardDirs> #include <kdebug.h> #include <assert.h> Index: effects/configs_builtins.cpp =================================================================== --- kwin/effects/configs_builtins.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/configs_builtins.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -33,6 +33,8 @@ #ifdef KWIN_HAVE_OPENGL_COMPOSITING #include "coverswitch_config.h" +#include "cube_config.h" +#include "cylinder_config.h" #include "flipswitch_config.h" #include "invert_config.h" #include "lookingglass_config.h" @@ -40,6 +42,7 @@ #include "magnifier_config.h" #include "sharpen_config.h" #include "snow_config.h" +#include "sphere_config.h" #include "trackmouse_config.h" #include "wobblywindows_config.h" #endif @@ -69,6 +72,8 @@ #define OPENGL_PLUGINS \ registerPlugin<KWin::CoverSwitchEffectConfig>("coverswitch"); \ + registerPlugin<KWin::CubeEffectConfig>("cube"); \ + registerPlugin<KWin::CylinderEffectConfig>("cylinder"); \ registerPlugin<KWin::FlipSwitchEffectConfig>("flipswitch"); \ registerPlugin<KWin::InvertEffectConfig>("invert"); \ registerPlugin<KWin::LookingGlassEffectConfig>("lookingglass"); \ @@ -76,6 +81,7 @@ registerPlugin<KWin::MagnifierEffectConfig>("magnifier"); \ registerPlugin<KWin::SharpenEffectConfig>("sharpen"); \ registerPlugin<KWin::SnowEffectConfig>("snow"); \ + registerPlugin<KWin::SphereEffectConfig>("sphere"); \ registerPlugin<KWin::TrackMouseEffectConfig>("trackmouse"); \ registerPlugin<KWin::WobblyWindowsEffectConfig> ("wobblywindows"); Index: effects/mousemark.cpp =================================================================== --- kwin/effects/mousemark.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/mousemark.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -56,12 +56,15 @@ a->setText( i18n( "Clear Last Mouse Mark" )); a->setGlobalShortcut( KShortcut( Qt::SHIFT + Qt::META + Qt::Key_F12 )); connect( a, SIGNAL( triggered( bool )), this, SLOT( clearLast())); + reconfigure( ReconfigureAll ); + arrow_start = NULL_POINT; + } +void MouseMarkEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = EffectsHandler::effectConfig("MouseMark"); width = conf.readEntry( "LineWidth", 3 ); color = conf.readEntry( "Color", QColor( Qt::red )); - - arrow_start = NULL_POINT; } void MouseMarkEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) Index: effects/fade.h =================================================================== --- kwin/effects/fade.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/fade.h (.../work/~seli/kwin11.1) (revision 880714) @@ -31,6 +31,7 @@ { public: FadeEffect(); + virtual void reconfigure( ReconfigureFlags ); 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 ); Index: effects/coverswitch.h =================================================================== --- kwin/effects/coverswitch.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/coverswitch.h (.../work/~seli/kwin11.1) (revision 880714) @@ -33,6 +33,7 @@ CoverSwitchEffect(); ~CoverSwitchEffect(); + virtual void reconfigure( ReconfigureFlags ); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); virtual void postPaintScreen(); Index: effects/dialogparent.cpp =================================================================== --- kwin/effects/dialogparent.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/dialogparent.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -28,7 +28,7 @@ void DialogParentEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) { // How long does it take for the effect to get it's full strength (in ms) - const double changeTime = 200; + const double changeTime = animationTime( 200 ); // Check if this window has a modal dialog and change the window's // effect's strength accordingly Index: effects/flipswitch.cpp =================================================================== --- kwin/effects/flipswitch.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/flipswitch.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -48,17 +48,22 @@ , startRequested( false ) , twinview( false ) { + reconfigure( ReconfigureAll ); + } + +FlipSwitchEffect::~FlipSwitchEffect() + { + } + +void FlipSwitchEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig( "FlipSwitch" ); - mFlipDuration = conf.readEntry( "FlipDuration", 200 ); + mFlipDuration = animationTime( conf, "FlipDuration", 200 ); mAnimation = conf.readEntry( "AnimateFlip", true ); timeLine.setCurveShape( TimeLine::EaseInOutCurve ); timeLine.setDuration( mFlipDuration ); } -FlipSwitchEffect::~FlipSwitchEffect() - { - } - void FlipSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if( mActivated || stopRequested || stop ) Index: effects/sphere.desktop =================================================================== --- kwin/effects/sphere.desktop (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere.desktop (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,52 @@ +[Desktop Entry] +Name=Desktop Sphere +Name[et]=Töölauasfäär +Name[ga]=Sféar Deisce +Name[gl]=Escritorio en esfera +Name[gu]=ડેસ્કટોપ ગોળો +Name[km]=ស៊្វែរផ្ទៃតុ +Name[nds]=Schriefdischkugel +Name[nn]=Skrivebordskule +Name[pt]=Esfera de Ecrãs +Name[pt_BR]=Esfera de Ecrãs +Name[sl]=Krogla z namizji +Name[sr]=Сфера површи +Name[sr@latin]=Sfera površi +Name[sv]=Skrivbordsklot +Name[te]=డెస్క్ టాప్ గొళం +Name[tr]=Masaüstü Küresi +Name[uk]=Стільнична сфера +Name[zh_TW]=桌面球體 +Icon=preferences-system-windows-effect-sphere +Comment=Map virtual desktops on a sphere +Comment[et]=Virtuaalsete töölaudade asetamine sfäärile +Comment[ga]=Taispeáin deasca fíorúla ar sféar +Comment[gl]=Mostra os escritorios virtuais nunha esfera +Comment[gu]=વર્ચ્યુઅલ ડેસ્કટોપને ગોળા સાથે જોડો +Comment[ja]=仮想デスクトップを球に位置付けます +Comment[km]=ផ្គូផ្គងផ្ទៃតុនិម្មិតនៅលើស៊្វែរ +Comment[nds]=Schriefdischen op en Kugel afbillen +Comment[nn]=Virtuelle skrivebord viste på ei kule +Comment[pt]=Mapear os ecrãs virtuais sobre uma esfera +Comment[pt_BR]=Mapear os ecrãs virtuais sobre uma esfera +Comment[sl]=Navidezna namizja preslika na kroglo +Comment[sr]=Слика виртуелне површи на сферу +Comment[sr@latin]=Slika virtuelne površi na sferu +Comment[sv]=Avbilda virtuella skrivbord på ett klot +Comment[te]=గోళంపైన వర్చ్యువల్ డెస్క్ టాప్లను మాప్చేయుము +Comment[tr]=Sanal masaüstlerini bir küre olarak göster +Comment[uk]=Відобразити віртуальні стільниці на сфері +Comment[zh_TW]=將虛擬桌面映射到一球體 + +Type=Service +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Martin Gräßlin +X-KDE-PluginInfo-Email=ubuntu@martin-graesslin.com +X-KDE-PluginInfo-Name=kwin4_effect_sphere +X-KDE-PluginInfo-Version=0.1.0 +X-KDE-PluginInfo-Category=Window Management +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +X-KDE-Library=kwin4_effect_builtins +X-KDE-Ordering=50 Index: effects/showfps_config.cpp =================================================================== --- kwin/effects/showfps_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/showfps_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -25,7 +25,6 @@ #include <klocale.h> #include <kdebug.h> -#include <QVBoxLayout> #ifndef KDE_USE_FINAL KWIN_EFFECT_CONFIG_FACTORY #endif Index: effects/desktopgrid.cpp =================================================================== --- kwin/effects/desktopgrid.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/desktopgrid.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -24,6 +24,7 @@ #include <kaction.h> #include <kactioncollection.h> +#include <kdebug.h> #include <klocale.h> #include <kconfiggroup.h> #include <netwm_def.h> @@ -41,25 +42,33 @@ , was_window_move( false ) , window_move( NULL ) , slide( false ) + , borderActivate( ElectricNone ) { KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = static_cast< KAction* >( actionCollection->addAction( "ShowDesktopGrid" )); a->setText( i18n("Show Desktop Grid" )); a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F8 )); connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle())); + reconfigure( ReconfigureAll ); + } + +DesktopGridEffect::~DesktopGridEffect() + { + effects->unreserveElectricBorder( borderActivate ); + } + +void DesktopGridEffect::reconfigure( ReconfigureFlags ) + { KConfigGroup conf = effects->effectConfig("DesktopGrid"); slideEnabled = conf.readEntry( "Slide", true ); - + effects->unreserveElectricBorder( borderActivate ); borderActivate = (ElectricBorder)conf.readEntry("BorderActivate", (int)ElectricNone); effects->reserveElectricBorder( borderActivate ); mTimeLine.setCurveShape(TimeLine::EaseInOutCurve); + mTimeLine.setDuration( animationTime( 250 )); + auto_layout = conf.readEntry( "AutoLayout", true ); } -DesktopGridEffect::~DesktopGridEffect() - { - effects->unreserveElectricBorder( borderActivate ); - } - void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time ) { if( slide ) @@ -192,7 +201,7 @@ { int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); w = x * displayWidth(); h = y * displayHeight(); // wrap around if shorter @@ -263,7 +272,7 @@ { int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); QRect desktop = desktopRect( painting_desktop, false ); data.xTranslate += window_move_pos.x() * x - ( desktop.x() + w->x()); data.yTranslate += window_move_pos.y() * y - ( desktop.y() + w->y()); @@ -288,7 +297,7 @@ { int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); --desktop; // make it start with 0 QRect rect; if( orientation == Qt::Horizontal ) @@ -324,7 +333,7 @@ { int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); if( w == window_move ) // it's being moved, return moved position return QRect( window_move_pos, QSize( w->width() / x, w->height() / y )); QRect desktop = desktopRect( w->isOnCurrentDesktop() @@ -350,7 +359,7 @@ qSwap( *begin++, *end-- ); int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); foreach( EffectWindow* w, windows ) { // don't use windowRect(), take special care of on-all-desktop windows @@ -391,7 +400,7 @@ { int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); w = x * displayWidth(); h = y * displayHeight(); // wrap around if shorter @@ -545,7 +554,7 @@ rect.translate( -desktopRect( desktop, true ).topLeft()); int x, y; Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); + calcDesktopLayout( &x, &y, &orientation ); effects->moveWindow( window_move, QPoint( rect.x() * x, rect.y() * y )); effects->windowToDesktop( window_move, desktop ); effects->setElevatedWindow( window_move, false ); @@ -644,6 +653,21 @@ return false; } +void DesktopGridEffect::calcDesktopLayout(int* x, int* y, Qt::Orientation* orientation) const + { + if( auto_layout ) + { + int numDesktops = effects->numberOfDesktops(); + *y = sqrt( numDesktops ) + 0.5; + *x = float( numDesktops ) / float( *y ) + 0.5; + if( *x * *y < numDesktops ) + (*x)++; + *orientation = Qt::Horizontal; + } + else + effects->calcDesktopLayout( x, y, orientation ); + } + } // namespace #include "desktopgrid.moc" Index: effects/coverswitch_config.ui =================================================================== --- kwin/effects/coverswitch_config.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/coverswitch_config.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -56,14 +56,17 @@ </item> <item row="4" column="1" > <widget class="QSpinBox" name="spinDuration" > + <property name="specialValueText" > + <string>Default</string> + </property> <property name="suffix" > <string> msec</string> </property> <property name="maximum" > <number>5000</number> </property> - <property name="value" > - <number>200</number> + <property name="singleStep" > + <number>10</number> </property> </widget> </item> Index: effects/coverswitch_config.cpp =================================================================== --- kwin/effects/coverswitch_config.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects/coverswitch_config.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -59,7 +59,7 @@ KConfigGroup conf = EffectsHandler::effectConfig( "CoverSwitch" ); - int duration = conf.readEntry( "Duration", 200 ); + int duration = conf.readEntry( "Duration", 0 ); bool animateSwitch = conf.readEntry( "AnimateSwitch", true ); bool animateStart = conf.readEntry( "AnimateStart", true ); bool animateStop = conf.readEntry( "AnimateStop", true ); @@ -119,7 +119,7 @@ void CoverSwitchEffectConfig::defaults() { - m_ui->spinDuration->setValue( 200 ); + m_ui->spinDuration->setValue( 0 ); m_ui->checkAnimateSwitch->setCheckState( Qt::Checked ); m_ui->checkAnimateStart->setCheckState( Qt::Checked ); m_ui->checkAnimateStop->setCheckState( Qt::Checked ); Index: effects/sphere.h =================================================================== --- kwin/effects/sphere.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/effects/sphere.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,54 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 +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 <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_SPHERE_H +#define KWIN_SPHERE_H + +#include <kwineffects.h> +#include <kwinglutils.h> + +namespace KWin +{ + +class SphereEffect + : public CubeEffect + { + public: + SphereEffect(); + ~SphereEffect(); + virtual void reconfigure( ReconfigureFlags ); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + + static bool supported(); + protected: + virtual void paintCap( float z, float zTexture ); + virtual void paintCapStep( float z, float zTexture, bool texture ); + private: + bool loadData(); + bool mInited; + bool mValid; + GLShader* mShader; + float capDeformationFactor; + }; + +} // namespace + +#endif Index: useractions.cpp =================================================================== --- kwin/useractions.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/useractions.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -227,7 +227,7 @@ } mResizeOpAction->setEnabled( active_popup_client->isResizable() ); - mMoveOpAction->setEnabled( active_popup_client->isMovable() ); + mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() ); mMaximizeOpAction->setEnabled( active_popup_client->isMaximizable() ); mMaximizeOpAction->setChecked( active_popup_client->maximizeMode() == Client::MaximizeFull ); mShadeOpAction->setEnabled( active_popup_client->isShadeable() ); @@ -614,13 +614,13 @@ workspace()->raiseClient( this ); workspace()->requestFocus( this ); workspace()->setActiveScreenMouse( globalPos ); - if( options->moveMode == Options::Transparent && isMovable()) + if( options->moveMode == Options::Transparent && isMovableAcrossScreens()) move_faked_activity = workspace()->fakeRequestedActivity( this ); // fallthrough case Options::MouseMove: case Options::MouseUnrestrictedMove: { - if (!isMovable()) + if (!isMovableAcrossScreens()) break; if( moveResizeMode ) finishMoveResize( false ); @@ -732,10 +732,10 @@ static_cast<EffectsHandlerImpl*>(effects)->unloadEffect( name ); } -void Workspace::reloadEffect( const QString& name ) +void Workspace::reconfigureEffect( const QString& name ) { if( effects ) - static_cast<EffectsHandlerImpl*>(effects)->reloadEffect( name ); + static_cast<EffectsHandlerImpl*>(effects)->reconfigureEffect( name ); } QStringList Workspace::loadedEffects() const Index: options.h =================================================================== --- kwin/options.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/options.h (.../work/~seli/kwin11.1) (revision 880714) @@ -289,6 +289,8 @@ bool useCompositing; CompositingType compositingMode; HiddenPreviews hiddenPreviews; + bool unredirectFullscreen; + bool disableCompositingChecks; uint refreshRate; // This is for OpenGL mode @@ -303,6 +305,7 @@ bool glDirect; bool glVSync; bool glStrictBinding; + double animationTimeFactor() const; private: WindowOperation OpTitlebarDblClick; @@ -331,6 +334,7 @@ bool desktop_topmenu; // List of window classes for which not to use focus stealing prevention QStringList ignoreFocusStealingClasses; + int animationSpeed; // 0 - instant, 5 - very slow MouseCommand wheelToMouseCommand( MouseWheelCommand com, int delta ); void reloadCompositingSettings(const CompositingPrefs& prefs); Index: composite.cpp =================================================================== --- kwin/composite.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/composite.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -52,10 +52,14 @@ #include "scene_xrender.h" #include "scene_opengl.h" #include "compositingprefs.h" +#include "notifications.h" #include <stdio.h> #include <QMenu> +#include <kaction.h> +#include <kactioncollection.h> +#include <klocale.h> #include <kxerrorhandler.h> #include <X11/extensions/shape.h> @@ -183,13 +187,17 @@ if( rate <= 0 ) rate = 50; // QTimer gives us 1msec (1000Hz) at best, so we ignore anything higher; - // however, additional throttling makes prevents very high rates from taking place anyway + // however, additional throttling prevents very high rates from taking place anyway else if( rate > 1000 ) rate = 1000; kDebug( 1212 ) << "Refresh rate " << rate << "Hz"; compositeRate = 1000 / rate; - compositeTimer.start( compositeRate ); lastCompositePaint.start(); + // fake a previous paint, so that the next starts right now + nextPaintReference = QTime::currentTime().addMSecs( -compositeRate ); + compositeTimer.setSingleShot( true ); + checkCompositeTimer(); + composite_paint_times.clear(); XCompositeRedirectSubwindows( display(), rootWindow(), CompositeRedirectManual ); new EffectsHandlerImpl( scene->compositingType() ); // sets also the 'effects' pointer addRepaintFull(); @@ -234,11 +242,11 @@ foreach( Deleted* c, deleted ) c->finishCompositing(); XCompositeUnredirectSubwindows( display(), rootWindow(), CompositeRedirectManual ); - compositeTimer.stop(); delete effects; effects = NULL; delete scene; scene = NULL; + compositeTimer.stop(); repaints_region = QRegion(); for( ClientList::ConstIterator it = clients.begin(); it != clients.end(); @@ -266,7 +274,17 @@ // for the shortcut void Workspace::slotToggleCompositing() { - compositingSuspended = !compositingSuspended; + suspendCompositing( !compositingSuspended ); + } + +void Workspace::suspendCompositing() + { + suspendCompositing( true ); + } + +void Workspace::suspendCompositing( bool suspend ) + { + compositingSuspended = suspend; finishCompositing(); setupCompositing(); // will do nothing if suspended } @@ -276,6 +294,7 @@ if( !compositing()) return; repaints_region += QRegion( x, y, w, h ); + checkCompositeTimer(); } void Workspace::addRepaint( const QRect& r ) @@ -283,6 +302,7 @@ if( !compositing()) return; repaints_region += r; + checkCompositeTimer(); } void Workspace::addRepaint( const QRegion& r ) @@ -290,6 +310,7 @@ if( !compositing()) return; repaints_region += r; + checkCompositeTimer(); } void Workspace::addRepaintFull() @@ -297,6 +318,7 @@ if( !compositing()) return; repaints_region = QRegion( 0, 0, displayWidth(), displayHeight()); + checkCompositeTimer(); } void Workspace::performCompositing() @@ -308,21 +330,25 @@ // them - leave at least 1msec time after one repaint is finished and next one // is started. if( lastCompositePaint.elapsed() < 1 ) + { + compositeTimer.start( 1 ); return; + } + if( !scene->waitSyncAvailable()) + nextPaintReference = QTime::currentTime(); checkCursorPos(); if(( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage || !overlay_visible ) // nothing is visible anyway { scene->idle(); - // With vsync, next repaint is scheduled dynamically at the end of this function, - // and it can have a very short timeout. If we now idle here, make sure the idling - // does not actually caused heavy load by firing the timer often too quickly. - if( compositeTimer.interval() != compositeRate ) - compositeTimer.start( compositeRate ); + // Note: It would seem here we should undo suspended unredirect, but when scenes need + // it for some reason, e.g. transformations or translucency, the next pass that does not + // need this anymore and paints normally will also reset the suspended unredirect. + // Otherwise the window would not be painted normally anyway. return; } // create a list of all windows in the stacking order - ToplevelList windows = compositingStackingOrder(); + ToplevelList windows = xStackingOrder(); foreach( EffectWindow* c, static_cast< EffectsHandlerImpl* >( effects )->elevatedWindows()) { Toplevel* t = static_cast< EffectWindowImpl* >( c )->window(); @@ -335,7 +361,7 @@ #if 0 // There is a bug somewhere that prevents this from working properly (#160393), but additionally // this cannot be used so carelessly - needs protections against broken clients, the window - // should not get focus before it's displayed and so on. + // should not get focus before it's displayed, handle unredirected windows properly and so on. foreach( Toplevel* c, tmp ) if( c->readyForPainting()) windows.append( c ); @@ -354,14 +380,24 @@ QRegion repaints = repaints_region; // clear all repaints, so that post-pass can add repaints for the next repaint repaints_region = QRegion(); + QTime t = QTime::currentTime(); scene->paint( repaints, windows ); if( scene->waitSyncAvailable()) { - // if vsync is used, schedule the next repaint slightly in advance of the next sync, - // so that there is still time for the drawing to take place - int untilNextSync = compositeRate - ( lastCompositePaint.elapsed() % compositeRate ); - compositeTimer.start( qMax( 1, untilNextSync - 10 )); // 10 ms in advance - TODO maybe less? + // If vsync is used, schedule the next repaint slightly in advance of the next sync, + // so that there is still time for the drawing to take place. We have just synced, and + // nextPaintReference is time from which multiples of compositeRate should be added, + // so set it 10ms back (meaning next paint will be in 'compositeRate - 10'). + // However, make sure the reserve is smaller than the composite rate. + int reserve = compositeRate <= 10 ? compositeRate - 1 : 10; + nextPaintReference = QTime::currentTime().addMSecs( -reserve ); } + // Trigger at least one more pass even if there would be nothing to paint, so that scene->idle() + // is called the next time. If there would be nothing pending, it will not restart the timer and + // checkCompositeTime() would restart it again somewhen later, called from functions that + // would again add something pending. + checkCompositeTimer(); + checkCompositePaintTime( t.elapsed()); lastCompositePaint.start(); #endif } @@ -383,6 +419,15 @@ return false; } +void Workspace::setCompositeTimer() + { + if( !compositing()) // should not really happen, but there may be e.g. some damage events still pending + return; + // The last paint set nextPaintReference as a reference time to which multiples of compositeRate + // should be added for the next paint. qBound() for protection; system time can change without notice. + compositeTimer.start( qBound( 0, nextPaintReference.msecsTo( QTime::currentTime() ), 250 ) % compositeRate ); + } + bool Workspace::createOverlay() { assert( overlay == None ); @@ -400,11 +445,62 @@ #endif } +void Workspace::checkCompositePaintTime( int msec ) + { + if( options->disableCompositingChecks ) + return; + composite_paint_times.prepend( msec ); + bool tooslow = false; + // If last 3 paints were way too slow, disable and warn. + // 1 second seems reasonable, it's not that difficult to get relatively high times + // with high system load. + const int MAX_LONG_PAINT = 1000; + if( composite_paint_times.count() >= 3 && composite_paint_times[ 0 ] > MAX_LONG_PAINT + && composite_paint_times[ 1 ] > MAX_LONG_PAINT && composite_paint_times[ 2 ] > MAX_LONG_PAINT ) + { + kDebug( 1212 ) << "Too long paint times, suspending"; + tooslow = true; + } + // If last 15 seconds all paints (all of them) were quite slow, disable and warn too. Quite slow being 0,1s + // should be reasonable, that's 10fps and having constant 10fps is bad. + // This may possibly trigger also when activating an expensive effect, so this may need tweaking. + const int MAX_SHORT_PAINT = 100; + const int SHORT_TIME = 15000; // 15 sec + int time = 0; + foreach( int t, composite_paint_times ) + { + if( t < MAX_SHORT_PAINT ) + break; + time += t; + if( time > SHORT_TIME ) // all paints in the given time were long + { + kDebug( 1212 ) << "Long paint times for long time, suspending"; + tooslow = true; + break; + } + } + if( composite_paint_times.count() > 1000 ) + composite_paint_times.removeLast(); + if( tooslow ) + { + QTimer::singleShot( 0, this, SLOT( suspendCompositing())); + QString shortcut = i18n( "Empty" ); + if( KAction* action = qobject_cast<KAction*>( keys->action("Suspend Compositing"))) + shortcut = action->globalShortcut().primary().toString(); + QString message = i18n( "Compositing was too slow and has been suspended.\n" + "If this was only a temporary problem, you can resume using the '%1' shortcut.\n" + "You can also disable functionality checks in advanced compositing settings.", shortcut ); + Notify::raise( Notify::CompositingSlow, message ); + compositeTimer.start( 1000 ); // so that it doesn't trigger sooner than suspendCompositing() + } + } + void Workspace::setupOverlay( Window w ) { assert( overlay != None ); assert( Extensions::shapeInputAvailable()); - XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); + overlay_shape = QRegion(); + setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight())); if( w != None ) XShapeCombineRectangles( display(), w, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); XSelectInput( display(), overlay, VisibilityChangeMask ); @@ -420,10 +516,46 @@ overlay_shown = true; } +void Workspace::hideOverlay() + { + assert( overlay != None ); + XUnmapWindow( display(), overlay ); + overlay_shown = false; + setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight())); + } + +void Workspace::setOverlayShape( const QRegion& reg ) + { + // Avoid setting the same shape again, it causes flicker (apparently it is not a no-op + // and triggers something). + if( reg == overlay_shape ) + return; + QVector< QRect > rects = reg.rects(); + XRectangle* xrects = new XRectangle[ rects.count() ]; + for( int i = 0; + i < rects.count(); + ++i ) + { + xrects[ i ].x = rects[ i ].x(); + xrects[ i ].y = rects[ i ].y(); + xrects[ i ].width = rects[ i ].width(); + xrects[ i ].height = rects[ i ].height(); + } + XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0, + xrects, rects.count(), ShapeSet, Unsorted ); + delete[] xrects; + XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); + overlay_shape = reg; + } + void Workspace::destroyOverlay() { if( overlay == None ) return; + // reset the overlay shape + XRectangle rec = { 0, 0, displayWidth(), displayHeight() }; + XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted ); + XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, &rec, 1, ShapeSet, Unsorted ); #ifdef HAVE_XCOMPOSITE_OVERLAY XCompositeReleaseOverlayWindow( display(), overlay ); #endif @@ -431,6 +563,52 @@ overlay_shown = false; } +bool Workspace::compositingActive() + { + return compositing(); + } + +// force is needed when the list of windows changes (e.g. a window goes away) +void Workspace::checkUnredirect( bool force ) + { + if( !compositing() || overlay == None || !options->unredirectFullscreen ) + return; + if( force ) + forceUnredirectCheck = true; + if( !unredirectTimer.isActive()) + unredirectTimer.start( 0 ); + } + +void Workspace::delayedCheckUnredirect() + { + if( !compositing() || overlay == None || !options->unredirectFullscreen ) + return; + ToplevelList list; + bool changed = forceUnredirectCheck; + foreach( Client* c, clients ) + list.append( c ); + foreach( Unmanaged* c, unmanaged ) + list.append( c ); + foreach( Toplevel* c, list ) + { + if( c->updateUnredirectedState()) + changed = true; + } + // no desktops, no Deleted ones + if( !changed ) + return; + forceUnredirectCheck = false; + // Cut out parts from the overlay window where unredirected windows are, + // so that they are actually visible. + QRegion reg( 0, 0, displayWidth(), displayHeight()); + foreach( Toplevel* c, list ) + { + if( c->unredirected()) + reg -= c->geometry(); + } + setOverlayShape( reg ); + } + //**************************************** // Toplevel //**************************************** @@ -446,6 +624,8 @@ damage_region = QRegion( 0, 0, width(), height()); effect_window = new EffectWindowImpl(); effect_window->setWindow( this ); + unredirect = false; + workspace()->checkUnredirect( true ); #endif } @@ -454,6 +634,7 @@ #ifdef KWIN_HAVE_COMPOSITING if( damage_handle == None ) return; + workspace()->checkUnredirect( true ); if( effect_window->window() == this ) // otherwise it's already passed to Deleted, don't free data { discardWindowPixmap(); @@ -482,6 +663,8 @@ { #ifdef KWIN_HAVE_COMPOSITING assert( compositing()); + if( unredirected()) + return None; grabXServer(); KXErrorHandler err; window_pix = XCompositeNameWindowPixmap( display(), frameId()); @@ -577,6 +760,7 @@ damage_region += r; repaints_region += r; static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), r ); + workspace()->checkCompositeTimer(); } void Toplevel::addDamageFull() @@ -586,6 +770,7 @@ damage_region = rect(); repaints_region = rect(); static_cast<EffectsHandlerImpl*>(effects)->windowDamaged( effectWindow(), rect()); + workspace()->checkCompositeTimer(); } void Toplevel::resetDamage( const QRect& r ) @@ -605,11 +790,13 @@ QRect r( x, y, w, h ); r &= rect(); repaints_region += r; + workspace()->checkCompositeTimer(); } void Toplevel::addRepaintFull() { repaints_region = rect(); + workspace()->checkCompositeTimer(); } void Toplevel::resetRepaints( const QRect& r ) @@ -632,4 +819,109 @@ workspace()->addRepaint( r ); } +bool Toplevel::updateUnredirectedState() + { + assert( compositing()); + bool should = shouldUnredirect() && !unredirectSuspend && !shape() && !hasAlpha() && opacity() == 1.0; + if( should && !unredirect ) + { + unredirect = true; + kDebug( 1212 ) << "Unredirecting:" << this; + XCompositeUnredirectWindow( display(), frameId(), CompositeRedirectManual ); + return true; + } + else if( !should && unredirect ) + { + unredirect = false; + kDebug( 1212 ) << "Redirecting:" << this; + XCompositeRedirectWindow( display(), frameId(), CompositeRedirectManual ); + discardWindowPixmap(); + return true; + } + return false; + } + +void Toplevel::suspendUnredirect( bool suspend ) + { + if( unredirectSuspend == suspend ) + return; + unredirectSuspend = suspend; + workspace()->checkUnredirect(); + } + +//**************************************** +// Client +//**************************************** + +void Client::setupCompositing() + { + Toplevel::setupCompositing(); + updateVisibility(); // for internalKeep() + } + +void Client::finishCompositing() + { + Toplevel::finishCompositing(); + updateVisibility(); + } + +bool Client::shouldUnredirect() const + { + if( isActiveFullScreen()) + { + ToplevelList stacking = workspace()->xStackingOrder(); + for( int pos = stacking.count() - 1; + pos >= 0; + --pos ) + { + Toplevel* c = stacking.at( pos ); + if( c == this ) // is not covered by any other window, ok to unredirect + return true; + if( c->geometry().intersects( geometry())) + return false; + } + abort(); + } + return false; + } + +//**************************************** +// Unmanaged +//**************************************** + +bool Unmanaged::shouldUnredirect() const + { + // the pixmap is needed for the login effect, a nicer solution would be the login effect increasing + // refcount for the window pixmap (which would prevent unredirect), avoiding this hack + if( resourceClass() == "ksplashx" || resourceClass() == "ksplashsimple" ) + return false; +// it must cover whole display or one xinerama screen, and be the topmost there + if( geometry() == workspace()->clientArea( FullArea, geometry().center(), workspace()->currentDesktop()) + || geometry() == workspace()->clientArea( ScreenArea, geometry().center(), workspace()->currentDesktop())) + { + ToplevelList stacking = workspace()->xStackingOrder(); + for( int pos = stacking.count() - 1; + pos >= 0; + --pos ) + { + Toplevel* c = stacking.at( pos ); + if( c == this ) // is not covered by any other window, ok to unredirect + return true; + if( c->geometry().intersects( geometry())) + return false; + } + abort(); + } + return false; + } + +//**************************************** +// Deleted +//**************************************** + +bool Deleted::shouldUnredirect() const + { + return false; + } + } // namespace Index: scene.h =================================================================== --- kwin/scene.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene.h (.../work/~seli/kwin11.1) (revision 880714) @@ -107,6 +107,7 @@ void finalDrawWindow( EffectWindowImpl* w, int mask, QRegion region, WindowPaintData& data ); // compute time since the last repaint void updateTimeDiff(); + QList< QPoint > selfCheckPoints() const; // saved data for 2nd pass of optimized screen painting struct Phase2Data { @@ -182,6 +183,7 @@ void updateToplevel( Toplevel* c ); // creates initial quad list for the window virtual WindowQuadList buildQuads() const; + void suspendUnredirect( bool suspend ); protected: WindowQuadList makeQuads( WindowQuadType type, const QRegion& reg ) const; Toplevel* toplevel; @@ -256,6 +258,12 @@ toplevel = c; } +inline +void Scene::Window::suspendUnredirect( bool suspend ) + { + toplevel->suspendUnredirect( suspend ); + } + } // namespace #endif Index: workspace.h =================================================================== --- kwin/workspace.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/workspace.h (.../work/~seli/kwin11.1) (revision 880714) @@ -137,7 +137,7 @@ void updateClientLayer( Client* c ); void raiseOrLowerClient( Client * ); void restoreSessionStackingOrder( Client* c ); - void reconfigure(); + void updateStackingOrder( bool propagate_new_clients = false ); void forceRestacking(); void clientHidden( Client* ); @@ -194,10 +194,10 @@ * at the last position */ const ClientList& stackingOrder() const; - + ToplevelList xStackingOrder() const; ClientList ensureStackingOrder( const ClientList& clients ) const; - Client* topClientOnDesktop( int desktop, bool unconstrained = false, bool only_normal = true ) const; + Client* topClientOnDesktop( int desktop, int screen, bool unconstrained = false, bool only_normal = true ) const; Client* findDesktop( bool topmost, int desktop ) const; void sendClientToDesktop( Client* c, int desktop, bool dont_activate ); void windowToPreviousDesktop( Client* c ); @@ -209,8 +209,7 @@ void loadEffect( const QString& name ); void toggleEffect( const QString& name ); - void reloadEffect( const QString& name ); - + void reconfigureEffect( const QString& name ); void unloadEffect( const QString& name ); QStringList loadedEffects() const; @@ -252,6 +251,9 @@ void nextDesktop(); void previousDesktop(); void circulateDesktopApplications(); + bool compositingActive(); + bool waitForCompositingSetup(); + void setCurrentScreen( int new_screen ); QString desktopName( int desk ) const; @@ -324,9 +326,13 @@ // init overlay and the destination window in it void setupOverlay( Window window ); void showOverlay(); + void hideOverlay(); // hides and resets overlay window + void setOverlayShape( const QRegion& reg ); // destroys XComposite overlay window void destroyOverlay(); Window overlayWindow(); + void checkUnredirect( bool force = false ); + void checkCompositeTimer(); public slots: void addRepaintFull(); @@ -451,6 +457,7 @@ void slotSettingsChanged( int category ); + void reconfigure(); void slotReconfigure(); void slotReinitCompositing(); @@ -464,6 +471,8 @@ void slotToggleCompositing(); void updateClientArea(); + void suspendCompositing(); + void suspendCompositing( bool suspend ); private slots: void desktopPopupAboutToShow(); @@ -487,6 +496,7 @@ void lostCMSelection(); void updateElectricBorders(); void resetCursorPosTime(); + void delayedCheckUnredirect(); protected: bool keyPressMouseEmulation( XKeyEvent& ev ); @@ -514,8 +524,6 @@ bool establishTabBoxGrab(); void removeTabBoxGrab(); - void updateStackingOrder( bool propagate_new_clients = false ); - ToplevelList compositingStackingOrder() const; void propagateClients( bool propagate_new_clients ); // called only from updateStackingOrder ClientList constrainedStackingOrder(); void raiseClientWithinApplication( Client* c ); @@ -569,6 +577,8 @@ void finishCompositing(); bool windowRepaintsPending() const; + void setCompositeTimer(); + void checkCompositePaintTime( int msec ); int current_desktop; int number_of_desktops; @@ -610,6 +620,8 @@ ClientList unconstrained_stacking_order; // topmost last ClientList stacking_order; // topmost last bool force_restacking; + mutable ToplevelList x_stacking; // from XQueryTree() + mutable bool x_stacking_dirty; QVector< ClientList > focus_chain; // currently ative last ClientList global_focus_chain; // this one is only for things like tabbox's MRU ClientList should_get_focus; // last is most recent @@ -728,13 +740,18 @@ bool compositingSuspended; QTimer compositeTimer; QTime lastCompositePaint; + QTime nextPaintReference; int compositeRate; QRegion repaints_region; Window overlay; // XComposite overlay window bool overlay_visible; bool overlay_shown; // for showOverlay() + QRegion overlay_shape; QSlider *transSlider; QPushButton *transButton; + QTimer unredirectTimer; + bool forceUnredirectCheck; + QList< int > composite_paint_times; private: friend bool performTransiencyCheck(); @@ -957,6 +974,13 @@ return findClient( ClientMatchPredicate( c )); } +inline +void Workspace::checkCompositeTimer() + { + if( !compositeTimer.isActive()) + setCompositeTimer(); + } + } // namespace #endif Index: events.cpp =================================================================== --- kwin/events.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/events.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -279,6 +279,10 @@ return true; } break; + case ConfigureNotify: + if( e->xconfigure.event == rootWindow()) + x_stacking_dirty = true; + break; }; if( Client* c = findClient( WindowMatchPredicate( e->xany.window ))) @@ -484,6 +488,7 @@ addRepaintFull(); QTimer::singleShot( 2000, this, SLOT( addRepaintFull())); } + checkCompositeTimer(); } break; default: @@ -750,29 +755,17 @@ } if( isTopMenu() && workspace()->managingTopMenus()) return true; // kwin controls these - switch ( mappingState() ) + // also copied in clientMessage() + if( isMinimized()) + unminimize(); + if( isShade()) + setShade( ShadeNone ); + if( !isOnCurrentDesktop()) { - case WithdrawnState: - assert( false ); // WMs are not supposed to manage clients in Withdrawn state, -// manage(); // after initial mapping manage() is called from createClient() - break; - case IconicState: - // also copied in clientMessage() - if( isMinimized()) - unminimize(); - if( isShade()) - setShade( ShadeNone ); - if( !isOnCurrentDesktop()) - { - if( workspace()->allowClientActivation( this )) - workspace()->activateClient( this ); - else - demandAttention(); - } - break; - case NormalState: - // TODO fake MapNotify? - break; + if( workspace()->allowClientActivation( this )) + workspace()->activateClient( this ); + else + demandAttention(); } return true; } @@ -792,25 +785,7 @@ if( ignore ) return; } - switch( mappingState()) - { - case IconicState: - releaseWindow(); - return; - case NormalState: - // maybe we will be destroyed soon. Check this first. - XEvent ev; - if( XCheckTypedWindowEvent (display(), window(), - DestroyNotify, &ev) ) // TODO I don't like this much - { - destroyClient(); // deletes this - return; - } - releaseWindow(); - break; - default: - assert( false ); - } + releaseWindow(); } void Client::destroyNotifyEvent( XDestroyWindowEvent* e ) @@ -974,7 +949,8 @@ if ( options->autoRaise && !isDesktop() && !isDock() && !isTopMenu() && workspace()->focusChangeEnabled() && - workspace()->topClientOnDesktop( workspace()->currentDesktop()) != this ) + workspace()->topClientOnDesktop( workspace()->currentDesktop(), + options->separateScreenFocus ? screen() : -1 ) != this ) { delete autoRaiseTimer; autoRaiseTimer = new QTimer( this ); @@ -1093,7 +1069,7 @@ { XUngrabButton( display(), AnyButton, AnyModifier, wrapperId()); // keep grab for the simple click without modifiers if needed (see below) - bool not_obscured = workspace()->topClientOnDesktop( workspace()->currentDesktop(), true, false ) == this; + bool not_obscured = workspace()->topClientOnDesktop( workspace()->currentDesktop(), -1, true, false ) == this; if( !( !options->clickRaise || not_obscured )) grabButton( None ); return; @@ -1109,7 +1085,7 @@ // is unobscured or if the user doesn't want click raise // (it is unobscured if it the topmost in the unconstrained stacking order, i.e. it is // the most recently raised window) - bool not_obscured = workspace()->topClientOnDesktop( workspace()->currentDesktop(), true, false ) == this; + bool not_obscured = workspace()->topClientOnDesktop( workspace()->currentDesktop(), -1, true, false ) == this; if( !options->clickRaise || not_obscured ) ungrabButton( None ); else @@ -1706,6 +1682,7 @@ addWorkspaceRepaint( geometry()); // damage old area QRect old = geom; geom = newgeom; + addRepaintFull(); if( old.size() != geom.size()) discardWindowPixmap(); if( scene != NULL ) Index: utils.h =================================================================== --- kwin/utils.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/utils.h (.../work/~seli/kwin11.1) (revision 880714) @@ -145,12 +145,19 @@ ShadeActivated // "shaded", but visible due to alt+tab to the window }; -enum HiddenPreviews // whether to keep all windows mapped when compositing - { // do not reorder (config file) - HiddenPreviewsNever, // don't keep pixmaps of unmapped windows at all -/**/ HiddenPreviewsKeep, // only keep pixmaps, but unmap windows -/**/ HiddenPreviewUpdate, // unmap, keep, but when needed map back and wait - HiddenPreviewsActive // keep windows mapped +// Whether to keep all windows mapped when compositing (i.e. whether to have +// actively updated window pixmaps). +enum HiddenPreviews + { + // The normal mode with regard to mapped windows. Hidden (minimized, etc.) + // and windows on inactive virtual desktops are not mapped, their pixmaps + // are only their icons. + HiddenPreviewsNever, + // Like normal mode, but shown windows (i.e. on inactive virtual desktops) + // are kept mapped, only hidden windows are unmapped. + HiddenPreviewsShown, + // All windows are kept mapped regardless of their state. + HiddenPreviewsAlways }; // compile with XShape older than 1.0 Index: scene_opengl.h =================================================================== --- kwin/scene_opengl.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene_opengl.h (.../work/~seli/kwin11.1) (revision 880714) @@ -64,15 +64,16 @@ bool initDrawableConfigs(); void waitSync(); void flushBuffer( int mask, QRegion damage ); + bool selfCheck(); GC gcroot; class FBConfigInfo - { + { public: GLXFBConfig fbconfig; int bind_texture_format; int y_inverted; int mipmap; - }; + }; Drawable buffer; GLXFBConfig fbcbuffer; static bool db; Index: deleted.h =================================================================== --- kwin/deleted.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/deleted.h (.../work/~seli/kwin11.1) (revision 880714) @@ -41,6 +41,7 @@ virtual QSize clientSize() const; protected: virtual void debug( kdbgstream& stream ) const; + virtual bool shouldUnredirect() const; private: Deleted( Workspace *ws ); // use create() void copyToDeleted( Toplevel* c ); Index: kcmkwin/kwincompositing/main.ui =================================================================== --- kwin/kcmkwin/kwincompositing/main.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/main.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -38,8 +38,8 @@ <property name="title" > <string>Common Effects</string> </property> - <layout class="QVBoxLayout" > - <item> + <layout class="QGridLayout" name="gridLayout" > + <item row="0" column="0" colspan="2" > <widget class="QCheckBox" name="effectWinManagement" > <property name="text" > <string>Improved window management</string> @@ -49,7 +49,7 @@ </property> </widget> </item> - <item> + <item row="1" column="0" colspan="2" > <widget class="QCheckBox" name="effectShadows" > <property name="text" > <string>Shadows</string> @@ -59,7 +59,7 @@ </property> </widget> </item> - <item> + <item row="2" column="0" colspan="2" > <widget class="QCheckBox" name="effectAnimations" > <property name="text" > <string>Various animations</string> @@ -69,13 +69,88 @@ </property> </widget> </item> - <item> + <item row="3" column="0" > + <widget class="QLabel" name="label_3" > + <property name="text" > + <string>Effect for window switching</string> + </property> + <property name="buddy" > + <cstring>windowSwitchingCombo</cstring> + </property> + </widget> + </item> + <item row="3" column="1" > + <widget class="QComboBox" name="windowSwitchingCombo" /> + </item> + <item row="4" column="0" > + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Effect for desktop switching</string> + </property> + <property name="buddy" > + <cstring>desktopSwitchingCombo</cstring> + </property> + </widget> + </item> + <item row="4" column="1" > + <widget class="QComboBox" name="desktopSwitchingCombo" /> + </item> + <item row="6" column="0" colspan="2" > <widget class="QLabel" name="label" > <property name="text" > <string>You can find more effects in the 'All Effects' tab</string> </property> </widget> </item> + <item row="5" column="1" > + <widget class="QComboBox" name="animationSpeedCombo" > + <property name="currentIndex" > + <number>3</number> + </property> + <item> + <property name="text" > + <string>Instant</string> + </property> + </item> + <item> + <property name="text" > + <string>Very fast</string> + </property> + </item> + <item> + <property name="text" > + <string>Fast</string> + </property> + </item> + <item> + <property name="text" > + <string>Normal</string> + </property> + </item> + <item> + <property name="text" > + <string>Slow</string> + </property> + </item> + <item> + <property name="text" > + <string>Very slow</string> + </property> + </item> + <item> + <property name="text" > + <string>Extremely slow</string> + </property> + </item> + </widget> + </item> + <item row="5" column="0" > + <widget class="QLabel" name="label_5" > + <property name="text" > + <string>Animation speed</string> + </property> + </widget> + </item> </layout> </widget> </item> Index: kcmkwin/kwincompositing/advanced.ui =================================================================== --- kwin/kcmkwin/kwincompositing/advanced.ui (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/advanced.ui (.../work/~seli/kwin11.1) (revision 880714) @@ -6,10 +6,10 @@ <x>0</x> <y>0</y> <width>400</width> - <height>305</height> + <height>322</height> </rect> </property> - <layout class="QVBoxLayout" > + <layout class="QVBoxLayout" name="verticalLayout" > <item> <layout class="QHBoxLayout" > <item> @@ -36,9 +36,43 @@ </layout> </item> <item> - <widget class="QCheckBox" name="updateThumbnails" > + <layout class="QHBoxLayout" name="horizontalLayout" > + <item> + <widget class="QLabel" name="label_4" > + <property name="text" > + <string>Keep window thumbnails</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="windowThumbnails" > + <item> + <property name="text" > + <string>Always</string> + </property> + </item> + <item> + <property name="text" > + <string>Only for shown windows</string> + </property> + </item> + <item> + <property name="text" > + <string>Never</string> + </property> + </item> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="disableChecks" > + <property name="whatsThis" > + <string>Enabling this option allows compositing to be activated even if some of the internal checks fail. Doing so may make the whole desktop unusable and its use is not recommened. Use only if KWin refuses to activate compositing on a system that should be capable of compositing. +</string> + </property> <property name="text" > - <string>Keep thumbnails of hidden windows up to date</string> + <string>Disable functionality checks</string> </property> </widget> </item> @@ -146,7 +180,7 @@ <property name="orientation" > <enum>Qt::Vertical</enum> </property> - <property name="sizeHint" > + <property name="sizeHint" stdset="0" > <size> <width>382</width> <height>101</height> Index: kcmkwin/kwincompositing/interface_util.h =================================================================== --- kwin/kcmkwin/kwincompositing/interface_util.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/kcmkwin/kwincompositing/interface_util.h (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,26 @@ +/* This file is part of the KDE libraries + Copyright (C) 2008 Laurent Montel <montel@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INTERFACEUTIL_H +#define INTERFACEUTIL_H + + +// needed by the DBUS interface +Q_DECLARE_METATYPE(QList<int>) +#endif Index: kcmkwin/kwincompositing/main.cpp =================================================================== --- kwin/kcmkwin/kwincompositing/main.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/main.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -21,11 +21,13 @@ #include "main.h" #include "advanced.h" +#include "kwin_interface.h" #include <kaboutdata.h> #include <kconfig.h> #include <kconfiggroup.h> #include <kdebug.h> +#include <kmessagebox.h> #include <ksettings/dispatcher.h> #include <kpluginselector.h> #include <kservicetypetrader.h> @@ -87,6 +89,10 @@ connect(ui.effectSelector, SIGNAL(configCommitted(const QByteArray&)), this, SLOT(reparseConfiguration(const QByteArray&))); + connect(ui.windowSwitchingCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + connect(ui.desktopSwitchingCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + connect(ui.animationSpeedCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); + // Open the temporary config file // Temporary conf file is used to syncronize effect checkboxes with effect // selector by loading/saving effects from/to temp config when active tab @@ -122,6 +128,41 @@ 0, KLocalizedString(), KAboutData::License_GPL, ki18n("(c) 2007 Rivo Laks")); about->addAuthor(ki18n("Rivo Laks"), KLocalizedString(), "rivolaks@hot.ee"); setAboutData(about); + + // search the effect names + KServiceTypeTrader* trader = KServiceTypeTrader::self(); + KService::List services; + QString boxswitch, presentwindows, coverswitch, flipswitch, slide, cube; + // window switcher + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_boxswitch'"); + if( !services.isEmpty() ) + boxswitch = services.first()->name(); + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_presentwindows'"); + if( !services.isEmpty() ) + presentwindows = services.first()->name(); + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_coverswitch'"); + if( !services.isEmpty() ) + coverswitch = services.first()->name(); + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_flipswitch'"); + if( !services.isEmpty() ) + flipswitch = services.first()->name(); + // desktop switcher + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_desktopgrid'"); + if( !services.isEmpty() ) + slide = services.first()->name(); + services = trader->query("KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_cube'"); + if( !services.isEmpty() ) + cube = services.first()->name(); + // init the combo boxes + ui.windowSwitchingCombo->addItem(i18n("No Effect")); + ui.windowSwitchingCombo->addItem(boxswitch); + ui.windowSwitchingCombo->addItem(presentwindows); + ui.windowSwitchingCombo->addItem(coverswitch); + ui.windowSwitchingCombo->addItem(flipswitch); + + ui.desktopSwitchingCombo->addItem(i18n("No Effect")); + ui.desktopSwitchingCombo->addItem(slide); + ui.desktopSwitchingCombo->addItem(cube); } KWinCompositingConfig::~KWinCompositingConfig() @@ -148,9 +189,27 @@ void KWinCompositingConfig::showConfirmDialog() { - ConfirmDialog confirm; - if(!confirm.exec()) + bool revert = false; + // Feel free to extend this to support several kwin instances (multihead) if you + // think it makes sense. + OrgKdeKWinInterface kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus()); + if( !kwin.waitForCompositingSetup().value()) { + KMessageBox::sorry( this, i18n( + "Failed to activate desktop effects using the given " + "configuration options. Settings will be reverted to their previous values.\n\n" + "Check your X configuration. You may also consider changing advanced options, " + "especially changing the compositing type." )); + revert = true; + } + else + { + ConfirmDialog confirm; + if( !confirm.exec()) + revert = true; + } + if( revert ) + { // Revert settings KConfigGroup config(mKWinConfig, "Compositing"); config.deleteGroup(); @@ -201,16 +260,15 @@ { KConfigGroup config(mKWinConfig, "Compositing"); ui.useCompositing->setChecked(config.readEntry("Enabled", mDefaultPrefs.enableCompositing())); + ui.animationSpeedCombo->setCurrentIndex(config.readEntry("AnimationSpeed", 3 )); // Load effect settings KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define LOAD_EFFECT_CONFIG(effectname) effectconfig.readEntry("kwin4_effect_" effectname "Enabled", true) int winManagementEnabled = LOAD_EFFECT_CONFIG("presentwindows") - + LOAD_EFFECT_CONFIG("boxswitch") + LOAD_EFFECT_CONFIG("desktopgrid") - + LOAD_EFFECT_CONFIG("dialogparent") - + LOAD_EFFECT_CONFIG("trackmouse"); - if (winManagementEnabled > 0 && winManagementEnabled < 5) { + + LOAD_EFFECT_CONFIG("dialogparent"); + if (winManagementEnabled > 0 && winManagementEnabled < 3) { ui.effectWinManagement->setTristate(true); ui.effectWinManagement->setCheckState(Qt::PartiallyChecked); } @@ -219,8 +277,38 @@ ui.effectShadows->setChecked(LOAD_EFFECT_CONFIG("shadow")); ui.effectAnimations->setChecked(LOAD_EFFECT_CONFIG("minimizeanimation")); #undef LOAD_EFFECT_CONFIG + + // window switching + if( effectEnabled( "boxswitch", effectconfig )) + ui.windowSwitchingCombo->setCurrentIndex( 1 ); + if( effectEnabled( "coverswitch", effectconfig )) + ui.windowSwitchingCombo->setCurrentIndex( 3 ); + if( effectEnabled( "flipswitch", effectconfig )) + ui.windowSwitchingCombo->setCurrentIndex( 4 ); + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); + if( effectEnabled( "presentwindows", effectconfig ) && presentwindowsconfig.readEntry("TabBox", false) ) + ui.windowSwitchingCombo->setCurrentIndex( 2 ); + + // desktop switching + KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid"); + if( effectEnabled( "desktopgrid", effectconfig ) && gridconfig.readEntry("Slide",true)) + ui.desktopSwitchingCombo->setCurrentIndex( 1 ); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); + if( effectEnabled( "cube", effectconfig ) && cubeconfig.readEntry("AnimateDesktopChange", false)) + ui.desktopSwitchingCombo->setCurrentIndex( 2 ); + } +bool KWinCompositingConfig::effectEnabled( const QString& effect, const KConfigGroup& cfg ) const +{ + KService::List services = KServiceTypeTrader::self()->query( + "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_" + effect + "'"); + if( services.isEmpty()) + return false; + QVariant v = services.first()->property("X-KDE-PluginInfo-EnabledByDefault"); + return cfg.readEntry("kwin4_effect_" + effect + "Enabled", v.toBool()); +} + void KWinCompositingConfig::loadEffectsTab() { ui.effectSelector->load(); @@ -260,22 +348,85 @@ } config.writeEntry("Enabled", ui.useCompositing->isChecked()); + config.writeEntry("AnimationSpeed", ui.animationSpeedCombo->currentIndex()); // Save effects KConfigGroup effectconfig(mTmpConfig, "Plugins"); #define WRITE_EFFECT_CONFIG(effectname, widget) effectconfig.writeEntry("kwin4_effect_" effectname "Enabled", widget->isChecked()) if (ui.effectWinManagement->checkState() != Qt::PartiallyChecked) { WRITE_EFFECT_CONFIG("presentwindows", ui.effectWinManagement); - WRITE_EFFECT_CONFIG("boxswitch", ui.effectWinManagement); WRITE_EFFECT_CONFIG("desktopgrid", ui.effectWinManagement); WRITE_EFFECT_CONFIG("dialogparent", ui.effectWinManagement); - WRITE_EFFECT_CONFIG("trackmouse", ui.effectWinManagement); } WRITE_EFFECT_CONFIG("shadow", ui.effectShadows); // TODO: maybe also do some effect-specific configuration here, e.g. // enable/disable desktopgrid's animation according to this setting WRITE_EFFECT_CONFIG("minimizeanimation", ui.effectAnimations); #undef WRITE_EFFECT_CONFIG + + int windowSwitcher = ui.windowSwitchingCombo->currentIndex(); + bool presentWindowSwitching = false; + switch( windowSwitcher ) + { + case 0: + // no effect + effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", false); + break; + case 1: + // box switch + effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", true); + effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", false); + break; + case 2: + // present windows + presentWindowSwitching = true; + effectconfig.writeEntry("kwin4_effect_presentwindowsEnabled", true); + effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", false); + break; + case 3: + // coverswitch + effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", true); + effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", false); + break; + case 4: + // flipswitch + effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", false); + effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", true); + break; + } + KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows"); + presentwindowsconfig.writeEntry("TabBox", presentWindowSwitching); + + int desktopSwitcher = ui.desktopSwitchingCombo->currentIndex(); + bool cubeDesktopSwitching = false; + bool slide = false; + switch( desktopSwitcher ) + { + case 0: + // no effect + break; + case 1: + // slide + slide = true; + effectconfig.writeEntry("kwin4_effect_desktopgridEnabled", true); + break; + case 2: + // cube + cubeDesktopSwitching = true; + effectconfig.writeEntry("kwin4_effect_cubeEnabled", true); + break; + } + KConfigGroup gridconfig(mKWinConfig, "Effect-DesktopGrid"); + gridconfig.writeEntry("Slide",slide); + KConfigGroup cubeconfig(mKWinConfig, "Effect-Cube"); + cubeconfig.writeEntry("AnimateDesktopChange", cubeDesktopSwitching); } void KWinCompositingConfig::saveEffectsTab() @@ -339,6 +490,10 @@ ui.effectShadows->setChecked(true); ui.effectAnimations->setChecked(true); + ui.windowSwitchingCombo->setCurrentIndex( 1 ); + ui.desktopSwitchingCombo->setCurrentIndex( 1 ); + ui.animationSpeedCombo->setCurrentIndex( 3 ); + ui.effectSelector->defaults(); } Index: kcmkwin/kwincompositing/advanced.cpp =================================================================== --- kwin/kcmkwin/kwincompositing/advanced.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/advanced.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -23,9 +23,11 @@ #include <klocale.h> #include <QtDBus/QtDBus> +#include <kmessagebox.h> #include "compositingprefs.h" #include "main.h" +#include "kwin_interface.h" namespace KWin { @@ -47,7 +49,8 @@ connect(ui.compositingType, SIGNAL(currentIndexChanged(int)), this, SLOT(compositingModeChanged())); connect(ui.compositingType, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); - connect(ui.updateThumbnails, SIGNAL(toggled(bool)), this, SLOT(changed())); + connect(ui.windowThumbnails, SIGNAL(activated(int)), this, SLOT(changed())); + connect(ui.disableChecks, SIGNAL(toggled(bool)), this, SLOT(changed())); connect(ui.glMode, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); connect(ui.glTextureFilter, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); connect(ui.glDirect, SIGNAL(toggled(bool)), this, SLOT(changed())); @@ -80,9 +83,27 @@ void KWinAdvancedCompositingOptions::showConfirmDialog() { - ConfirmDialog confirm; - if(!confirm.exec()) + bool revert = false; + // Feel free to extend this to support several kwin instances (multihead) if you + // think it makes sense. + OrgKdeKWinInterface kwin("org.kde.kwin", "/KWin", QDBusConnection::sessionBus()); + if( !kwin.compositingActive().value()) { + KMessageBox::sorry( this, i18n( + "Failed to activate desktop effects using the given " + "configuration options. Settings will be reverted to their previous values.\n\n" + "Check your X configuration. You may also consider changing advanced options, " + "especially changing the compositing type." )); + revert = true; + } + else + { + ConfirmDialog confirm; + if( !confirm.exec()) + revert = true; + } + if( revert ) + { // Revert settings KConfigGroup config(mKWinConfig, "Compositing"); config.deleteGroup(); @@ -104,7 +125,15 @@ KConfigGroup config(mKWinConfig, "Compositing"); QString backend = config.readEntry("Backend", "OpenGL"); ui.compositingType->setCurrentIndex((backend == "XRender") ? 1 : 0); - ui.updateThumbnails->setChecked(config.readEntry("HiddenPreviews", 0) == 3); + // 4 - off, 5 - shown, 6 - always, other are old values + int hps = config.readEntry("HiddenPreviews", 5); + if( hps == 6 ) // always + ui.windowThumbnails->setCurrentIndex( 0 ); + else if( hps == 4 ) // never + ui.windowThumbnails->setCurrentIndex( 2 ); + else // shown, or default + ui.windowThumbnails->setCurrentIndex( 1 ); + ui.disableChecks->setChecked( config.readEntry( "DisableChecks", false )); QString glMode = config.readEntry("GLMode", "TFP"); ui.glMode->setCurrentIndex((glMode == "TFP") ? 0 : ((glMode == "SHM") ? 1 : 2)); @@ -126,10 +155,24 @@ KConfigGroup config(mKWinConfig, "Compositing"); mPreviousConfig = config.entryMap(); + bool showConfirm = false; + QString glModes[] = { "TFP", "SHM", "Fallback" }; + + if( config.readEntry("Backend", "OpenGL") + != ((ui.compositingType->currentIndex() == 0) ? "OpenGL" : "XRender") + || config.readEntry("GLMode", "TFP") != glModes[ui.glMode->currentIndex()] + || config.readEntry("GLDirect", mDefaultPrefs->enableDirectRendering()) + != ui.glDirect->isChecked() + || config.readEntry("GLVSync", mDefaultPrefs->enableVSync()) != ui.glVSync->isChecked() + || config.readEntry("DisableChecks", false ) != ui.disableChecks->isChecked()) + { + showConfirm = true; + } config.writeEntry("Backend", (ui.compositingType->currentIndex() == 0) ? "OpenGL" : "XRender"); - config.writeEntry("HiddenPreviews", ui.updateThumbnails->isChecked() ? 3 : 0); - QString glModes[] = { "TFP", "SHM", "Fallback" }; + static const int hps[] = { 6 /*always*/, 5 /*shown*/, 4 /*never*/ }; + config.writeEntry("HiddenPreviews", hps[ ui.windowThumbnails->currentIndex() ] ); + config.writeEntry("DisableChecks", ui.disableChecks->isChecked()); config.writeEntry("GLMode", glModes[ui.glMode->currentIndex()]); config.writeEntry("GLTextureFilter", ui.glTextureFilter->currentIndex()); @@ -141,7 +184,8 @@ enableButtonApply(false); reinitKWinCompositing(); - showConfirmDialog(); + if( showConfirm ) + showConfirmDialog(); } void KWinAdvancedCompositingOptions::reinitKWinCompositing() @@ -149,6 +193,8 @@ // Send signal to kwin mKWinConfig->sync(); // Send signal to all kwin instances + // If this ever changes to using the 'reconfigure' DBUS call, change the compositingActive() + // check above. QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reinitCompositing"); QDBusConnection::sessionBus().send(message); } Index: kcmkwin/kwincompositing/main.h =================================================================== --- kwin/kcmkwin/kwincompositing/main.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/main.h (.../work/~seli/kwin11.1) (revision 880714) @@ -72,6 +72,8 @@ void initEffectSelector(); private: + bool effectEnabled( const QString& effect, const KConfigGroup& cfg ) const; + KSharedConfigPtr mKWinConfig; Ui::KWinCompositingConfig ui; CompositingPrefs mDefaultPrefs; Index: kcmkwin/kwincompositing/CMakeLists.txt =================================================================== --- kwin/kcmkwin/kwincompositing/CMakeLists.txt (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kcmkwin/kwincompositing/CMakeLists.txt (.../work/~seli/kwin11.1) (revision 880714) @@ -10,6 +10,9 @@ ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/lib/kwinglobals.cpp ) kde4_add_ui_files(kcm_kwincompositing_PART_SRCS advanced.ui main.ui) +set(kwin_xml ${KDEBASE_WORKSPACE_SOURCE_DIR}/kwin/org.kde.KWin.xml) +set_source_files_properties(${kwin_xml} PROPERTIES INCLUDE "interface_util.h") +QT4_ADD_DBUS_INTERFACE(kcm_kwincompositing_PART_SRCS ${kwin_xml} kwin_interface) kde4_add_plugin(kcm_kwincompositing ${kcm_kwincompositing_PART_SRCS}) target_link_libraries(kcm_kwincompositing ${KDE4_KUTILS_LIBS} ${KDE4_KDEUI_LIBS} ${X11_LIBRARIES}) install(TARGETS kcm_kwincompositing DESTINATION ${PLUGIN_INSTALL_DIR} ) Index: toplevel.cpp =================================================================== --- kwin/toplevel.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/toplevel.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -43,6 +43,8 @@ , is_shape( false ) , effect_window( NULL ) , wmClientLeaderWin( 0 ) + , unredirect( false ) + , unredirectSuspend( false ) { } Index: options.cpp =================================================================== --- kwin/options.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/options.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -210,6 +210,7 @@ compositingMode = XRenderCompositing; else compositingMode = OpenGLCompositing; + disableCompositingChecks = config.readEntry("DisableChecks", false); QString glmode = config.readEntry("GLMode", "TFP" ).toUpper(); if( glmode == "TFP" ) glMode = GLTFP; @@ -224,8 +225,21 @@ xrenderSmoothScale = config.readEntry("XRenderSmoothScale", false ); - const HiddenPreviews hps[] = { HiddenPreviewsNever, HiddenPreviewsKeep, HiddenPreviewUpdate, HiddenPreviewsActive }; - hiddenPreviews = hps[ qBound( 0, config.readEntry( "HiddenPreviews", 0 ), 3 ) ]; + hiddenPreviews = HiddenPreviewsShown; + // 4 - off, 5 - shown, 6 - always, other are old values + int hps = config.readEntry( "HiddenPreviews", 5 ); + if( hps == 4 ) + hiddenPreviews = HiddenPreviewsNever; + else if( hps == 5 ) + hiddenPreviews = HiddenPreviewsShown; + else if( hps == 6 ) + hiddenPreviews = HiddenPreviewsAlways; + + unredirectFullscreen = config.readEntry( "UnredirectFullscreen", true ); + animationSpeed = qBound( 0, config.readEntry( "AnimationSpeed", 3 ), 6 ); + + if( !disableCompositingChecks && !prefs.validateSetup( compositingMode )) + useCompositing = false; } @@ -346,4 +360,10 @@ return mode == Opaque ? "Opaque" : "Transparent"; } +double Options::animationTimeFactor() const + { + const double factors[] = { 0, 0.2, 0.5, 1, 2, 4, 20 }; + return factors[ animationSpeed ]; + } + } // namespace Index: scene.cpp =================================================================== --- kwin/scene.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -77,6 +77,8 @@ #include "deleted.h" #include "effects.h" +#include <qdesktopwidget.h> + namespace KWin { @@ -116,7 +118,7 @@ *mask &= ~PAINT_SCREEN_REGION; *region = infiniteRegion(); } - else if( *mask & PAINT_SCREEN_REGION ) + else if( *mask & PAINT_SCREEN_REGION ) { // make sure not to go outside visible screen *region &= QRegion( 0, 0, displayWidth(), displayHeight()); } @@ -198,6 +200,9 @@ if( !w->isPaintingEnabled()) continue; phase2.append( Phase2Data( w, infiniteRegion(), data.clip, data.mask, data.quads )); + // transformations require window pixmap + w->suspendUnredirect( data.mask + & ( PAINT_WINDOW_TRANSLUCENT | PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED )); } foreach( const Phase2Data &d, phase2 ) @@ -212,6 +217,7 @@ // TODO PAINT_WINDOW_* flags don't belong here, that's why it's in the assert, // perhaps the two enums should be separated assert(( orig_mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED + | PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_OPAQUE )) == 0 ); QHash< Window*, Phase2Data > phase2data; // Draw each opaque window top to bottom, subtracting the bounding rect of @@ -233,13 +239,20 @@ foreach( const WindowQuad &q, data.quads ) if( q.isTransformed()) kFatal( 1212 ) << "Pre-paint calls are not allowed to transform quads!" ; + if( data.mask & PAINT_WINDOW_TRANSFORMED ) + kFatal( 1212 ) << "PAINT_WINDOW_TRANSFORMED without PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS!"; #endif if( !w->isPaintingEnabled()) + { + w->suspendUnredirect( true ); continue; + } if( data.paint != region ) // prepaint added area to draw painted_region |= data.paint; // make sure it makes it to the screen // Schedule the window for painting phase2data[w] = Phase2Data( w, data.paint, data.clip, data.mask, data.quads ); + // no transformations, but translucency requires window pixmap + w->suspendUnredirect( data.mask & PAINT_WINDOW_TRANSLUCENT ); } // Do the actual painting // First opaque windows, top to bottom @@ -307,6 +320,21 @@ w->sceneWindow()->performPaint( mask, region, data ); } +QList< QPoint > Scene::selfCheckPoints() const + { + QList< QPoint > ret; + // Use QDesktopWidget directly, we're interested in "real" screens, not depending on our config. + for( int screen = 0; + screen < qApp->desktop()->numScreens(); + ++screen ) + { // test top-left and bottom-right of every screen + ret.append( qApp->desktop()->screenGeometry( screen ).topLeft()); + ret.append( qApp->desktop()->screenGeometry( screen ).bottomRight() + QPoint( -5 + 1, -1 + 1 ) + + QPoint( -1, 0 )); // intentionally moved one up, since the source windows will be one down + } + return ret; + } + //**************************************** // Scene::Window //**************************************** Index: compositingprefs.h =================================================================== --- kwin/compositingprefs.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/compositingprefs.h (.../work/~seli/kwin11.1) (revision 880714) @@ -25,6 +25,7 @@ #include <QStringList> #include "kwinglutils.h" +#include "kwinglobals.h" namespace KWin @@ -52,6 +53,7 @@ static bool compositingPossible(); static QString compositingNotPossibleReason(); + bool validateSetup( CompositingType compositingType ) const; bool enableCompositing() const; bool enableVSync() const { return mEnableVSync; } bool enableDirectRendering() const { return mEnableDirectRendering; } Index: scene_opengl.cpp =================================================================== --- kwin/scene_opengl.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene_opengl.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -84,6 +84,10 @@ #ifdef KWIN_HAVE_OPENGL_COMPOSITING +#include <X11/extensions/Xcomposite.h> + +#include <qpainter.h> + namespace KWin { @@ -159,15 +163,28 @@ // OpenGL scene setup glMatrixMode( GL_PROJECTION ); glLoadIdentity(); + float fovy = 60.0f; + float aspect = 1.0f; + float zNear = 0.1f; + float zFar = 100.0f; + float ymax = zNear * tan( fovy * M_PI / 360.0f ); + float ymin = -ymax; + float xmin = ymin * aspect; + float xmax = ymax * aspect; // swap top and bottom to have OpenGL coordinate system match X system - glOrtho( 0, displayWidth(), displayHeight(), 0, 0, 65535 ); + glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); + float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; + glTranslatef( xmin*scaleFactor, ymax*scaleFactor, -1.1 ); + glScalef( (xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001 ); if( checkGLError( "Init" )) { kError( 1212 ) << "OpenGL compositing setup failed"; return; // error } + if( !selfCheck()) + return; kDebug( 1212 ) << "DB:" << db << ", TFP:" << tfp_mode << ", SHM:" << shm_mode << ", Direct:" << bool( glXIsDirect( display(), ctxbuffer )) << endl; init_ok = true; @@ -604,6 +621,88 @@ return true; } +// Test if compositing actually _really_ works, by creating a texture from a testing +// window, drawing it on the screen, reading the contents back and comparing. This +// should test whether compositing really works. +// It would be still nice to check somehow if compositing is not awfully slow. +bool SceneOpenGL::selfCheck() + { + QImage img( 5, 1, QImage::Format_RGB32 ); + img.setPixel( 0, 0, QColor( Qt::red ).rgb()); + img.setPixel( 1, 0, QColor( Qt::green ).rgb()); + img.setPixel( 2, 0, QColor( Qt::blue ).rgb()); + img.setPixel( 3, 0, QColor( Qt::white ).rgb()); + img.setPixel( 4, 0, QColor( Qt::black ).rgb()); + QPixmap pix = QPixmap::fromImage( img ); + QList< QPoint > points = selfCheckPoints(); + QRegion reg; + foreach( const QPoint& p, points ) + reg |= QRect( p, pix.size()); + if( wspace->overlayWindow()) + { // avoid covering the whole screen too soon + wspace->setOverlayShape( reg ); + wspace->showOverlay(); + } + foreach( const QPoint& p, points ) + { + XSetWindowAttributes wa; + wa.override_redirect = True; + ::Window window = XCreateWindow( display(), rootWindow(), 0, 0, 5, 1, 0, QX11Info::appDepth(), + CopyFromParent, CopyFromParent, CWOverrideRedirect, &wa ); + XSetWindowBackgroundPixmap( display(), window, pix.handle()); + XClearWindow( display(), window ); + XMapWindow( display(), window ); + // move the window one down to where the result will be rendered too, just in case + // the render would fail completely and eventual check would try to read this window's contents + XMoveWindow( display(), window, p.x() + 1, p.y()); + XCompositeRedirectWindow( display(), window, CompositeRedirectManual ); + Pixmap wpix = XCompositeNameWindowPixmap( display(), window ); + glXWaitX(); + Texture texture; + texture.load( wpix, QSize( 5, 1 ), QX11Info::appDepth()); + texture.bind(); + QRect rect( p.x(), p.y(), 5, 1 ); + texture.render( infiniteRegion(), rect ); + texture.unbind(); + glXWaitGL(); + XFreePixmap( display(), wpix ); + XDestroyWindow( display(), window ); + } + flushBuffer( PAINT_SCREEN_REGION, reg ); + glXWaitGL(); + bool ok = true; + foreach( const QPoint& p, points ) + { + QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 5, 1 ); + QImage img = pix.toImage(); +// kdDebug() << "P:" << QColor( img.pixel( 0, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 1, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 2, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 3, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 4, 0 )).name(); + if( img.pixel( 0, 0 ) != QColor( Qt::red ).rgb() + || img.pixel( 1, 0 ) != QColor( Qt::green ).rgb() + || img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb() + || img.pixel( 3, 0 ) != QColor( Qt::white ).rgb() + || img.pixel( 4, 0 ) != QColor( Qt::black ).rgb()) + { + kError( 1212 ) << "Compositing self-check failed, disabling compositing."; + ok = false; + break; + } + } + if( wspace->overlayWindow()) + wspace->hideOverlay(); + if( ok ) + kDebug( 1212 ) << "Compositing self-check passed."; + if( !ok && options->disableCompositingChecks ) + { + kWarning( 1212 ) << "Compositing checks disabled, proceeding regardless of self-check failure."; + return true; + } + return ok; + } + // the entry function for painting void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels ) { @@ -625,6 +724,8 @@ #endif glPopMatrix(); ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync + if( wspace->overlayWindow()) // show the window only after the first pass, since + wspace->showOverlay(); // that pass may take long flushBuffer( mask, damage ); // do cleanup stacking_order.clear(); @@ -647,8 +748,6 @@ // actually paint to the screen (double-buffer swap or copy from pixmap buffer) void SceneOpenGL::flushBuffer( int mask, QRegion damage ) { - if( wspace->overlayWindow()) // show the window only after the first pass, since - wspace->showOverlay(); // that pass may take long if( db ) { if( mask & PAINT_SCREEN_REGION ) @@ -715,8 +814,30 @@ if( mask & PAINT_SCREEN_TRANSFORMED ) { // apply screen transformations glPushMatrix(); - glTranslatef( data.xTranslate, data.yTranslate, 0 ); - glScalef( data.xScale, data.yScale, 1 ); + glTranslatef( data.xTranslate, data.yTranslate, data.zTranslate ); + if( data.rotation ) + { + // translate to rotation point, rotate, translate back + glTranslatef( data.rotation->xRotationPoint, data.rotation->yRotationPoint, data.rotation->zRotationPoint ); + float xAxis = 0.0; + float yAxis = 0.0; + float zAxis = 0.0; + switch( data.rotation->axis ) + { + case RotationData::XAxis: + xAxis = 1.0; + break; + case RotationData::YAxis: + yAxis = 1.0; + break; + case RotationData::ZAxis: + zAxis = 1.0; + break; + } + glRotatef( data.rotation->angle, xAxis, yAxis, zAxis ); + glTranslatef( -data.rotation->xRotationPoint, -data.rotation->yRotationPoint, -data.rotation->zRotationPoint ); + } + glScalef( data.xScale, data.yScale, data.zScale ); } Scene::paintGenericScreen( mask, data ); if( mask & PAINT_SCREEN_TRANSFORMED ) @@ -882,7 +1003,7 @@ mScale.setHeight( 1.0f ); break; default: - assert( false ); + abort(); } } @@ -1244,14 +1365,37 @@ // do required transformations int x = toplevel->x(); int y = toplevel->y(); + double z = 0.0; if( mask & PAINT_WINDOW_TRANSFORMED ) { x += data.xTranslate; y += data.yTranslate; + z += data.zTranslate; } - glTranslatef( x, y, 0 ); - if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 )) - glScalef( data.xScale, data.yScale, 1 ); + glTranslatef( x, y, z ); + if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 || data.zScale != 1 )) + glScalef( data.xScale, data.yScale, data.zScale ); + if(( mask & PAINT_WINDOW_TRANSFORMED ) && data.rotation ) + { + glTranslatef( data.rotation->xRotationPoint, data.rotation->yRotationPoint, data.rotation->zRotationPoint ); + float xAxis = 0.0; + float yAxis = 0.0; + float zAxis = 0.0; + switch( data.rotation->axis ) + { + case RotationData::XAxis: + xAxis = 1.0; + break; + case RotationData::YAxis: + yAxis = 1.0; + break; + case RotationData::ZAxis: + zAxis = 1.0; + break; + } + glRotatef( data.rotation->angle, xAxis, yAxis, zAxis ); + glTranslatef( -data.rotation->xRotationPoint, -data.rotation->yRotationPoint, -data.rotation->zRotationPoint ); + } region.translate( toplevel->x(), toplevel->y() ); // Back to screen coords texture.bind(); Index: COMPOSITE_TODO =================================================================== --- kwin/COMPOSITE_TODO (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/COMPOSITE_TODO (.../work/~seli/kwin11.1) (revision 880714) @@ -40,8 +40,6 @@ / handling of window pixmaps for unmapped windows [Seli] - config option? - - switching virtual desktops can be slow because of this as well, maybe HiddenPreviews - option should consider this (and be renamed to something more suitable) - shm mode needs support for more data formats than GL_BGRA @@ -154,7 +152,9 @@ in window's pre-paint - see the transformedShape() comment - and currently seems to be generally broken ++ implement self-check (SceneOpenGL::selfCheckSetup() etc.) also for XRender, possibly share some code + Effects framework TODO ============================== @@ -188,6 +188,9 @@ Effects TODO =============================== +! add reloadConfig() to effects + - currently changing the global animation speed in the kcm does not change effect + + minimize/shade effects - to replace the ones from KWin core / - minimizing Index: BRANCH =================================================================== --- kwin/BRANCH (.../KDE/4.1/kdebase/workspace/kwin) (revision 0) +++ kwin/BRANCH (.../work/~seli/kwin11.1) (revision 880714) @@ -0,0 +1,7 @@ +last sync: r879707 + +taskbar thumbnails? - needs plasma + - r832980, r840301 +shortcuts? + - r837779 +r841974 ? (argb + plasma) Index: notifications.h =================================================================== --- kwin/notifications.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/notifications.h (.../work/~seli/kwin11.1) (revision 880714) @@ -22,6 +22,7 @@ #ifndef KWIN_NOTIFICATIONS_H #define KWIN_NOTIFICATIONS_H +#include <knotification.h> #include <stdlib.h> #include <QString> #include <QList> @@ -57,18 +58,19 @@ ResizeEnd, DemandAttentionCurrent, DemandAttentionOther, + CompositingSlow, DesktopChange = 100 }; static bool raise( Event, const QString& message = QString(), Client* c = NULL ); static void sendPendingEvents(); private: - static QString eventToName( Event ); struct EventData { QString event; QString message; long window; + KNotification::NotificationFlags flags; }; static QList< EventData > pending_events; }; Index: client.cpp =================================================================== --- kwin/client.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/client.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -121,7 +121,7 @@ { // set the initial mapping state - mapping_state = WithdrawnState; + mapping_state = Withdrawn; desk = 0; // no desktop yet mode = PositionCenter; @@ -149,8 +149,6 @@ urgency = false; ignore_focus_stealing = false; demands_attention = false; - hidden_preview = false; - raw_shown = false; check_active_modal = false; Pdeletewindow = 0; @@ -225,7 +223,7 @@ // grab X during the release to make removing of properties, setting to withdrawn state // and repareting to root an atomic operation (http://lists.kde.org/?l=kde-devel&m=116448102901184&w=2) grabXServer(); - setMappingState( WithdrawnState ); + exportMappingState( WithdrawnState ); setModal( false ); // otherwise its mainwindow wouldn't get focus hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags) if( !on_shutdown ) @@ -441,7 +439,7 @@ noborder = false; break; default: - assert( false ); + abort(); } // NET::Override is some strange beast without clear definition, usually // just meaning "noborder", so let's treat it only as such flag, and ignore it as @@ -536,7 +534,7 @@ void Client::updateInputShape() { - if( hidden_preview ) // sets it to none, don't change + if( hiddenPreview()) // sets it to none, don't change return; if( Extensions::shapeInputAvailable()) { // There appears to be no way to find out if a window has input @@ -829,68 +827,58 @@ { if( deleting ) return; - bool show = true; if( hidden ) { - setMappingState( IconicState ); info->setState( NET::Hidden, NET::Hidden ); setSkipTaskbar( true, false ); // also hide from taskbar - rawHide(); - show = false; + if( compositing() && options->hiddenPreviews == HiddenPreviewsAlways ) + internalKeep( Allowed ); + else + internalHide( Allowed ); + return; } - else - { - setSkipTaskbar( original_skip_taskbar, false ); - } + setSkipTaskbar( original_skip_taskbar, false ); // reset from 'hidden' if( minimized ) { - setMappingState( IconicState ); info->setState( NET::Hidden, NET::Hidden ); - rawHide(); - show = false; + if( compositing() && options->hiddenPreviews == HiddenPreviewsAlways ) + internalKeep( Allowed ); + else + internalHide( Allowed ); + return; } - if( show ) - info->setState( 0, NET::Hidden ); + info->setState( 0, NET::Hidden ); if( !isOnCurrentDesktop()) { - setMappingState( IconicState ); - rawHide(); - show = false; - } - if( show ) - { - bool belongs_to_desktop = false; - for( ClientList::ConstIterator it = group()->members().begin(); - it != group()->members().end(); - ++it ) - if( (*it)->isDesktop()) - { - belongs_to_desktop = true; - break; - } - if( !belongs_to_desktop && workspace()->showingDesktop()) - workspace()->resetShowingDesktop( true ); - if( isShade()) - setMappingState( IconicState ); + if( compositing() && options->hiddenPreviews != HiddenPreviewsNever ) + internalKeep( Allowed ); else - setMappingState( NormalState ); - rawShow(); + internalHide( Allowed ); + return; } + bool belongs_to_desktop = false; + for( ClientList::ConstIterator it = group()->members().begin(); + it != group()->members().end(); + ++it ) + if( (*it)->isDesktop()) + { + belongs_to_desktop = true; + break; + } + if( !belongs_to_desktop && workspace()->showingDesktop()) + workspace()->resetShowingDesktop( true ); + internalShow( Allowed ); } /*! Sets the client window's mapping state. Possible values are WithdrawnState, IconicState, NormalState. */ -void Client::setMappingState(int s) +void Client::exportMappingState(int s) { assert( client != None ); assert( !deleting || s == WithdrawnState ); - if( mapping_state == s ) - return; - bool was_unmanaged = ( mapping_state == WithdrawnState ); - mapping_state = s; - if( mapping_state == WithdrawnState ) + if( s == WithdrawnState ) { XDeleteProperty( display(), window(), atoms->wm_state ); return; @@ -902,20 +890,63 @@ data[1] = (unsigned long) None; XChangeProperty(display(), window(), atoms->wm_state, atoms->wm_state, 32, PropModeReplace, (unsigned char *)data, 2); + } - if( was_unmanaged ) // manage() did block_geometry_updates = 1, now it's ok to finally set the geometry - blockGeometryUpdates( false ); +void Client::internalShow( allowed_t ) + { + if( mapping_state == Mapped ) + return; + MappingState old = mapping_state; + mapping_state = Mapped; + if( old == Unmapped || old == Withdrawn ) + map( Allowed ); + if( old == Kept ) + updateHiddenPreview(); + workspace()->checkUnredirect(); } +void Client::internalHide( allowed_t ) + { + if( mapping_state == Unmapped ) + return; + MappingState old = mapping_state; + mapping_state = Unmapped; + if( old == Mapped || old == Kept ) + unmap( Allowed ); + if( old == Kept ) + updateHiddenPreview(); + addWorkspaceRepaint( geometry()); + workspace()->clientHidden( this ); + workspace()->checkUnredirect(); + } + +void Client::internalKeep( allowed_t ) + { + assert( compositing()); + if( mapping_state == Kept ) + return; + MappingState old = mapping_state; + mapping_state = Kept; + if( old == Unmapped || old == Withdrawn ) + map( Allowed ); + updateHiddenPreview(); + addWorkspaceRepaint( geometry()); + workspace()->clientHidden( this ); + workspace()->checkUnredirect(); + } + /*! - Reimplemented to map the managed window in the window wrapper. - Proper mapping state should be set before showing the client. + Maps (shows) the client. Note that it is mapping state of the frame, + not necessarily the client window itself (i.e. a shaded window is here + considered mapped, even though it is in IconicState). */ -void Client::rawShow() +void Client::map( allowed_t ) { - if( raw_shown ) // this flag is used to purely avoid repeated calls to rawShow(), - return; // it doesn't say anything more about the state - raw_shown = true; + // XComposite invalidates backing pixmaps on unmap (minimize, different + // virtual desktop, etc.). We kept the last known good pixmap around + // for use in effects, but now we want to have access to the new pixmap + if( compositing() ) + discardWindowPixmap(); if( decoration != NULL ) decoration->widget()->show(); // not really necessary, but let it know the state XMapWindow( display(), frameId()); @@ -923,67 +954,31 @@ { XMapWindow( display(), wrapper ); XMapWindow( display(), client ); + exportMappingState( NormalState ); } - if( options->hiddenPreviews == HiddenPreviewsNever ) - { - // XComposite invalidates backing pixmaps on unmap (minimize, different - // virtual desktop, etc.). We kept the last known good pixmap around - // for use in effects, but now we want to have access to the new pixmap - if( compositing() ) - discardWindowPixmap(); - } else - { - if( hidden_preview ) - setHiddenPreview( false, Allowed ); - } + exportMappingState( IconicState ); } /*! - Reimplemented to unmap the managed window in the window wrapper. - Also informs the workspace. - Proper mapping state should be set before hiding the client. + Unmaps the client. Again, this is about the frame. */ -void Client::rawHide() +void Client::unmap( allowed_t ) { - if( !raw_shown ) - return; - raw_shown = false; - StackingUpdatesBlocker blocker( workspace()); - addWorkspaceRepaint( geometry()); - if( options->hiddenPreviews == HiddenPreviewsNever ) - { - // Here it may look like a race condition, as some other client might try to unmap - // the window between these two XSelectInput() calls. However, they're supposed to - // use XWithdrawWindow(), which also sends a synthetic event to the root window, - // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify - // will be missed is also very minimal, so I don't think it's needed to grab the server - // here. - XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify - XUnmapWindow( display(), frameId()); - XUnmapWindow( display(), wrapper ); - XUnmapWindow( display(), client ); - XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); - if( decoration != NULL ) - decoration->widget()->hide(); // not really necessary, but let it know the state - } - else - { - if( !hidden_preview ) - { - setHiddenPreview( true, Allowed ); - // actually keep the window mapped (taken from rawShow()) - if( decoration != NULL ) - decoration->widget()->show(); // not really necessary, but let it know the state - XMapWindow( display(), frameId()); - if( !isShade()) - { - XMapWindow( display(), wrapper ); - XMapWindow( display(), client ); - } - } - } - workspace()->clientHidden( this ); + // Here it may look like a race condition, as some other client might try to unmap + // the window between these two XSelectInput() calls. However, they're supposed to + // use XWithdrawWindow(), which also sends a synthetic event to the root window, + // which won't be missed, so this shouldn't be a problem. The chance the real UnmapNotify + // will be missed is also very minimal, so I don't think it's needed to grab the server + // here. + XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify + XUnmapWindow( display(), frameId()); + XUnmapWindow( display(), wrapper ); + XUnmapWindow( display(), client ); + XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); + if( decoration != NULL ) + decoration->widget()->hide(); // not really necessary, but let it know the state + exportMappingState( IconicState ); } // XComposite doesn't keep window pixmaps of unmapped windows, which means @@ -995,18 +990,16 @@ // then it's hoped that there will be some other desktop above it *shrug*. // Using normal shape would be better, but that'd affect other things, e.g. painting // of the actual preview. -void Client::setHiddenPreview( bool set, allowed_t ) +void Client::updateHiddenPreview() { - if( set && !hidden_preview ) - { // set - hidden_preview = true; + if( hiddenPreview()) + { workspace()->forceRestacking(); if( Extensions::shapeInputAvailable()) XShapeCombineRectangles( display(), frameId(), ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); } - else if( !set && hidden_preview ) - { // unset - hidden_preview = false; + else + { workspace()->forceRestacking(); updateInputShape(); } Index: kwin.notifyrc =================================================================== --- kwin/kwin.notifyrc (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/kwin.notifyrc (.../work/~seli/kwin11.1) (revision 880714) @@ -5461,3 +5461,7 @@ Comment[zh_CN]=未激活的虚拟桌面上的窗口请求注意 Comment[zh_TW]=在其他虛擬桌面上的視窗要求注意 +[Event/compositingslow] +Name=Compositing Performance Is Slow +Comment=The compositing performance was too slow and compositing has been suspended +Action=Popup Index: scene_xrender.cpp =================================================================== --- kwin/scene_xrender.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene_xrender.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -47,6 +47,8 @@ #include "effects.h" #include "kwinxrenderutils.h" +#include <X11/extensions/Xcomposite.h> + #include <kxerrorhandler.h> namespace KWin @@ -124,9 +126,14 @@ front = XRenderCreatePicture( display(), rootWindow(), format, CPSubwindowMode, &pa ); } createBuffer(); - init_ok = !xerr.error( true ); - if( !init_ok ) + if( xerr.error( true )) + { kError( 1212 ) << "XRender compositing setup failed"; + return; + } + if( !selfCheck()) + return; + init_ok = true; } SceneXrender::~SceneXrender() @@ -159,6 +166,84 @@ XFreePixmap( display(), pixmap ); // The picture owns the pixmap now } +// Just like SceneOpenGL::selfCheck() +bool SceneXrender::selfCheck() + { + QImage img( 5, 1, QImage::Format_RGB32 ); + img.setPixel( 0, 0, QColor( Qt::red ).rgb()); + img.setPixel( 1, 0, QColor( Qt::green ).rgb()); + img.setPixel( 2, 0, QColor( Qt::blue ).rgb()); + img.setPixel( 3, 0, QColor( Qt::white ).rgb()); + img.setPixel( 4, 0, QColor( Qt::black ).rgb()); + QPixmap pix = QPixmap::fromImage( img ); + QList< QPoint > points = selfCheckPoints(); + QRegion reg; + foreach( const QPoint& p, points ) + reg |= QRect( p, pix.size()); + if( wspace->overlayWindow()) + { // avoid covering the whole screen too soon + wspace->setOverlayShape( reg ); + wspace->showOverlay(); + } + foreach( const QPoint& p, points ) + { + XSetWindowAttributes wa; + wa.override_redirect = True; + ::Window window = XCreateWindow( display(), rootWindow(), 0, 0, 5, 1, 0, QX11Info::appDepth(), + CopyFromParent, CopyFromParent, CWOverrideRedirect, &wa ); + XSetWindowBackgroundPixmap( display(), window, pix.handle()); + XClearWindow( display(), window ); + XMapWindow( display(), window ); + // move the window one down to where the result will be rendered too, just in case + // the render would fail completely and eventual check would try to read this window's contents + XMoveWindow( display(), window, p.x() + 1, p.y()); + XCompositeRedirectWindow( display(), window, CompositeRedirectManual ); + Pixmap wpix = XCompositeNameWindowPixmap( display(), window ); + XWindowAttributes attrs; + XGetWindowAttributes( display(), window, &attrs ); + XRenderPictFormat* format = XRenderFindVisualFormat( display(), attrs.visual ); + Picture pic = XRenderCreatePicture( display(), wpix, format, 0, 0 ); + QRect rect( p.x(), p.y(), 5, 1 ); + XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0, + rect.x(), rect.y(), rect.width(), rect.height()); + XFreePixmap( display(), wpix ); + XDestroyWindow( display(), window ); + } + flushBuffer( PAINT_SCREEN_REGION, reg ); + bool ok = true; + foreach( const QPoint& p, points ) + { + QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 5, 1 ); + QImage img = pix.toImage(); +// kdDebug() << "P:" << QColor( img.pixel( 0, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 1, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 2, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 3, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 4, 0 )).name(); + if( img.pixel( 0, 0 ) != QColor( Qt::red ).rgb() + || img.pixel( 1, 0 ) != QColor( Qt::green ).rgb() + || img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb() + || img.pixel( 3, 0 ) != QColor( Qt::white ).rgb() + || img.pixel( 4, 0 ) != QColor( Qt::black ).rgb()) + { + kError( 1212 ) << "Compositing self-check failed, disabling compositing."; + ok = false; + break; + } + } + if( wspace->overlayWindow()) + wspace->hideOverlay(); + if( ok ) + kDebug( 1212 ) << "Compositing self-check passed."; + if( !ok && options->disableCompositingChecks ) + { + kWarning( 1212 ) << "Compositing checks disabled, proceeding regardless of self-check failure."; + return true; + } + return ok; + } + + // the entry point for painting void SceneXrender::paint( QRegion damage, ToplevelList toplevels ) { @@ -171,6 +256,13 @@ paintScreen( &mask, &damage ); if( wspace->overlayWindow()) // show the window only after the first pass, since wspace->showOverlay(); // that pass may take long + flushBuffer( mask, damage ); + // do cleanup + stacking_order.clear(); + } + +void SceneXrender::flushBuffer( int mask, QRegion damage ) + { if( mask & PAINT_SCREEN_REGION ) { // Use the damage region as the clip region for the root window @@ -189,8 +281,6 @@ XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight()); XFlush( display()); } - // do cleanup - stacking_order.clear(); } void SceneXrender::paintGenericScreen( int mask, ScreenPaintData data ) @@ -261,6 +351,8 @@ // The window can clip by its opaque parts the windows below. region -= w->transformedShape(); } + // translucency or window transformed require window pixmap + w->suspendUnredirect( data.mask & ( PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED )); } if( !( orig_mask & PAINT_SCREEN_BACKGROUND_FIRST )) paintBackground( region ); // Fill any areas of the root window not covered by windows Index: compositingprefs.cpp =================================================================== --- kwin/compositingprefs.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/compositingprefs.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -46,7 +46,6 @@ bool CompositingPrefs::enableCompositing() const { - return false; // disabled by default, for the time being, until support becomes better return mEnableCompositing; } @@ -108,6 +107,28 @@ #endif } +// This function checks selected compositing setup and returns false if it should not +// be used even if explicitly configured (unless checks are overriden). +// More checks like broken XRender setups etc. should be added here. +bool CompositingPrefs::validateSetup( CompositingType compositingType ) const + { + switch( compositingType ) + { + case NoCompositing: + return false; + case OpenGLCompositing: + if( mDriver == "software" ) + { + kDebug( 1212 ) << "Software GL renderer detected, forcing compositing off."; + return false; + } + return true; // allow + case XRenderCompositing: + return true; // xrender - always allow? + } + abort(); + } + void CompositingPrefs::detect() { if( !compositingPossible()) @@ -219,18 +240,34 @@ kDebug( 1212 ) << "GL version is" << mGLVersion; kDebug( 1212 ) << "XGL:" << ( mXgl ? "yes" : "no" ); - if( mGLRenderer.contains( "Intel" )) + if( mGLRenderer.startsWith( "Mesa DRI Intel" )) { mDriver = "intel"; QStringList words = mGLRenderer.split(" "); mVersion = Version( words[ words.count() - 2 ] ); } - else if( mGLVendor.contains( "NVIDIA" )) + else if( mGLVendor == "NVIDIA Corporation" ) { mDriver = "nvidia"; QStringList words = mGLVersion.split(" "); mVersion = Version( words[ words.count() - 1 ] ); } + else if( mGLVendor == "ATI Technologies Inc." ) + { + mDriver = "fglrx"; + mVersion = Version( mGLVersion.split(" ").first()); + } + else if( mGLRenderer.startsWith( "Mesa DRI" )) + { + mDriver = "radeon"; + mVersion = Version( mGLRenderer.split(" ")[ 3 ] ); + } + else if( mGLRenderer == "Software Rasterizer" ) + { + mDriver = "software"; + QStringList words = mGLVersion.split(" "); + mVersion = Version( words[ words.count() - 1 ] ); + } else { mDriver = "unknown"; @@ -240,6 +277,7 @@ #endif } +// See http://techbase.kde.org/Projects/KWin/HW for a list of some cards that are known to work. void CompositingPrefs::applyDriverSpecificOptions() { if( mXgl ) @@ -253,27 +291,45 @@ kDebug( 1212 ) << "intel driver, disabling vsync, enabling direct"; mEnableVSync = false; mEnableDirectRendering = true; - // Enable compositing by default only on 900-series cards - if( mVersion >= Version( "20061017" ) && mGLRenderer.contains( "Intel(R) 9" )) - { - kDebug( 1212 ) << "intel >= 20061017 and 900-series card, enabling compositing"; - mEnableCompositing = true; + if( mVersion >= Version( "20061017" )) + { + if( mGLRenderer.contains( "Intel(R) 9" )) + { // Enable compositing by default on 900-series cards + kDebug( 1212 ) << "intel >= 20061017 and 900-series card, enabling compositing"; + mEnableCompositing = true; + } + if( mGLRenderer.contains( "Mesa DRI Intel(R) G" )) + { // e.g. G43 chipset + kDebug( 1212 ) << "intel >= 20061017 and Gxx-series card, enabling compositing"; + mEnableCompositing = true; + } } } else if( mDriver == "nvidia" ) { mStrictBinding = false; - if( mVersion <= Version( "100.14.23" )) + if( mVersion >= Version( "173.14.12" )) { - kDebug( 1212 ) << "nvidia <= 100.14.23, disabling vsync"; - mEnableVSync = false; + kDebug( 1212 ) << "nvidia >= 173.14.12, enabling compositing"; + mEnableCompositing = true; } - if( mVersion >= Version( "96.39" )) + } + else if( mDriver == "radeon" ) + { // radeon r200 only ? + if( mGLRenderer.startsWith( "Mesa DRI R200" ) && mVersion >= Version( "20060602" )) { - kDebug( 1212 ) << "nvidia >= 96.39, enabling compositing"; + kDebug( 1212 ) << "radeon r200 >= 20060602, enabling compositing"; mEnableCompositing = true; } } + else if( mDriver == "fglrx" ) + { // radeon r200 only ? + if( mVersion >= Version( "2.1.7412" )) + { + kDebug( 1212 ) << "fglrx >= 2.1.7412, enabling compositing"; + mEnableCompositing = true; + } + } } Index: geometry.cpp =================================================================== --- kwin/geometry.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/geometry.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -270,8 +270,7 @@ case ScreenArea: return desktopwidget->screenGeometry( screen ); } - assert( false ); - return QRect(); + abort(); } QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const @@ -396,6 +395,34 @@ ny = ly - ch; } } + + // Corner snapping + if( nx == lrx || nx+cw == lx ) + { + if ((sOWO?(ry>lry):true) && (qAbs(lry-ry)<snap) && (qAbs(lry-ry) < deltaY)) + { + deltaY = qAbs( lry - ry ); + ny = lry - ch; + } + if ((sOWO?(cy<ly):true) && (qAbs(cy-ly)<snap) && (qAbs(cy-ly) < deltaY)) + { + deltaY = qAbs( cy - ly ); + ny = ly; + } + } + if( ny == lry || ny+ch == ly ) + { + if ((sOWO?(rx>lrx):true) && (qAbs(lrx-rx)<snap) && (qAbs(lrx-rx) < deltaX)) + { + deltaX = qAbs( lrx - rx ); + nx = lrx - cw; + } + if ((sOWO?(cx<lx):true) && (qAbs(cx-lx)<snap) && (qAbs(cx-lx) < deltaX)) + { + deltaX = qAbs( cx - lx ); + nx = lx; + } + } } } } @@ -496,7 +523,7 @@ SNAP_BORDER_LEFT break; default: - assert( false ); + abort(); break; } @@ -558,38 +585,78 @@ newrx=lx; \ } +#define SNAP_WINDOW_C_TOP if ( (sOWO?(newcy<ly):true) \ + && (newcx == lrx || newrx == lx) \ + && qAbs(ly-newcy) < deltaY ) { \ + deltaY = qAbs( ly - newcy + 1 ); \ + newcy = ly + 1; \ + } + +#define SNAP_WINDOW_C_BOTTOM if ( (sOWO?(newry>lry):true) \ + && (newcx == lrx || newrx == lx) \ + && qAbs(lry-newry) < deltaY ) { \ + deltaY = qAbs( lry - newry - 1 ); \ + newry = lry - 1; \ + } + +#define SNAP_WINDOW_C_LEFT if ( (sOWO?(newcx<lx):true) \ + && (newcy == lry || newry == ly) \ + && qAbs(lx-newcx) < deltaX ) { \ + deltaX = qAbs( lx - newcx + 1 ); \ + newcx = lx + 1; \ + } + +#define SNAP_WINDOW_C_RIGHT if ( (sOWO?(newrx>lrx):true) \ + && (newcy == lry || newry == ly) \ + && qAbs(lrx-newrx) < deltaX ) { \ + deltaX = qAbs( lrx - newrx - 1 ); \ + newrx = lrx - 1; \ + } + switch ( mode ) { case PositionBottomRight: SNAP_WINDOW_BOTTOM SNAP_WINDOW_RIGHT + SNAP_WINDOW_C_BOTTOM + SNAP_WINDOW_C_RIGHT break; case PositionRight: SNAP_WINDOW_RIGHT + SNAP_WINDOW_C_RIGHT break; case PositionBottom: SNAP_WINDOW_BOTTOM + SNAP_WINDOW_C_BOTTOM break; case PositionTopLeft: SNAP_WINDOW_TOP SNAP_WINDOW_LEFT + SNAP_WINDOW_C_TOP + SNAP_WINDOW_C_LEFT break; case PositionLeft: SNAP_WINDOW_LEFT + SNAP_WINDOW_C_LEFT break; case PositionTop: SNAP_WINDOW_TOP + SNAP_WINDOW_C_TOP break; case PositionTopRight: SNAP_WINDOW_TOP SNAP_WINDOW_RIGHT + SNAP_WINDOW_C_TOP + SNAP_WINDOW_C_RIGHT break; case PositionBottomLeft: SNAP_WINDOW_BOTTOM SNAP_WINDOW_LEFT + SNAP_WINDOW_C_BOTTOM + SNAP_WINDOW_C_LEFT break; default: - assert( false ); + abort(); break; } } @@ -1501,9 +1568,8 @@ void Client::resizeWithChecks( int w, int h, ForceGeometry_t force ) { - if( shade_geometry_change ) - assert( false ); - else if( isShade()) + assert( !shade_geometry_change ); + if( isShade()) { if( h == border_top + border_bottom ) { @@ -1614,6 +1680,20 @@ } /*! + Returns whether the window is moveable across Xinerama screens + */ +bool Client::isMovableAcrossScreens() const + { + if( !motif_may_move ) + return false; + if( isSpecialWindow() && !isSplash() && !isToolbar()) // allow moving of splashscreens :) + return false; + if( rules()->checkPosition( invalidPoint ) != invalidPoint ) // forced position + return false; + return true; + } + +/*! Returns whether the window is resizable or has a fixed size. */ bool Client::isResizable() const @@ -1736,6 +1816,8 @@ updateWindowRules(); checkMaximizeGeometry(); workspace()->checkActiveScreen( this ); + workspace()->updateStackingOrder(); + workspace()->checkUnredirect(); if( resized ) { discardWindowPixmap(); @@ -1808,6 +1890,8 @@ updateWindowRules(); checkMaximizeGeometry(); workspace()->checkActiveScreen( this ); + workspace()->updateStackingOrder(); + workspace()->checkUnredirect(); discardWindowPixmap(); if( scene != NULL ) scene->windowGeometryShapeChanged( this ); @@ -1850,6 +1934,8 @@ updateWindowRules(); checkMaximizeGeometry(); workspace()->checkActiveScreen( this ); + workspace()->updateStackingOrder(); + workspace()->checkUnredirect(); // client itself is not damaged addWorkspaceRepaint( geom_before_block ); addWorkspaceRepaint( geom ); // trigger repaint of window's new location @@ -2201,6 +2287,7 @@ } } updateWindowRules(); + workspace()->checkUnredirect(); } int Client::checkFullScreenHack( const QRect& geom ) const @@ -2500,7 +2587,7 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) { - if(( mode == PositionCenter && !isMovable()) + if(( mode == PositionCenter && !isMovableAcrossScreens() ) || ( mode != PositionCenter && ( isShade() || !isResizable()))) return; @@ -2589,7 +2676,7 @@ break; case PositionCenter: default: - assert( false ); + abort(); break; } @@ -2644,7 +2731,7 @@ break; case PositionCenter: default: - assert( false ); + abort(); break; } if( moveResizeGeom.size() != previousMoveResizeGeom.size()) @@ -2653,24 +2740,32 @@ else if( isMove()) { assert( mode == PositionCenter ); - // first move, then snap, then check bounds - moveResizeGeom.moveTopLeft( topleft ); - moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft() ) ); - // NOTE: This is duped in checkUnrestrictedMoveResize(). - if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 ) // titlebar mustn't go out - moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 ); - // no need to check top_marge, titlebar_marge already handles it - if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge ) - moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge ); - if( moveResizeGeom.right() < desktopArea.left() + left_marge ) - moveResizeGeom.moveRight( desktopArea.left() + left_marge ); - if( moveResizeGeom.left() > desktopArea.right() - right_marge ) - moveResizeGeom.moveLeft(desktopArea.right() - right_marge ); + if( !isMovable() ) // isMovableAcrossScreens() must have been true to get here + { // Special moving of maximized windows on Xinerama screens + int screen = workspace()->screenNumber( globalPos ); + moveResizeGeom = workspace()->clientArea( MaximizeArea, screen, 0 ); + } + else + { + // first move, then snap, then check bounds + moveResizeGeom.moveTopLeft( topleft ); + moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft())); + // NOTE: This is duped in checkUnrestrictedMoveResize(). + if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 ) // titlebar mustn't go out + moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 ); + // no need to check top_marge, titlebar_marge already handles it + if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge ) + moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge ); + if( moveResizeGeom.right() < desktopArea.left() + left_marge ) + moveResizeGeom.moveRight( desktopArea.left() + left_marge ); + if( moveResizeGeom.left() > desktopArea.right() - right_marge ) + moveResizeGeom.moveLeft(desktopArea.right() - right_marge ); + } if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft()) update = true; } else - assert( false ); + abort(); if( isResize()) { Index: group.cpp =================================================================== --- kwin/group.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/group.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -175,7 +175,7 @@ { kdDebug() << "BT:" << transiencyCheckStartBt << endl; kdDebug() << "CLIENT:" << transiencyCheckClient << endl; - assert( false ); + abort(); } transiencyCheckNonExistent = false; } Index: toplevel.h =================================================================== --- kwin/toplevel.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/toplevel.h (.../work/~seli/kwin11.1) (revision 880714) @@ -108,8 +108,11 @@ double opacity() const; int depth() const; bool hasAlpha() const; - void setupCompositing(); - void finishCompositing(); + virtual void setupCompositing(); + virtual void finishCompositing(); + bool updateUnredirectedState(); + bool unredirected() const; + void suspendUnredirect( bool suspend ); void addRepaint( const QRect& r ); void addRepaint( int x, int y, int w, int h ); void addRepaintFull(); @@ -144,6 +147,7 @@ void disownDataPassedToDeleted(); friend kdbgstream& operator<<( kdbgstream& stream, const Toplevel* ); void deleteEffectWindow(); + virtual bool shouldUnredirect() const = 0; QRect geom; Visual* vis; int bit_depth; @@ -172,6 +176,8 @@ QByteArray client_machine; WId wmClientLeaderWin; QByteArray window_role; + bool unredirect; + bool unredirectSuspend; // when unredirected, but pixmap is needed temporarily // when adding new data members, check also copyToDeleted() }; @@ -396,6 +402,11 @@ return info->pid(); } +inline bool Toplevel::unredirected() const + { + return unredirect; + } + kdbgstream& operator<<( kdbgstream& stream, const Toplevel* ); kdbgstream& operator<<( kdbgstream& stream, const ToplevelList& ); kdbgstream& operator<<( kdbgstream& stream, const ConstToplevelList& ); Index: notifications.cpp =================================================================== --- kwin/notifications.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/notifications.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -27,9 +27,16 @@ namespace KWin { -QString Notify::eventToName( Event e ) +static bool forgetIt = false; +QList< Notify::EventData > Notify::pending_events; + +bool Notify::raise( Event e, const QString& message, Client* c ) { + if ( forgetIt ) + return false; // no connection was possible, don't try each time + QString event; + KNotification::NotificationFlags flags = KNotification::CloseOnTimeout; switch ( e ) { case Activate: @@ -92,6 +99,10 @@ case DemandAttentionOther: event = "demandsattentionother"; break; + case CompositingSlow: + event = "compositingslow"; + flags = KNotification::Persistent; + break; default: if ((e > DesktopChange) && (e <= DesktopChange+20)) { @@ -99,18 +110,6 @@ } break; } - return event; - } - -static bool forgetIt = false; -QList< Notify::EventData > Notify::pending_events; - -bool Notify::raise( Event e, const QString& message, Client* c ) - { - if ( forgetIt ) - return false; // no connection was possible, don't try each time - - QString event = eventToName( e ); if ( event.isNull() ) return false; @@ -124,12 +123,13 @@ data.event = event; data.message = message; data.window = c ? c->window() : 0; + data.flags = flags; pending_events.append( data ); return true; } - return KNotification::event( event, message /*, QPixmap() , c ? c->window() : 0*/ ); //FIXME get the widget ? + return KNotification::event( event, message, QPixmap(), NULL /* TODO c ? c->window() : 0*/, flags ); } void Notify::sendPendingEvents() @@ -139,7 +139,7 @@ EventData data = pending_events.first(); pending_events.pop_front(); if( !forgetIt ) - KNotification::event( data.event, data.message /* , QPixmap() , data.window */ ); + KNotification::event( data.event, data.message, QPixmap(), NULL /* TODO data.window*/, data.flags ); } } Index: client.h =================================================================== --- kwin/client.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/client.h (.../work/~seli/kwin11.1) (revision 880714) @@ -150,6 +150,7 @@ void setFullScreen( bool set, bool user ); bool isFullScreen() const; bool isFullScreenable( bool fullscreen_hack = false ) const; + bool isActiveFullScreen() const; bool userCanSetFullScreen() const; QRect geometryFSRestore() const { return geom_fs_restore; } // only for session saving int fullScreenMode() const { return fullscreen_mode; } // only for session saving @@ -182,6 +183,7 @@ bool isResizable() const; bool isMovable() const; + bool isMovableAcrossScreens() const; bool isCloseable() const; // may be closed by the user (may have a close button) void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h) @@ -230,6 +232,9 @@ void hideClient( bool hide ); bool hiddenPreview() const; // window is mapped in order to get a window pixmap + virtual void setupCompositing(); + virtual void finishCompositing(); + QString caption( bool full = true ) const; void updateCaption(); @@ -324,6 +329,7 @@ protected: virtual void debug( kdbgstream& stream ) const; + virtual bool shouldUnredirect() const; private slots: void pingTimeout(); @@ -333,10 +339,7 @@ void delayedSetShortcut(); private: - void setMappingState( int s ); // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1 - int mappingState() const; - bool isIconicState() const; - bool isNormalState() const; + void exportMappingState( int s ); // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1 bool isManaged() const; // returns false if this client is not yet managed void updateAllowedActions( bool force = false ); QSize sizeForClientSize( const QSize&, Sizemode mode = SizemodeAny, bool noframe = false ) const; @@ -390,9 +393,13 @@ void destroyDecoration(); void updateFrameExtents(); - void rawShow(); // just shows it - void rawHide(); // just hides it - void setHiddenPreview( bool set, allowed_t ); + void internalShow( allowed_t ); + void internalHide( allowed_t ); + void internalKeep( allowed_t ); + void map( allowed_t ); + void unmap( allowed_t ); + void updateHiddenPreview(); + void updateInputShape(); Time readUserTimeMapTimestamp( const KStartupInfoId* asn_id, const KStartupInfoData* asn_data, @@ -419,7 +426,14 @@ QRect initialMoveResizeGeom; XSizeHints xSizeHint; void sendSyntheticConfigureNotify(); - int mapping_state; + enum MappingState + { + Withdrawn, // not handled, as per ICCCM WithdrawnState + Mapped, // the frame is mapped + Unmapped, // the frame is not mapped + Kept // the frame should be unmapped, but is kept (for compositing) + }; + MappingState mapping_state; void readTransient(); Window verifyTransientFor( Window transient_for, bool set ); void addTransient( Client* cl ); @@ -457,8 +471,6 @@ uint urgency : 1; // XWMHints, UrgencyHint uint ignore_focus_stealing : 1; // don't apply focus stealing prevention to this client uint demands_attention : 1; - uint hidden_preview : 1; // mapped only to get a window pixmap for compositing - uint raw_shown : 1; // for use in rawShow()/rawHide() WindowRules client_rules; void getWMHints(); void readIcons(); @@ -595,11 +607,6 @@ return in_group; } -inline int Client::mappingState() const - { - return mapping_state; - } - inline bool Client::isMinimized() const { @@ -710,19 +717,9 @@ return sm_stacking_order; } -inline bool Client::isIconicState() const - { - return mapping_state == IconicState; - } - -inline bool Client::isNormalState() const - { - return mapping_state == NormalState; - } - inline bool Client::isManaged() const { - return mapping_state != WithdrawnState; + return mapping_state != Withdrawn; } inline QPoint Client::clientPos() const @@ -789,7 +786,7 @@ inline bool Client::hiddenPreview() const { - return hidden_preview; + return mapping_state == Kept; } KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Client, Window, cl->wrapperId() == value ); Index: effects.h =================================================================== --- kwin/effects.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects.h (.../work/~seli/kwin11.1) (revision 880714) @@ -99,6 +99,7 @@ virtual int desktopToRight( int desktop, bool wrap ) const; virtual int desktopUp( int desktop, bool wrap ) const; virtual int desktopDown( int desktop, bool wrap ) const; + virtual double animationTimeFactor() const; virtual Window createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor ); using EffectsHandler::createInputWindow; @@ -142,7 +143,7 @@ bool loadEffect( const QString& name ); void toggleEffect( const QString& name ); void unloadEffect( const QString& name ); - void reloadEffect( const QString& name ); + void reconfigureEffect( const QString& name ); bool isEffectLoaded( const QString& name ); QStringList loadedEffects() const; QStringList listOfEffects() const; @@ -200,6 +201,7 @@ virtual QSize size() const; virtual QRect rect() const; virtual bool isMovable() const; + virtual bool isMovableAcrossScreens() const; virtual bool isUserMove() const; virtual bool isUserResize() const; virtual QRect iconGeometry() const; Index: lib/kwineffects.cpp =================================================================== --- kwin/lib/kwineffects.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/lib/kwineffects.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -64,11 +64,14 @@ , decoration_opacity( 1.0 ) , xScale( 1 ) , yScale( 1 ) + , zScale( 1 ) , xTranslate( 0 ) , yTranslate( 0 ) + , zTranslate( 0 ) , saturation( 1 ) , brightness( 1 ) , shader( NULL ) + , rotation( NULL ) { quads = w->buildQuads(); } @@ -76,11 +79,23 @@ ScreenPaintData::ScreenPaintData() : xScale( 1 ) , yScale( 1 ) + , zScale( 1 ) , xTranslate( 0 ) , yTranslate( 0 ) + , zTranslate( 0 ) + , rotation( NULL ) { } +RotationData::RotationData() + : axis( ZAxis ) + , angle( 0.0 ) + , xRotationPoint( 0.0 ) + , yRotationPoint( 0.0 ) + , zRotationPoint( 0.0 ) + { + } + //**************************************** // Effect //**************************************** @@ -93,6 +108,10 @@ { } +void Effect::reconfigure( ReconfigureFlags ) + { + } + void Effect::windowUserMovedResized( EffectWindow* , bool, bool ) { } @@ -241,6 +260,17 @@ return effects->cursorPos(); } +double Effect::animationTime( const KConfigGroup& cfg, const QString& key, int defaultTime ) + { + int time = cfg.readEntry( key, 0 ); + return time != 0 ? time : qMax( defaultTime * effects->animationTimeFactor(), 1. ); + } + +double Effect::animationTime( int defaultTime ) + { // at least 1ms, otherwise 0ms times can break some things + return qMax( defaultTime * effects->animationTimeFactor(), 1. ); + } + //**************************************** // EffectsHandler //**************************************** @@ -307,7 +337,7 @@ void EffectsHandler::sendReloadMessage( const QString& effectname ) { - QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kwin", "/KWin", "org.kde.KWin", "reloadEffect"); + QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kwin", "/KWin", "org.kde.KWin", "reconfigureEffect"); message << QString("kwin4_effect_" + effectname); QDBusConnection::sessionBus().send(message); } @@ -351,21 +381,7 @@ glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); textTexture.bind(); - const float verts[ 4 * 2 ] = - { - area.x(), area.y(), - area.x(), area.y() + area.height(), - area.x() + area.width(), area.y() + area.height(), - area.x() + area.width(), area.y() - }; - const float texcoords[ 4 * 2 ] = - { - 0, textPixmap.height(), - 0, 0, - textPixmap.width(), 0, - textPixmap.width(), textPixmap.height() - }; - renderGLGeometry( 4, verts, texcoords ); + textTexture.render( infiniteRegion(), area ); textTexture.unbind(); glPopAttrib(); return true; @@ -900,9 +916,8 @@ TimeLine::TimeLine(const int duration) { m_Time = 0; - m_CurveShape = TimeLine::EaseInCurve; m_Duration = duration; - m_TimeLine = new QTimeLine(m_Duration); + m_TimeLine = new QTimeLine(m_Duration ? m_Duration : 1); // (avoid QTimeLine warning) m_TimeLine->setFrameRange(0, m_Duration); m_TimeLine->setCurveShape(QTimeLine::EaseInCurve); } @@ -910,12 +925,12 @@ TimeLine::TimeLine(const TimeLine &other) { m_Time = other.m_Time; - m_CurveShape = other.m_CurveShape; m_Duration = other.m_Duration; - m_TimeLine = new QTimeLine(m_Duration); + m_TimeLine = new QTimeLine(m_Duration ? m_Duration : 1); m_TimeLine->setFrameRange(0, m_Duration); - setProgress(m_Progress); setCurveShape(m_CurveShape); + if( m_Duration != 0 ) + setProgress(m_Progress); } TimeLine::~TimeLine() @@ -931,16 +946,19 @@ void TimeLine::setDuration(const int msec) { m_Duration = msec; - m_TimeLine->setDuration(msec); + m_TimeLine->setDuration(m_Duration); + m_TimeLine->setFrameRange(0, m_Duration); } double TimeLine::value() const { + Q_ASSERT( m_Duration != 0 ); return valueForTime(m_Time); } double TimeLine::valueForTime(const int msec) const { + Q_ASSERT( m_Duration != 0 ); // Catch non QTimeLine CurveShapes here, (but there are none right now) @@ -950,34 +968,40 @@ void TimeLine::addTime(const int msec) { + Q_ASSERT( m_Duration != 0 ); m_Time = qMin(m_Duration, m_Time + msec); m_Progress = (double)m_Time / m_Duration; } void TimeLine::removeTime(const int msec) { + Q_ASSERT( m_Duration != 0 ); m_Time = qMax(0, m_Time - msec); m_Progress = (double)m_Time / m_Duration; } void TimeLine::setProgress(const double progress) { + Q_ASSERT( m_Duration != 0 ); m_Progress = progress; m_Time = qRound(m_Duration * progress); } double TimeLine::progress() const { + Q_ASSERT( m_Duration != 0 ); return m_Progress; } int TimeLine::time() const { + Q_ASSERT( m_Duration != 0 ); return m_Time; } void TimeLine::addProgress(const double progress) { + Q_ASSERT( m_Duration != 0 ); m_Progress += progress; m_Time = (int)(m_Duration * m_Progress); } Index: lib/kwinglutils.cpp =================================================================== --- kwin/lib/kwinglutils.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/lib/kwinglutils.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -298,7 +298,9 @@ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // We have two elements per vertex in the verts array int verticesCount = verts.count() / 2; + texture->enableNormalizedTexCoords(); renderGLGeometry( verticesCount, verts.data(), texcoords.data() ); + texture->disableNormalizedTexCoords(); texture->unbind(); glPopMatrix(); @@ -368,6 +370,8 @@ GLTexture::~GLTexture() { discard(); + assert( mUnnormalizeActive == 0 ); + assert( mNormalizeActive == 0 ); } void GLTexture::init() @@ -378,6 +382,8 @@ y_inverted = false; can_use_mipmaps = false; has_valid_mipmaps = false; + mUnnormalizeActive = 0; + mNormalizeActive = 0; } void GLTexture::initStatic() @@ -485,16 +491,21 @@ }; const float texcoords[ 4 * 2 ] = { - 0, 1, + 0, 1, // y needs to be swapped (normalized coords) 0, 0, 1, 0, 1, 1 }; + enableNormalizedTexCoords(); renderGLGeometry( region, 4, verts, texcoords ); + disableNormalizedTexCoords(); } void GLTexture::enableUnnormalizedTexCoords() { + assert( mNormalizeActive == 0 ); + if( mUnnormalizeActive++ != 0 ) + return; // update texture matrix to handle GL_TEXTURE_2D and GL_TEXTURE_RECTANGLE glMatrixMode( GL_TEXTURE ); glPushMatrix(); @@ -512,12 +523,44 @@ void GLTexture::disableUnnormalizedTexCoords() { + if( --mUnnormalizeActive != 0 ) + return; // Restore texture matrix glMatrixMode( GL_TEXTURE ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); } +void GLTexture::enableNormalizedTexCoords() + { + assert( mUnnormalizeActive == 0 ); + if( mNormalizeActive++ != 0 ) + return; + // update texture matrix to handle GL_TEXTURE_2D and GL_TEXTURE_RECTANGLE + glMatrixMode( GL_TEXTURE ); + glPushMatrix(); + glLoadIdentity(); + glScalef( mSize.width() * mScale.width(), mSize.height() * mScale.height(), 1 ); + if( y_inverted ) + { + // Modify texture matrix so that we could always use non-opengl + // coordinates for textures + glScalef( 1, -1, 1 ); + glTranslatef( 0, -mSize.height(), 0 ); + } + glMatrixMode( GL_MODELVIEW ); + } + +void GLTexture::disableNormalizedTexCoords() + { + if( --mNormalizeActive != 0 ) + return; + // Restore texture matrix + glMatrixMode( GL_TEXTURE ); + glPopMatrix(); + glMatrixMode( GL_MODELVIEW ); + } + GLuint GLTexture::texture() const { return mTexture; Index: lib/kwineffects.h =================================================================== --- kwin/lib/kwineffects.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/lib/kwineffects.h (.../work/~seli/kwin11.1) (revision 880714) @@ -56,6 +56,7 @@ class WindowQuad; class GLRenderTarget; class GLShader; +class RotationData; class WindowQuadList; class WindowPrePaintData; class WindowPaintData; @@ -162,7 +163,7 @@ #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 21 +#define KWIN_EFFECT_API_VERSION_MINOR 40 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -273,6 +274,20 @@ virtual ~Effect(); /** + * Flags describing which parts of configuration have changed. + */ + enum ReconfigureFlag + { + ReconfigureAll = 1 << 0 /// Everything needs to be reconfigured. + }; + Q_DECLARE_FLAGS( ReconfigureFlags, ReconfigureFlag ) + + /** + * Called when configuration changes (either the effect's or KWin's global). + */ + virtual void reconfigure( ReconfigureFlags flags ); + + /** * Called before starting to paint the screen. * In this method you can: * @li set whether the windows or the entire screen will be transformed @@ -372,6 +387,22 @@ static QPoint cursorPos(); /** + * Read animation time from the configuration and possibly adjust using animationTimeFactor(). + * The configuration value in the effect should also have special value 'default' (set using + * QSpinBox::setSpecialValueText()) with the value 0. This special value is adjusted + * using the global animation speed, otherwise the exact time configured is returned. + * @param cfg configuration group to read value from + * @param key configuration key to read value from + * @param defaultTime default animation time in milliseconds + */ + // return type is intentionally double so that one can divide using it without losing data + static double animationTime( const KConfigGroup& cfg, const QString& key, int defaultTime ); + /** + * @overload Use this variant if the animation time is hardcoded and not configurable + * in the effect itself. + */ + static double animationTime( int defaultTime ); + /** * Linearly interpolates between @p x and @p y. * * Returns @p x when @p a = 0; returns @p y when @p a = 1. @@ -487,6 +518,14 @@ virtual int desktopToRight( int desktop, bool wrap ) const = 0; virtual int desktopUp( int desktop, bool wrap ) const = 0; virtual int desktopDown( int desktop, bool wrap ) const = 0; + /** + * Factor by which animation speed in the effect should be modified (multiplied). + * If configurable in the effect itself, the option should have also 'default' + * animation speed. The actual value should be determined using animationTime(). + * Note: The factor can be also 0, so make sure your code can cope with 0ms time + * if used manually. + */ + virtual double animationTimeFactor() const = 0; virtual EffectWindow* findWindow( WId id ) const = 0; virtual EffectWindowList stackingOrder() const = 0; @@ -629,6 +668,7 @@ virtual QSize size() const = 0; virtual QRect rect() const = 0; virtual bool isMovable() const = 0; + virtual bool isMovableAcrossScreens() const = 0; virtual bool isUserMove() const = 0; virtual bool isUserResize() const = 0; virtual QRect iconGeometry() const = 0; @@ -873,8 +913,10 @@ double decoration_opacity; double xScale; double yScale; + double zScale; int xTranslate; int yTranslate; + double zTranslate; /** * Saturation of the window, in range [0; 1] * 1 means that the window is unchanged, 0 means that it's completely @@ -895,6 +937,7 @@ * Shader to be used for rendering, if any. */ GLShader* shader; + RotationData* rotation; }; class KWIN_EXPORT ScreenPaintData @@ -903,8 +946,11 @@ ScreenPaintData(); double xScale; double yScale; + double zScale; int xTranslate; int yTranslate; + double zTranslate; + RotationData* rotation; }; class KWIN_EXPORT ScreenPrePaintData @@ -914,6 +960,23 @@ QRegion paint; }; +class KWIN_EXPORT RotationData + { + public: + RotationData(); + enum RotationAxis + { + XAxis, + YAxis, + ZAxis + }; + RotationAxis axis; + float angle; + float xRotationPoint; + float yRotationPoint; + float zRotationPoint; + }; + /** * @short Helper class for restricting painting area only to allowed area. * @@ -1043,12 +1106,12 @@ }; /** - * Creates a TimeLine and computes the progress data. The default - * duration can be overridden from the Effect. Usually, for larger + * Creates a TimeLine and computes the progress data. Usually, for larger * animations you want to choose values more towards 300 milliseconds. * For small animations, values around 150 milliseconds are sensible. + * Note that duration 0 is not valid. */ - explicit TimeLine(const int duration = 250); + explicit TimeLine(int duration = 0); /** * Creates a copy of the TimeLine so we can have the state copied Index: lib/kwinglutils.h =================================================================== --- kwin/lib/kwinglutils.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/lib/kwinglutils.h (.../work/~seli/kwin11.1) (revision 880714) @@ -77,6 +77,8 @@ * Renders quads using given vertices. * If texture is not 0, each texture coordinate much have two components (st). * If color is not 0, each color much have four components (rgba). + * Note that texture coordinates must match texture type (normalized/unnormalized + * for GL_TEXTURE_2D/GL_TEXTURE_ARB). * * @param count number of vertices to use. * @param dim number of components per vertex coordinate in vertices array. @@ -124,8 +126,32 @@ virtual void bind(); virtual void unbind(); void render( QRegion region, const QRect& rect ); + /** + * Set up texture transformation matrix to automatically map unnormalized + * texture coordinates (i.e. 0 to width, 0 to height, (0,0) is top-left) + * to OpenGL coordinates. Automatically adjusts for different texture + * types. This can be done only for one texture at a time, repeated + * calls for the same texture are allowed though, requiring the same + * amount of calls to disableUnnormalizedTexCoords(). + */ void enableUnnormalizedTexCoords(); + /** + * Disables transformation set up using enableUnnormalizedTexCoords(). + */ void disableUnnormalizedTexCoords(); + /** + * Set up texture transformation matrix to automatically map normalized + * texture coordinates (i.e. 0 to 1, 0 to 1, (0,0) is bottom-left) + * to OpenGL coordinates. Automatically adjusts for different texture + * types. This can be done only for one texture at a time, repeated + * calls for the same texture are allowed though, requiring the same + * amount of calls to disableNormalizedTexCoords(). + */ + void enableNormalizedTexCoords(); + /** + * Disables transformation set up using enableNormalizedTexCoords(). + */ + void disableNormalizedTexCoords(); GLuint texture() const; GLenum target() const; @@ -157,6 +183,8 @@ private: void init(); + int mUnnormalizeActive; // 0 - no, otherwise refcount + int mNormalizeActive; // 0 - no, otherwise refcount static bool mNPOTTextureSupported; static bool mFramebufferObjectSupported; Index: manage.cpp =================================================================== --- kwin/manage.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/manage.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -66,8 +66,6 @@ vis = attr.visual; bit_depth = attr.depth; - setupCompositing(); - // SELI order all these things in some sane manner bool init_minimize = false; @@ -133,6 +131,8 @@ original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0; skip_pager = ( info->state() & NET::SkipPager) != 0; + setupCompositing(); + KStartupInfoId asn_id; KStartupInfoData asn_data; bool asn_valid = workspace()->checkStartupNotification( window(), asn_id, asn_data ); @@ -530,9 +530,9 @@ else // doNotShow { // SELI HACK !!! hideClient( true ); - setMappingState( IconicState ); } - assert( mappingState() != WithdrawnState ); + assert( mapping_state != Withdrawn ); + blockGeometryUpdates( false ); if( user_time == CurrentTime || user_time == -1U ) // no known user time, set something old { Index: scene_xrender.h =================================================================== --- kwin/scene_xrender.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/scene_xrender.h (.../work/~seli/kwin11.1) (revision 880714) @@ -54,6 +54,8 @@ private: void paintTransformedScreen( int mask ); void createBuffer(); + void flushBuffer( int mask, QRegion damage ); + bool selfCheck(); XRenderPictFormat* format; Picture front; static Picture buffer; Index: workspace.cpp =================================================================== --- kwin/workspace.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/workspace.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -99,6 +99,7 @@ active_screen (0), delayfocus_client (0), force_restacking( false ), + x_stacking_dirty( true ), showing_desktop( false ), block_showing_desktop( 0 ), was_user_interaction (false), @@ -140,7 +141,8 @@ overlay_visible( true ), overlay_shown( false ), transSlider( NULL ), - transButton( NULL ) + transButton( NULL ), + forceUnredirectCheck( true ) { (void) new KWinAdaptor( this ); QDBusConnection dbus = QDBusConnection::sessionBus(); @@ -164,6 +166,8 @@ connect( &temporaryRulesMessages, SIGNAL( gotMessage( const QString& )), this, SLOT( gotTemporaryRulesMessage( const QString& ))); connect( &rulesUpdatedTimer, SIGNAL( timeout()), this, SLOT( writeWindowRules())); + connect( &unredirectTimer, SIGNAL( timeout()), this, SLOT( delayedCheckUnredirect())); + unredirectTimer.setSingleShot( true ); updateXTime(); // needed for proper initialization of user_time in Client ctor @@ -348,7 +352,7 @@ connect( &compositeTimer, SIGNAL( timeout()), SLOT( performCompositing())); connect(KGlobalSettings::self(), SIGNAL(appearanceChanged()), this, - SLOT(slotReconfigure())); + SLOT(reconfigure())); connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), this, SLOT(slotSettingsChanged(int))); connect(KGlobalSettings::self(), SIGNAL(blockShortcuts(int)), this, @@ -422,7 +426,7 @@ && activeClient() == NULL && should_get_focus.count() == 0 ) // no client activated in manage() { if( new_active_client == NULL ) - new_active_client = topClientOnDesktop( currentDesktop()); + new_active_client = topClientOnDesktop( currentDesktop(), -1 ); if( new_active_client == NULL && !desktops.isEmpty() ) new_active_client = findDesktop( true, currentDesktop()); } @@ -544,6 +548,7 @@ stacking_order.append( c ); // c to be in stacking_order if( c->isTopMenu()) addTopMenu( c ); + x_stacking_dirty = true; updateClientArea(); // this cannot be in manage(), because the client got added only now updateClientLayer( c ); if( c->isDesktop()) @@ -566,6 +571,7 @@ void Workspace::addUnmanaged( Unmanaged* c, allowed_t ) { unmanaged.append( c ); + x_stacking_dirty = true; } /* @@ -597,6 +603,7 @@ desktops.removeAll( c ); unconstrained_stacking_order.removeAll( c ); stacking_order.removeAll( c ); + x_stacking_dirty = true; for( int i = 1; i <= numberOfDesktops(); ++i ) @@ -633,12 +640,14 @@ { assert( unmanaged.contains( c )); unmanaged.removeAll( c ); + x_stacking_dirty = true; } void Workspace::addDeleted( Deleted* c, allowed_t ) { assert( !deleted.contains( c )); deleted.append( c ); + x_stacking_dirty = true; } void Workspace::removeDeleted( Deleted* c, allowed_t ) @@ -649,6 +658,7 @@ if( effects ) static_cast<EffectsHandlerImpl*>(effects)->windowDeleted( c->effectWindow()); deleted.removeAll( c ); + x_stacking_dirty = true; } void Workspace::updateFocusChains( Client* c, FocusChainChange change ) @@ -959,6 +969,18 @@ reconfigureTimer.start( 200 ); } +// This DBUS call is used by the compositing kcm. Since the reconfigure() +// DBUS call delays the actual reconfiguring, it is not possible to immediately +// call compositingActive(). Therefore the kcm will instead call this to ensure +// the reconfiguring has already happened. +bool Workspace::waitForCompositingSetup() + { + if( !reconfigureTimer.isActive()) + return false; + reconfigureTimer.stop(); + slotReconfigure(); + return compositingActive(); + } void Workspace::slotSettingsChanged(int category) { @@ -2447,7 +2469,7 @@ if( message == "noborderaltf3" ) { KAction* action = qobject_cast<KAction*>(keys->action( "Window Operations Menu" )); - if (action==0) assert( false ); + assert( action != NULL ); QString shortcut = QString( "%1 (%2)" ).arg( action->text() ) .arg( action->globalShortcut().primary().toString()); args << "--msgbox" << @@ -2461,7 +2483,7 @@ else if( message == "fullscreenaltf3" ) { KAction* action = qobject_cast<KAction*>(keys->action( "Window Operations Menu" )); - if (action==0) assert( false ); + assert( action != NULL ); QString shortcut = QString( "%1 (%2)" ).arg( action->text() ) .arg( action->globalShortcut().primary().toString()); args << "--msgbox" << @@ -2474,7 +2496,7 @@ type = "altf3warning"; } else - assert( false ); + abort(); if( !type.isEmpty()) { KConfig cfg( "kwin_dialogsrc" ); Index: layers.cpp =================================================================== --- kwin/layers.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/layers.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -216,6 +216,10 @@ cl[pos++] = (*it)->window(); rootInfo->setClientListStacking( cl, pos ); delete [] cl; + + // Make the cached stacking order invalid here, in case we need the new stacking order before we get + // the matching event, due to X being asynchronous. + x_stacking_dirty = true; } @@ -224,8 +228,8 @@ or of any other special kind are excluded. Also if the window doesn't accept focus it's excluded. */ -// TODO misleading name for this method -Client* Workspace::topClientOnDesktop( int desktop, bool unconstrained, bool only_normal ) const +// TODO misleading name for this method, too many slightly different ways to use it +Client* Workspace::topClientOnDesktop( int desktop, int screen, bool unconstrained, bool only_normal ) const { // TODO Q_ASSERT( block_stacking_updates == 0 ); ClientList list; @@ -239,6 +243,8 @@ { if( list.at( i )->isOnDesktop( desktop ) && list.at( i )->isShown( false )) { + if( screen != -1 && list.at( i )->screen() != screen ) + continue; if( !only_normal ) return list.at( i ); if( list.at( i )->wantsTabFocus() && !list.at( i )->isSpecialWindow()) @@ -281,7 +287,8 @@ most_recently_raised->isShown( true ) && c->isOnCurrentDesktop()) topmost = most_recently_raised; else - topmost = topClientOnDesktop( c->isOnAllDesktops() ? currentDesktop() : c->desktop()); + topmost = topClientOnDesktop( c->isOnAllDesktops() ? currentDesktop() : c->desktop(), + options->separateScreenFocus ? c->screen() : -1 ); if( c == topmost) lowerClient(c); @@ -720,30 +727,33 @@ return true; } -// Returns all windows in their stacking order on the root window, used only by compositing. -// TODO This possibly should be optimized to avoid the X roundtrip and building it every pass. -ToplevelList Workspace::compositingStackingOrder() const +// Returns all windows in their stacking order on the root window. +ToplevelList Workspace::xStackingOrder() const { + if( !x_stacking_dirty ) + return x_stacking; + x_stacking_dirty = false; + x_stacking.clear(); Window dummy; Window* windows = NULL; unsigned int count = 0; XQueryTree( display(), rootWindow(), &dummy, &dummy, &windows, &count ); - ToplevelList ret; // use our own stacking order, not the X one, as they may differ foreach( Client* c, stacking_order ) - ret.append( c ); + x_stacking.append( c ); for( unsigned int i = 0; i < count; ++i ) { if( Unmanaged* c = findUnmanaged( WindowMatchPredicate( windows[ i ] ))) - ret.append( c ); + x_stacking.append( c ); } foreach( Deleted* c, deleted ) - ret.append( c ); + x_stacking.append( c ); if( windows != NULL ) XFree( windows ); - return ret; + const_cast< Workspace* >( this )->checkUnredirect(); + return x_stacking; } //******************************* @@ -832,17 +842,22 @@ return DockLayer; if( isTopMenu()) return DockLayer; - // only raise fullscreen above docks if it's the topmost window in unconstrained stacking order, - // i.e. the window set to be topmost by the user (also includes transients of the fullscreen window) - const Client* ac = workspace()->mostRecentlyActivatedClient(); // instead of activeClient() - avoids flicker - const Client* top = workspace()->topClientOnDesktop( desktop(), true, false ); - if( isFullScreen() && ac != NULL && top != NULL - && ( ac == this || this->group() == ac->group()) - && ( top == this || this->group() == top->group())) + if( isActiveFullScreen()) return ActiveLayer; if( keepAbove()) return AboveLayer; return NormalLayer; } +bool Client::isActiveFullScreen() const + { + // only raise fullscreen above docks if it's the topmost window in unconstrained stacking order, + // i.e. the window set to be topmost by the user (also includes transients of the fullscreen window) + const Client* ac = workspace()->mostRecentlyActivatedClient(); // instead of activeClient() - avoids flicker + const Client* top = workspace()->topClientOnDesktop( workspace()->currentDesktop(), screen(), true, false ); + return( isFullScreen() && ac != NULL && top != NULL +// not needed, for xinerama && ( ac == this || this->group() == ac->group()) + && ( top == this || this->group() == top->group())); + } + } // namespace Index: activation.cpp =================================================================== --- kwin/activation.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/activation.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -884,6 +884,7 @@ decoration->activeChange(); updateMouseGrab(); updateUrgency(); // demand attention again if it's still urgent + workspace()->checkUnredirect(); } void Client::startupIdChanged() Index: unmanaged.h =================================================================== --- kwin/unmanaged.h (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/unmanaged.h (.../work/~seli/kwin11.1) (revision 880714) @@ -43,6 +43,7 @@ virtual QSize clientSize() const; protected: virtual void debug( kdbgstream& stream ) const; + virtual bool shouldUnredirect() const; private: virtual ~Unmanaged(); // use release() // handlers for X11 events Index: org.kde.KWin.xml =================================================================== --- kwin/org.kde.KWin.xml (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/org.kde.KWin.xml (.../work/~seli/kwin11.1) (revision 880714) @@ -44,7 +44,7 @@ <method name="toggleEffect"> <arg name="name" type="s" direction="in"/> </method> - <method name="reloadEffect"> + <method name="reconfigureEffect"> <arg name="name" type="s" direction="in"/> </method> <method name="loadedEffects"> @@ -53,6 +53,12 @@ <method name="listOfEffects"> <arg type="as" direction="out"/> </method> + <method name="compositingActive"> + <arg type="b" direction="out"/> + </method> + <method name="waitForCompositingSetup"> + <arg type="b" direction="out"/> + </method> <method name="decorationSupportedColors"> <arg type="ai" direction="out"/> <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QList<int>"/> Index: effects.cpp =================================================================== --- kwin/effects.cpp (.../KDE/4.1/kdebase/workspace/kwin) (revision 880714) +++ kwin/effects.cpp (.../work/~seli/kwin11.1) (revision 880714) @@ -85,14 +85,21 @@ if( shouldbeloaded ) effectsToBeLoaded.append( plugininfo.pluginName() ); } + QStringList newLoaded; // Then load those that should be loaded foreach( const QString &effectName, effectsToBeLoaded ) { if( !isEffectLoaded( effectName )) { loadEffect( effectName ); + newLoaded.append( effectName ); } } + foreach( const EffectPair &ep, loaded_effects ) + { + if( !newLoaded.contains( ep.first )) // don't reconfigure newly loaded effects + ep.second->reconfigure( Effect::ReconfigureAll ); + } } // the idea is that effects call this function again which calls the next one @@ -419,6 +426,11 @@ return Workspace::self()->desktopDown( desktop, wrap ); } +double EffectsHandlerImpl::animationTimeFactor() const + { + return options->animationTimeFactor(); + } + int EffectsHandlerImpl::displayWidth() const { return KWin::displayWidth(); @@ -607,7 +619,7 @@ return; } } - assert( false ); + abort(); } bool EffectsHandlerImpl::checkInputWindowEvent( XEvent* e ) @@ -882,13 +894,14 @@ kDebug( 1212 ) << "EffectsHandler::unloadEffect : Effect not loaded : " << name; } -void EffectsHandlerImpl::reloadEffect( const QString& name ) +void EffectsHandlerImpl::reconfigureEffect( const QString& name ) { - if( isEffectLoaded( name )) - { - unloadEffect( name ); - loadEffect( name ); - } + for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); ++it) + if ( (*it).first == name ) + { + (*it).second->reconfigure( Effect::ReconfigureAll ); + return; + } } bool EffectsHandlerImpl::isEffectLoaded( const QString& name ) @@ -1144,6 +1157,13 @@ return false; } +bool EffectWindowImpl::isMovableAcrossScreens() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + return c->isMovableAcrossScreens(); + return false; + } + bool EffectWindowImpl::isUserMove() const { if( Client* c = dynamic_cast< Client* >( toplevel ))
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor