Complete rewrite of flip switch.

* no more usage of OpenGL directly. Only highlevel API (except multiscreen :-()
 * better animations by adjusting the TimeLine's curve shape
 * new configuration options for window positions
 * Usage without tabbox (also supporting electric border)
 * Effect Frame showing the window title
 * many more things I have forgotten to mention
BUG: 187761

svn path=/trunk/KDE/kdebase/workspace/; revision=1000437
This commit is contained in:
Martin Gräßlin 2009-07-21 10:18:48 +00:00
parent e785ec1993
commit abe5c4ff04
8 changed files with 1284 additions and 574 deletions

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com>
Copyright (C) 2008, 2009 Martin Gräßlin <kde@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
@ -22,13 +22,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KWIN_FLIPSWITCH_H
#include <kwineffects.h>
#include <KShortcut>
#include <QQueue>
class KShortcut;
namespace KWin
{
class FlipSwitchEffect
: public Effect
: public QObject, public Effect
{
Q_OBJECT
public:
FlipSwitchEffect();
~FlipSwitchEffect();
@ -37,30 +42,80 @@ class FlipSwitchEffect
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 void tabBoxAdded( int mode );
virtual void tabBoxClosed();
virtual void tabBoxUpdated();
virtual void windowAdded( EffectWindow* w );
virtual void windowClosed( EffectWindow* w );
virtual bool borderActivated( ElectricBorder border );
virtual void grabbedKeyboardEvent( QKeyEvent* e );
static bool supported();
private Q_SLOTS:
void toggleActiveCurrent();
void toggleActiveAllDesktops();
void globalShortcutChangedCurrent( QKeySequence shortcut );
void globalShortcutChangedAll( QKeySequence shortcut );
private:
void paintWindowFlip( EffectWindow* w, bool draw = true, float opacity = 0.8 );
bool mActivated;
bool mAnimation;
int mFlipDuration;
bool animateFlip;
bool forward;
int selectedWindow;
bool start;
bool stop;
bool addFullRepaint;
int rearrangeWindows;
bool stopRequested;
bool startRequested;
bool twinview;
QRect area;
TimeLine timeLine;
Window input;
class ItemInfo;
enum SwitchingDirection
{
DirectionForward,
DirectionBackward
};
enum FlipSwitchMode
{
TabboxMode,
CurrentDesktopMode,
AllDesktopsMode
};
void setActive( bool activate, FlipSwitchMode mode );
bool isSelectableWindow( EffectWindow *w ) const;
void scheduleAnimation( const SwitchingDirection& direction, int distance = 1 );
void adjustWindowMultiScreen( const EffectWindow *w, WindowPaintData& data );
QQueue< SwitchingDirection> m_scheduledDirections;
EffectWindow* m_selectedWindow;
TimeLine m_timeLine;
TimeLine m_startStopTimeLine;
TimeLine::CurveShape m_currentAnimationShape;
QRect m_screenArea;
int m_activeScreen;
bool m_active;
bool m_start;
bool m_stop;
bool m_animation;
bool m_hasKeyboardGrab;
Window m_input;
FlipSwitchMode m_mode;
EffectFrame m_captionFrame;
QFont m_captionFont;
EffectWindowList m_flipOrderedWindows;
QHash< const EffectWindow*, ItemInfo* > m_windows;
// options
QList<ElectricBorder> m_borderActivate;
QList<ElectricBorder> m_borderActivateAll;
bool m_tabbox;
float m_angle;
float m_xPosition;
float m_yPosition;
bool m_windowTitle;
// Shortcuts
KShortcut m_shortcutCurrent;
KShortcut m_shortcutAll;
};
class FlipSwitchEffect::ItemInfo
{
public:
ItemInfo();
~ItemInfo();
bool deleted;
double opacity;
double brightness;
double saturation;
};
} // namespace

View file

@ -2,7 +2,7 @@
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com
Copyright (C) 2008, 2009 Martin Gräßlin <kde@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
@ -21,6 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwineffects.h>
#include <kconfiggroup.h>
#include <KAction>
#include <KActionCollection>
#include <QVBoxLayout>
@ -43,8 +45,26 @@ FlipSwitchEffectConfig::FlipSwitchEffectConfig(QWidget* parent, const QVariantLi
layout->addWidget(m_ui);
connect(m_ui->checkAnimateFlip, SIGNAL(stateChanged(int)), this, SLOT(changed()));
connect(m_ui->spinFlipDuration, SIGNAL(valueChanged(int)), this, SLOT(changed()));
// Shortcut config. The shortcut belongs to the component "kwin"!
m_actionCollection = new KActionCollection( this, KComponentData("kwin") );
KAction* a = ( KAction* )m_actionCollection->addAction( "FlipSwitchCurrent" );
a->setText( i18n( "Toggle Flip Switch (Current desktop)" ));
a->setGlobalShortcut( KShortcut(), KAction::ActiveShortcut );
KAction* b = ( KAction* )m_actionCollection->addAction( "FlipSwitchAll" );
b->setText( i18n( "Toggle Flip Switch (All desktops)" ));
b->setGlobalShortcut( KShortcut(), KAction::ActiveShortcut );
m_actionCollection->setConfigGroup( "FlipSwitch" );
m_actionCollection->setConfigGlobal( true );
m_ui->shortcutEditor->addCollection( m_actionCollection );
connect(m_ui->durationSpin, SIGNAL(valueChanged(int)), SLOT(changed()));
connect(m_ui->angleSpin, SIGNAL(valueChanged(int)), SLOT(changed()));
connect(m_ui->horizontalSlider, SIGNAL(valueChanged(int)), SLOT(changed()));
connect(m_ui->verticalSlider, SIGNAL(valueChanged(int)), SLOT(changed()));
connect(m_ui->windowTitleBox, SIGNAL(stateChanged(int)), SLOT(changed()));
connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() ));
load();
}
@ -59,18 +79,12 @@ void FlipSwitchEffectConfig::load()
KConfigGroup conf = EffectsHandler::effectConfig( "FlipSwitch" );
int flipDuration = conf.readEntry( "FlipDuration", 0 );
bool animateFlip = conf.readEntry( "AnimateFlip", true );
m_ui->spinFlipDuration->setValue( flipDuration );
m_ui->spinFlipDuration->setSuffix( ki18np ( " milisecond", " miliseconds" ) );
if( animateFlip )
{
m_ui->checkAnimateFlip->setCheckState( Qt::Checked );
}
else
{
m_ui->checkAnimateFlip->setCheckState( Qt::Unchecked );
}
m_ui->durationSpin->setValue( conf.readEntry( "Duration", 0 ));
m_ui->angleSpin->setValue( conf.readEntry( "Angle", 30 ));
m_ui->horizontalSlider->setValue( conf.readEntry( "XPosition", 33 ));
// slider bottom is 0, effect bottom is 100
m_ui->verticalSlider->setValue( 100 - conf.readEntry( "YPosition", 100 ));
m_ui->windowTitleBox->setChecked( conf.readEntry( "WindowTitle", true ));
emit changed(false);
}
@ -79,8 +93,14 @@ void FlipSwitchEffectConfig::save()
{
KConfigGroup conf = EffectsHandler::effectConfig( "FlipSwitch" );
conf.writeEntry( "FlipDuration", m_ui->spinFlipDuration->value() );
conf.writeEntry( "AnimateFlip", m_ui->checkAnimateFlip->checkState() == Qt::Checked ? true : false );
conf.writeEntry( "Duration", m_ui->durationSpin->value() );
conf.writeEntry( "Angle", m_ui->angleSpin->value() );
conf.writeEntry( "XPosition", m_ui->horizontalSlider->value() );
// slider bottom is 0, effect bottom is 100
conf.writeEntry( "YPosition", 100 - m_ui->verticalSlider->value() );
conf.writeEntry( "WindowTitle", m_ui->windowTitleBox->isChecked() );
m_ui->shortcutEditor->save();
conf.sync();
@ -90,8 +110,13 @@ void FlipSwitchEffectConfig::save()
void FlipSwitchEffectConfig::defaults()
{
m_ui->spinFlipDuration->setValue( 0 );
m_ui->checkAnimateFlip->setCheckState( Qt::Checked );
m_ui->durationSpin->setValue( 0 );
m_ui->angleSpin->setValue( 30 );
m_ui->horizontalSlider->setValue( 33 );
// slider bottom is 0, effect bottom is 100
m_ui->verticalSlider->setValue( 0 );
m_ui->windowTitleBox->setChecked( true );
m_ui->shortcutEditor->allDefault();
emit changed(true);
}

View file

@ -2,7 +2,7 @@
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com
Copyright (C) 2008, 2009 Martin Gräßlin <kde@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
@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "ui_flipswitch_config.h"
class KActionCollection;
namespace KWin
{
@ -49,6 +51,7 @@ class FlipSwitchEffectConfig : public KCModule
private:
FlipSwitchEffectConfigForm* m_ui;
KActionCollection* m_actionCollection;
};
} // namespace

View file

@ -1,60 +1,219 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KWin::FlipSwitchEffectConfigForm</class>
<widget class="QWidget" name="KWin::FlipSwitchEffectConfigForm" >
<property name="geometry" >
<widget class="QWidget" name="KWin::FlipSwitchEffectConfigForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>267</width>
<height>105</height>
<width>400</width>
<height>316</height>
</rect>
</property>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout">
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Appearance</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="0" colspan="2" >
<widget class="QCheckBox" name="checkAnimateFlip" >
<property name="text" >
<string>Animate &amp;flip</string>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Flip animation duration:</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>F&amp;lip animation duration:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<cstring>spinFlipDuration</cstring>
<property name="buddy">
<cstring>durationSpin</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="KIntSpinBox" name="spinFlipDuration" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="0" column="1">
<widget class="KIntSpinBox" name="durationSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="specialValueText" >
<property name="specialValueText">
<string comment="Duration of flip animation">Default</string>
</property>
<property name="maximum" >
<property name="maximum">
<number>5000</number>
</property>
<property name="singleStep" >
<property name="singleStep">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Angle:</string>
</property>
<property name="buddy">
<cstring>angleSpin</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="KIntSpinBox" name="angleSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> °</string>
</property>
<property name="maximum">
<number>360</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Horizontal position of front:</string>
</property>
<property name="buddy">
<cstring>horizontalSlider</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSlider" name="horizontalSlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Left</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>Right</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Vertical position of front:</string>
</property>
<property name="buddy">
<cstring>verticalSlider</cstring>
</property>
</widget>
</item>
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QSlider" name="verticalSlider">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Top</string>
</property>
</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>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Bottom</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="windowTitleBox">
<property name="text">
<string>Display window &amp;titles</string>
</property>
<property name="shortcut">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Activation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="KWin::GlobalShortcutsEditor" name="shortcutEditor" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@ -66,10 +225,15 @@
<extends>QSpinBox</extends>
<header>knuminput.h</header>
</customwidget>
<customwidget>
<class>KWin::GlobalShortcutsEditor</class>
<extends>QWidget</extends>
<header location="global">kwineffects.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>checkAnimateFlip</tabstop>
<tabstop>spinFlipDuration</tabstop>
<tabstop>durationSpin</tabstop>
</tabstops>
<resources/>
<connections/>

View file

@ -338,7 +338,8 @@ void KWinCompositingConfig::loadGeneralTab()
ui.windowSwitchingCombo->setCurrentIndex( 1 );
if( effectEnabled( "coverswitch", effectconfig ))
ui.windowSwitchingCombo->setCurrentIndex( 3 );
if( effectEnabled( "flipswitch", effectconfig ))
KConfigGroup flipswitchconfig(mKWinConfig, "Effect-FlipSwitch");
if( effectEnabled( "flipswitch", effectconfig ) && flipswitchconfig.readEntry("TabBox", false))
ui.windowSwitchingCombo->setCurrentIndex( 4 );
KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
if( effectEnabled( "presentwindows", effectconfig ) && presentwindowsconfig.readEntry("TabBox", false) )
@ -490,19 +491,18 @@ void KWinCompositingConfig::saveGeneralTab()
int windowSwitcher = ui.windowSwitchingCombo->currentIndex();
bool presentWindowSwitching = false;
bool flipSwitch = 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
@ -510,16 +510,15 @@ void KWinCompositingConfig::saveGeneralTab()
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
flipSwitch = true;
effectconfig.writeEntry("kwin4_effect_boxswitchEnabled", false);
effectconfig.writeEntry("kwin4_effect_coverswitchEnabled", false);
effectconfig.writeEntry("kwin4_effect_flipswitchEnabled", true);
@ -527,6 +526,8 @@ void KWinCompositingConfig::saveGeneralTab()
}
KConfigGroup presentwindowsconfig(mKWinConfig, "Effect-PresentWindows");
presentwindowsconfig.writeEntry("TabBox", presentWindowSwitching);
KConfigGroup flipswitchconfig(mKWinConfig, "Effect-FlipSwitch");
flipswitchconfig.writeEntry("TabBox", flipSwitch);
int desktopSwitcher = ui.desktopSwitchingCombo->currentIndex();
switch( desktopSwitcher )

View file

@ -214,6 +214,19 @@ void KWinScreenEdgesConfig::monitorInit()
monitorAddItem( services.first()->name() + " - " + i18n( "Cylinder" ));
monitorAddItem( services.first()->name() + " - " + i18n( "Sphere" ));
}
services = trader->query( "KWin/Effect", "[X-KDE-PluginInfo-Name] == 'kwin4_effect_flipswitch'" );
if( services.isEmpty() )
{
// adding empty strings in case the effect is not found
// TODO: after string freeze add a info that the effect is missing
monitorAddItem( QString() );
monitorAddItem( QString() );
}
else
{
monitorAddItem( services.first()->name() + " - " + i18n( "All Desktops" ));
monitorAddItem( services.first()->name() + " - " + i18n( "Current Desktop" ));
}
monitorShowEvent();
}
@ -291,6 +304,25 @@ void KWinScreenEdgesConfig::monitorLoad()
{
monitorChangeEdge( ElectricBorder( i ), int( Sphere ) );
}
// Flip Switch
KConfigGroup flipSwitchConfig( m_config, "Effect-FlipSwitch" );
list.clear();
// FlipSwitch BorderActivateAll
list.append( int( ElectricNone ) );
list = flipSwitchConfig.readEntry( "BorderActivateAll", list );
foreach( int i, list )
{
monitorChangeEdge( ElectricBorder( i ), int( FlipSwitchAll ) );
}
// FlipSwitch BorderActivate
list.clear();
list.append( int( ElectricNone ) );
list = flipSwitchConfig.readEntry( "BorderActivate", list );
foreach( int i, list )
{
monitorChangeEdge( ElectricBorder( i ), int( FlipSwitchCurrent ) );
}
}
void KWinScreenEdgesConfig::monitorSaveAction( int edge, const QString& configName )
@ -339,6 +371,13 @@ void KWinScreenEdgesConfig::monitorSave()
monitorCheckEffectHasEdge( int( Cylinder )));
cubeConfig.writeEntry( "BorderActivateSphere",
monitorCheckEffectHasEdge( int( Sphere )));
// Flip Switch
KConfigGroup flipSwitchConfig( m_config, "Effect-FlipSwitch" );
flipSwitchConfig.writeEntry( "BorderActivateAll",
monitorCheckEffectHasEdge( int( FlipSwitchAll )));
flipSwitchConfig.writeEntry( "BorderActivate",
monitorCheckEffectHasEdge( int( FlipSwitchCurrent )));
}
void KWinScreenEdgesConfig::monitorDefaults()
@ -373,6 +412,11 @@ void KWinScreenEdgesConfig::monitorShowEvent()
monitorItemSetEnabled( int( Cube ), enabled );
monitorItemSetEnabled( int( Cylinder ), enabled );
monitorItemSetEnabled( int( Sphere ), enabled );
// Flip Switch
enabled = effectEnabled( "flipswitch", config );
monitorItemSetEnabled( int( FlipSwitchAll ), enabled );
monitorItemSetEnabled( int( FlipSwitchCurrent ), enabled );
}
else // Compositing disabled
{
@ -382,6 +426,8 @@ void KWinScreenEdgesConfig::monitorShowEvent()
monitorItemSetEnabled( int( Cube ), false );
monitorItemSetEnabled( int( Cylinder ), false );
monitorItemSetEnabled( int( Sphere ), false );
monitorItemSetEnabled( int( FlipSwitchAll ), false );
monitorItemSetEnabled( int( FlipSwitchCurrent ), false );
}
}

View file

@ -70,7 +70,9 @@ class KWinScreenEdgesConfig : public KCModule
DesktopGrid,
Cube,
Cylinder,
Sphere
Sphere,
FlipSwitchAll,
FlipSwitchCurrent
};
bool effectEnabled( const QString& effect, const KConfigGroup& cfg ) const;