summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilip Wieladek <Filip@Wieladek.com>2012-07-27 05:58:21 (GMT)
committerMartin Gräßlin <mgraesslin@kde.org>2012-10-26 07:47:22 (GMT)
commit49b350df9cd8322d2fbb140de50c985a31e7a5c9 (patch)
tree2db4d23ffbbe02ac4d287d08d19593e84a822a36
parent4363db498bb4343364b94eb33ba18e03a305b94c (diff)
Mouse Click animation effect
An effect which visualy animates when a mouse button is pressed or released. REVIEW: 105780 BUG: 309006 FIXED-IN: 4.10
-rw-r--r--kwin/effects/CMakeLists.txt1
-rw-r--r--kwin/effects/configs_builtins.cpp2
-rw-r--r--kwin/effects/mouseclick/CMakeLists.txt27
-rw-r--r--kwin/effects/mouseclick/mouseclick.cpp315
-rw-r--r--kwin/effects/mouseclick/mouseclick.desktop17
-rw-r--r--kwin/effects/mouseclick/mouseclick.h141
-rw-r--r--kwin/effects/mouseclick/mouseclick_config.cpp162
-rw-r--r--kwin/effects/mouseclick/mouseclick_config.desktop9
-rw-r--r--kwin/effects/mouseclick/mouseclick_config.h58
-rw-r--r--kwin/effects/mouseclick/mouseclick_config.ui285
10 files changed, 1017 insertions, 0 deletions
diff --git a/kwin/effects/CMakeLists.txt b/kwin/effects/CMakeLists.txt
index 9d0f73b..402d5c2 100644
--- a/kwin/effects/CMakeLists.txt
+++ b/kwin/effects/CMakeLists.txt
@@ -134,6 +134,7 @@ if( NOT KWIN_MOBILE_EFFECTS )
include( invert/CMakeLists.txt )
include( lookingglass/CMakeLists.txt )
include( magnifier/CMakeLists.txt )
+ include( mouseclick/CMakeLists.txt )
include( mousemark/CMakeLists.txt )
include( sheet/CMakeLists.txt )
include( snaphelper/CMakeLists.txt )
diff --git a/kwin/effects/configs_builtins.cpp b/kwin/effects/configs_builtins.cpp
index 22fbdf7..a762c48 100644
--- a/kwin/effects/configs_builtins.cpp
+++ b/kwin/effects/configs_builtins.cpp
@@ -45,6 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "invert/invert_config.h"
#include "lookingglass/lookingglass_config.h"
#include "magnifier/magnifier_config.h"
+#include "mouseclick/mouseclick_config.h"
#include "mousemark/mousemark_config.h"
#include "trackmouse/trackmouse_config.h"
#include "wobblywindows/wobblywindows_config.h"
@@ -79,6 +80,7 @@ KWIN_EFFECT_CONFIG_MULTIPLE(builtins,
KWIN_EFFECT_CONFIG_SINGLE(glide, GlideEffectConfig)
KWIN_EFFECT_CONFIG_SINGLE(invert, InvertEffectConfig)
KWIN_EFFECT_CONFIG_SINGLE(lookingglass, LookingGlassEffectConfig)
+ KWIN_EFFECT_CONFIG_SINGLE(mouseclick, MouseClickEffectConfig)
KWIN_EFFECT_CONFIG_SINGLE(magnifier, MagnifierEffectConfig)
KWIN_EFFECT_CONFIG_SINGLE(mousemark, MouseMarkEffectConfig)
KWIN_EFFECT_CONFIG_SINGLE(trackmouse, TrackMouseEffectConfig)
diff --git a/kwin/effects/mouseclick/CMakeLists.txt b/kwin/effects/mouseclick/CMakeLists.txt
new file mode 100644
index 0000000..b4cace8
--- /dev/null
+++ b/kwin/effects/mouseclick/CMakeLists.txt
@@ -0,0 +1,27 @@
+##########################
+## mouse click effect
+##########################
+
+# Source files
+set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources}
+ mouseclick/mouseclick.cpp
+ )
+
+# .desktop files
+install( FILES
+ mouseclick/mouseclick.desktop
+ DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
+
+##########################
+## configurtion dialog
+##########################
+
+# Source files
+set( kwin4_effect_builtins_config_sources ${kwin4_effect_builtins_config_sources}
+ mouseclick/mouseclick_config.cpp
+ mouseclick/mouseclick_config.ui
+ )
+
+install( FILES
+ mouseclick/mouseclick_config.desktop
+ DESTINATION ${SERVICES_INSTALL_DIR}/kwin )
diff --git a/kwin/effects/mouseclick/mouseclick.cpp b/kwin/effects/mouseclick/mouseclick.cpp
new file mode 100644
index 0000000..3739d46
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick.cpp
@@ -0,0 +1,315 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2012 Filip Wieladek <wattos@gmail.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 "mouseclick.h"
+
+#include <kwinconfig.h>
+#include <kwinglutils.h>
+
+#include <KDE/KAction>
+#include <KDE/KActionCollection>
+#include <KDE/KConfigGroup>
+
+#include <math.h>
+
+namespace KWin
+{
+
+KWIN_EFFECT(mouseclick, MouseClickEffect)
+KWIN_EFFECT_SUPPORTED(mouseclick, MouseClickEffect::supported())
+
+MouseClickEffect::MouseClickEffect()
+{
+ m_enabled = false;
+ KActionCollection* actionCollection = new KActionCollection(this);
+ KAction* a = static_cast<KAction*>(actionCollection->addAction("ToggleMouseClick"));
+ a->setText(i18n("Toggle Effect"));
+ a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Asterisk));
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleEnabled()));
+ connect(effects, SIGNAL(mouseChanged(QPoint, QPoint, Qt::MouseButtons, Qt::MouseButtons, Qt::KeyboardModifiers, Qt::KeyboardModifiers)),
+ this, SLOT(slotMouseChanged(QPoint, QPoint, Qt::MouseButtons, Qt::MouseButtons, Qt::KeyboardModifiers, Qt::KeyboardModifiers)));
+ reconfigure(ReconfigureAll);
+
+ m_buttons[0] = new MouseButton(i18n("Left"), Qt::LeftButton);
+ m_buttons[1] = new MouseButton(i18n("Right"), Qt::RightButton);
+ m_buttons[2] = new MouseButton(i18n("Middle"), Qt::MiddleButton);
+}
+
+MouseClickEffect::~MouseClickEffect()
+{
+ effects->stopMousePolling();
+ foreach (const MouseEvent* click, m_clicks) {
+ delete click;
+ }
+ m_clicks.clear();
+
+ for (int i = 0; i < BUTTON_COUNT; ++i) {
+ delete m_buttons[i];
+ }
+}
+
+bool MouseClickEffect::supported()
+{
+ return effects->isOpenGLCompositing();
+}
+
+void MouseClickEffect::reconfigure(ReconfigureFlags)
+{
+ KConfigGroup conf = EffectsHandler::effectConfig("MouseClick");
+ m_colors[0] = conf.readEntry("Color1", QColor(Qt::red));
+ m_colors[1] = conf.readEntry("Color2", QColor(Qt::green));
+ m_colors[2] = conf.readEntry("Color3", QColor(Qt::blue));
+ m_lineWidth = conf.readEntry("LineWidth", 1.f);
+ m_ringLife = conf.readEntry("RingLife", 300);
+ m_ringMaxSize = conf.readEntry("RingSize", 20);
+ m_ringCount = conf.readEntry("RingCount", 2);
+ m_showText = conf.readEntry("ShowText", true);
+ m_font = conf.readEntry("Font", QFont());
+}
+
+void MouseClickEffect::prePaintScreen(ScreenPrePaintData& data, int time)
+{
+ foreach (MouseEvent* click, m_clicks) {
+ click->m_time += time;
+ }
+
+ for (int i = 0; i < BUTTON_COUNT; ++i) {
+ if (m_buttons[i]->m_isPressed) {
+ m_buttons[i]->m_time += time;
+ }
+ }
+
+ while (m_clicks.size() > 0) {
+ MouseEvent* first = m_clicks[0];
+ if (first->m_time <= m_ringLife) {
+ break;
+ }
+ m_clicks.pop_front();
+ delete first;
+ }
+
+ effects->prePaintScreen(data, time);
+}
+
+void MouseClickEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
+{
+ effects->paintScreen(mask, region, data);
+
+ paintScreenSetup(mask, region, data);
+ foreach (const MouseEvent* click, m_clicks) {
+ for (int i = 0; i < m_ringCount; ++i) {
+ float alpha = computeAlpha(click, i);
+ float size = computeRadius(click, i);
+ if (size > 0 && alpha > 0) {
+ QColor color = m_colors[click->m_button];
+ color.setAlphaF(alpha);
+ drawCircle(color, click->m_pos.x(), click->m_pos.y(), size);
+ }
+ }
+
+ if (m_showText && click->m_frame) {
+ float frameAlpha = (click->m_time * 2.0f - m_ringLife) / m_ringLife;
+ frameAlpha = frameAlpha < 0 ? 1 : -(frameAlpha * frameAlpha) + 1;
+ click->m_frame->render(infiniteRegion(), frameAlpha, frameAlpha);
+ }
+ }
+ paintScreenFinish(mask, region, data);
+}
+
+void MouseClickEffect::postPaintScreen()
+{
+ effects->postPaintScreen();
+ repaint();
+}
+
+float MouseClickEffect::computeRadius(const MouseEvent* click, int ring)
+{
+ float ringDistance = m_ringLife / (m_ringCount * 3);
+ if (click->m_press) {
+ return ((click->m_time - ringDistance * ring) / m_ringLife) * m_ringMaxSize;
+ }
+ return ((m_ringLife - click->m_time - ringDistance * ring) / m_ringLife) * m_ringMaxSize;
+}
+
+float MouseClickEffect::computeAlpha(const MouseEvent* click, int ring)
+{
+ float ringDistance = m_ringLife / (m_ringCount * 3);
+ return (m_ringLife - (float)click->m_time - ringDistance * (ring)) / m_ringLife;
+}
+
+void MouseClickEffect::slotMouseChanged(const QPoint& pos, const QPoint&,
+ Qt::MouseButtons buttons, Qt::MouseButtons oldButtons,
+ Qt::KeyboardModifiers, Qt::KeyboardModifiers)
+{
+ MouseEvent* m = NULL;
+ for (int i = 0; i < BUTTON_COUNT; ++i) {
+ MouseButton* b = m_buttons[i];
+ if (isPressed(b->m_button, buttons, oldButtons)) {
+ m = new MouseEvent(i, pos, 0, createEffectFrame(pos, b->m_labelDown), true);
+ } else if (isReleased(b->m_button, buttons, oldButtons) && b->m_time > m_ringLife) {
+ m = new MouseEvent(i, pos, 0, createEffectFrame(pos, b->m_labelUp), false);
+ }
+ b->setPressed(b->m_button & buttons);
+ }
+
+ if (m) {
+ m_clicks.append(m);
+ }
+ repaint();
+}
+
+EffectFrame* MouseClickEffect::createEffectFrame(const QPoint& pos, const QString& text) {
+ if (!m_showText) {
+ return NULL;
+ }
+ QPoint point(pos.x() + m_ringMaxSize, pos.y());
+ EffectFrame* frame = effects->effectFrame(EffectFrameStyled, false, point, Qt::AlignLeft);
+ frame->setFont(m_font);
+ frame->setText(text);
+ return frame;
+}
+
+void MouseClickEffect::repaint()
+{
+ if (m_clicks.size() > 0) {
+ int xmin = effects->workspaceWidth();
+ int ymin = effects->workspaceHeight();
+ int xmax = 0;
+ int ymax = 0;
+ int yfontMax = 0;
+ foreach (MouseEvent* click, m_clicks) {
+ QRect fontGeo = click->m_frame->geometry();
+ xmin = qMin<int>(xmin, click->m_pos.x());
+ ymin = qMin<int>(ymin, click->m_pos.y());
+ xmax = qMax<int>(xmax, click->m_pos.x() + (fontGeo.width() + 10));
+ ymax = qMax<int>(ymax, click->m_pos.y());
+ yfontMax = qMax<int>(yfontMax, fontGeo.height() + 10);
+ }
+ int radius = m_ringMaxSize + m_lineWidth;
+ int yradius = yfontMax / 2 > radius ? yfontMax / 2 : radius;
+ QRect repaint(xmin - radius, ymin - yradius, xmax - xmin + radius * 2 , ymax - ymin + yradius * 2);
+ effects->addRepaint(repaint);
+ }
+}
+
+bool MouseClickEffect::isReleased(Qt::MouseButtons button, Qt::MouseButtons buttons, Qt::MouseButtons oldButtons)
+{
+ return !(button & buttons) && (button & oldButtons);
+}
+
+bool MouseClickEffect::isPressed(Qt::MouseButtons button, Qt::MouseButtons buttons, Qt::MouseButtons oldButtons)
+{
+ return (button & buttons) && !(button & oldButtons);
+}
+
+void MouseClickEffect::toggleEnabled()
+{
+ m_enabled = !m_enabled;
+ if (m_clicks.size() > 0) {
+ foreach (const MouseEvent* click, m_clicks) {
+ delete click;
+ }
+ }
+ m_clicks.clear();
+
+ for (int i = 0; i < BUTTON_COUNT; ++i) {
+ m_buttons[i]->m_time = 0;
+ m_buttons[i]->m_isPressed = false;
+ }
+
+ if (m_enabled) {
+ effects->startMousePolling();
+ } else {
+ effects->stopMousePolling();
+ }
+}
+
+bool MouseClickEffect::isActive() const
+{
+ return m_enabled && (m_clicks.size() > 0);
+}
+
+void MouseClickEffect::drawCircle(const QColor& color, float cx, float cy, float r)
+{
+ drawCircleGl(color, cx, cy, r);
+}
+
+void MouseClickEffect::paintScreenSetup(int mask, QRegion region, ScreenPaintData& data)
+{
+ paintScreenSetupGl(mask, region, data);
+}
+
+void MouseClickEffect::paintScreenFinish(int mask, QRegion region, ScreenPaintData& data)
+{
+ paintScreenFinishGl(mask, region, data);
+}
+
+void MouseClickEffect::drawCircleGl(const QColor& color, float cx, float cy, float r)
+{
+ static int num_segments = 80;
+ static float theta = 2 * 3.1415926 / float(num_segments);
+ static float c = cosf(theta); //precalculate the sine and cosine
+ static float s = sinf(theta);
+ float t;
+
+ float x = r;//we start at angle = 0
+ float y = 0;
+
+ GLVertexBuffer* vbo = GLVertexBuffer::streamingBuffer();
+ vbo->reset();
+ vbo->setUseColor(true);
+ vbo->setColor(color);
+ QVector<float> verts;
+ verts.reserve(num_segments * 2);
+
+ for (int ii = 0; ii < num_segments; ++ii) {
+ verts << x + cx << y + cy;//output vertex
+ //apply the rotation matrix
+ t = x;
+ x = c * x - s * y;
+ y = s * t + c * y;
+ }
+ vbo->setData(verts.size() / 2, 2, verts.data(), NULL);
+ vbo->render(GL_LINE_LOOP);
+}
+
+void MouseClickEffect::paintScreenSetupGl(int, QRegion, ScreenPaintData&)
+{
+ if (ShaderManager::instance()->isValid()) {
+ ShaderManager::instance()->pushShader(ShaderManager::ColorShader);
+ }
+
+ glLineWidth(m_lineWidth);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+}
+
+void MouseClickEffect::paintScreenFinishGl(int, QRegion, ScreenPaintData&)
+{
+ glDisable(GL_BLEND);
+
+ if (ShaderManager::instance()->isValid()) {
+ ShaderManager::instance()->popShader();
+ }
+}
+
+} // namespace
+
+#include "mouseclick.moc"
diff --git a/kwin/effects/mouseclick/mouseclick.desktop b/kwin/effects/mouseclick/mouseclick.desktop
new file mode 100644
index 0000000..4bfbfd2
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Name=Mouse Click Animation
+Icon=preferences-system-windows-effect-mouseclick
+
+Comment=Creates an animation whenever a mouse button is clicked. This is useful for screenrecordings/presentations.
+
+Type=Service
+X-KDE-ServiceTypes=KWin/Effect
+X-KDE-PluginInfo-Author=Filip Wieladek
+X-KDE-PluginInfo-Email=Wattos@gmail.com
+X-KDE-PluginInfo-Name=kwin4_effect_mouseclick
+X-KDE-PluginInfo-Version=0.1.0
+X-KDE-PluginInfo-Category=Accessibility
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=false
+X-KDE-Library=kwin4_effect_builtins
diff --git a/kwin/effects/mouseclick/mouseclick.h b/kwin/effects/mouseclick/mouseclick.h
new file mode 100644
index 0000000..8695d37
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick.h
@@ -0,0 +1,141 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2012 Filip Wieladek <wattos@gmail.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_MOUSECLICK_H
+#define KWIN_MOUSECLICK_H
+
+#include <kwineffects.h>
+#include <kwinglutils.h>
+#include <kwinxrenderutils.h>
+#include <KLocalizedString>
+
+namespace KWin
+{
+
+#define BUTTON_COUNT 3
+
+class MouseEvent
+{
+public:
+ int m_button;
+ QPoint m_pos;
+ int m_time;
+ EffectFrame* m_frame;
+ bool m_press;
+public:
+ MouseEvent(int button, QPoint point, int time, EffectFrame* frame, bool press)
+ : m_button(button),
+ m_pos(point),
+ m_time(time),
+ m_frame(frame),
+ m_press(press)
+ {};
+
+ ~MouseEvent()
+ {
+ delete m_frame;
+ }
+};
+
+class MouseButton
+{
+public:
+ QString m_labelUp;
+ QString m_labelDown;
+ Qt::MouseButtons m_button;
+ bool m_isPressed;
+ int m_time;
+public:
+ MouseButton(QString label, Qt::MouseButtons button)
+ : m_labelUp(label),
+ m_labelDown(label),
+ m_button(button),
+ m_isPressed(false),
+ m_time(0)
+ {
+ m_labelDown.append(i18n("↓"));
+ m_labelUp.append(i18n("↑"));
+ };
+
+ inline void setPressed(bool pressed)
+ {
+ if (m_isPressed != pressed) {
+ m_isPressed = pressed;
+ if (pressed)
+ m_time = 0;
+ }
+ }
+};
+
+class MouseClickEffect
+ : public Effect
+{
+ Q_OBJECT
+public:
+ MouseClickEffect();
+ ~MouseClickEffect();
+ virtual void reconfigure(ReconfigureFlags);
+ virtual void prePaintScreen(ScreenPrePaintData& data, int time);
+ virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data);
+ virtual void postPaintScreen();
+ virtual bool isActive() const;
+
+ static bool supported();
+private slots:
+ void toggleEnabled();
+ void slotMouseChanged(const QPoint& pos, const QPoint& old,
+ Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
+ Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers);
+private:
+ EffectFrame* createEffectFrame(const QPoint& pos, const QString& text);
+ inline void drawCircle(const QColor& color, float cx, float cy, float r);
+ inline void paintScreenSetup(int mask, QRegion region, ScreenPaintData& data);
+ inline void paintScreenFinish(int mask, QRegion region, ScreenPaintData& data);
+
+ inline bool isReleased(Qt::MouseButtons button, Qt::MouseButtons buttons, Qt::MouseButtons oldButtons);
+ inline bool isPressed(Qt::MouseButtons button, Qt::MouseButtons buttons, Qt::MouseButtons oldButtons);
+
+ inline float computeRadius(const MouseEvent* click, int ring);
+ inline float computeAlpha(const MouseEvent* click, int ring);
+
+ void repaint();
+
+ void drawCircleGl(const QColor& color, float cx, float cy, float r);
+ void paintScreenSetupGl(int mask, QRegion region, ScreenPaintData& data);
+ void paintScreenFinishGl(int mask, QRegion region, ScreenPaintData& data);
+
+ QColor m_colors[BUTTON_COUNT];
+ int m_ringCount;
+ float m_lineWidth;
+ float m_ringLife;
+ float m_ringMaxSize;
+ bool m_showText;
+ QFont m_font;
+
+ QList<MouseEvent*> m_clicks;
+ MouseButton* m_buttons[BUTTON_COUNT];
+
+ bool m_enabled;
+
+};
+
+} // namespace
+
+#endif
diff --git a/kwin/effects/mouseclick/mouseclick_config.cpp b/kwin/effects/mouseclick/mouseclick_config.cpp
new file mode 100644
index 0000000..b8d8eeb
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick_config.cpp
@@ -0,0 +1,162 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2012 Filip Wieladek <wattos@gmail.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 "mouseclick_config.h"
+
+#include <kwineffects.h>
+
+#include <KDE/KActionCollection>
+#include <KDE/KAction>
+#include <KDE/KConfigGroup>
+#include <KDE/KShortcutsEditor>
+
+#include <QWidget>
+
+namespace KWin
+{
+
+KWIN_EFFECT_CONFIG_FACTORY
+
+MouseClickEffectConfigForm::MouseClickEffectConfigForm(QWidget* parent) : QWidget(parent)
+{
+ setupUi(this);
+}
+
+MouseClickEffectConfig::MouseClickEffectConfig(QWidget* parent, const QVariantList& args) :
+ KCModule(EffectFactory::componentData(), parent, args)
+{
+ m_ui = new MouseClickEffectConfigForm(this);
+
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ layout->addWidget(m_ui);
+
+ connect(m_ui->editor, SIGNAL(keyChange()), this, SLOT(changed()));
+ connect(m_ui->button1_color_input, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
+ connect(m_ui->button2_color_input, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
+ connect(m_ui->button3_color_input, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
+ connect(m_ui->ring_line_width_input, SIGNAL(valueChanged(double)), this, SLOT(changed()));
+ connect(m_ui->ring_duration_input, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(m_ui->ring_radius_input, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(m_ui->ring_count_input, SIGNAL(valueChanged(int)), this, SLOT(changed()));
+ connect(m_ui->showtext_input, SIGNAL(toggled(bool)), this, SLOT(changed()));
+ connect(m_ui->font_input, SIGNAL(fontSelected(QFont)), this, SLOT(changed()));
+
+ // Shortcut config. The shortcut belongs to the component "kwin"!
+ m_actionCollection = new KActionCollection(this, KComponentData("kwin"));
+
+ KAction* a = static_cast<KAction*>(m_actionCollection->addAction("ToggleMouseClick"));
+ a->setText(i18n("Toggle Effect"));
+ a->setProperty("isConfigurationAction", true);
+ a->setGlobalShortcut(KShortcut(Qt::META + Qt::Key_Asterisk));
+
+ m_ui->editor->addCollection(m_actionCollection);
+ load();
+}
+
+MouseClickEffectConfig::~MouseClickEffectConfig()
+{
+ // Undo (only) unsaved changes to global key shortcuts
+ m_ui->editor->undoChanges();
+}
+
+void MouseClickEffectConfig::load()
+{
+ KCModule::load();
+
+ KConfigGroup conf = EffectsHandler::effectConfig("MouseClick");
+
+ QColor color1 = conf.readEntry("Color1", QColor(Qt::red));
+ QColor color2 = conf.readEntry("Color2", QColor(Qt::green));
+ QColor color3 = conf.readEntry("Color3", QColor(Qt::blue));
+
+ float lineWidth = conf.readEntry("LineWidth", 1.f);
+ float ringLife = conf.readEntry("RingLife", 300);
+ float ringSize = conf.readEntry("RingSize", 20);
+
+ bool showText = conf.readEntry("ShowText", true);
+ int ringCount = conf.readEntry("RingCount", 2);
+ QFont font = conf.readEntry("Font", QFont());
+
+ m_ui->button1_color_input->setColor(color1);
+ m_ui->button2_color_input->setColor(color2);
+ m_ui->button3_color_input->setColor(color3);
+ m_ui->ring_line_width_input->setValue(lineWidth);
+ m_ui->ring_duration_input->setValue(ringLife);
+ m_ui->ring_radius_input->setValue(ringSize);
+ m_ui->ring_count_input->setValue(ringCount);
+
+ m_ui->showtext_input->setChecked(showText);
+ m_ui->font_input->setFont(font);
+
+ m_ui->ring_line_width_input->setSuffix(i18n(" pixels"));
+ m_ui->ring_duration_input->setSuffix(ki18np(" millisecond", " milliseconds"));
+ m_ui->ring_radius_input->setSuffix(ki18np(" pixel", " pixels"));
+
+ emit changed(false);
+}
+
+void MouseClickEffectConfig::save()
+{
+ //KCModule::save();
+
+ KConfigGroup conf = EffectsHandler::effectConfig("MouseClick");
+
+ conf.writeEntry("Color1", m_ui->button1_color_input->color());
+ conf.writeEntry("Color2", m_ui->button2_color_input->color());
+ conf.writeEntry("Color3", m_ui->button3_color_input->color());
+
+ conf.writeEntry("LineWidth", m_ui->ring_line_width_input->value());
+ conf.writeEntry("RingLife", m_ui->ring_duration_input->value());
+ conf.writeEntry("RingSize", m_ui->ring_radius_input->value());
+ conf.writeEntry("RingCount", m_ui->ring_count_input->value());
+
+ conf.writeEntry("ShowText", m_ui->showtext_input->isChecked());
+ conf.writeEntry("Font", m_ui->font_input->font());
+
+ m_actionCollection->writeSettings();
+ m_ui->editor->save(); // undo() will restore to this state from now on
+
+ conf.sync();
+
+ emit changed(false);
+ EffectsHandler::sendReloadMessage("mouseclick");
+}
+
+void MouseClickEffectConfig::defaults()
+{
+ m_ui->button1_color_input->setColor(Qt::red);
+ m_ui->button2_color_input->setColor(Qt::green);
+ m_ui->button3_color_input->setColor(Qt::blue);
+
+ m_ui->ring_line_width_input->setValue(1.f);
+ m_ui->ring_duration_input->setValue(300);
+ m_ui->ring_radius_input->setValue(20);
+ m_ui->ring_count_input->setValue(2);
+
+ m_ui->showtext_input->setChecked(true);
+ m_ui->font_input->setFont(QFont());
+
+ emit changed(true);
+}
+
+
+} // namespace
+
+#include "mouseclick_config.moc"
diff --git a/kwin/effects/mouseclick/mouseclick_config.desktop b/kwin/effects/mouseclick/mouseclick_config.desktop
new file mode 100644
index 0000000..ed02a76
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick_config.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=KCModule
+
+X-KDE-Library=kcm_kwin4_effect_builtins
+X-KDE-ParentComponents=kwin4_effect_mouseclick
+X-KDE-PluginKeyword=mouseclick
+
+Name=Mouse Click Animation
diff --git a/kwin/effects/mouseclick/mouseclick_config.h b/kwin/effects/mouseclick/mouseclick_config.h
new file mode 100644
index 0000000..af02c2b
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick_config.h
@@ -0,0 +1,58 @@
+/********************************************************************
+ KWin - the KDE window manager
+ This file is part of the KDE project.
+
+Copyright (C) 2012 Filip Wieladek <wattos@gmail.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_MOUSECLICK_CONFIG_H
+#define KWIN_MOUSECLICK_CONFIG_H
+
+#include <kcmodule.h>
+
+#include "ui_mouseclick_config.h"
+
+class KActionCollection;
+
+namespace KWin
+{
+
+class MouseClickEffectConfigForm : public QWidget, public Ui::MouseClickEffectConfigForm
+{
+ Q_OBJECT
+public:
+ explicit MouseClickEffectConfigForm(QWidget* parent);
+};
+
+class MouseClickEffectConfig : public KCModule
+{
+ Q_OBJECT
+public:
+ explicit MouseClickEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList());
+ virtual ~MouseClickEffectConfig();
+
+ virtual void save();
+ virtual void load();
+ virtual void defaults();
+
+private:
+ MouseClickEffectConfigForm* m_ui;
+ KActionCollection* m_actionCollection;
+};
+
+} // namespace
+
+#endif
diff --git a/kwin/effects/mouseclick/mouseclick_config.ui b/kwin/effects/mouseclick/mouseclick_config.ui
new file mode 100644
index 0000000..4c5aed7
--- /dev/null
+++ b/kwin/effects/mouseclick/mouseclick_config.ui
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KWin::MouseClickEffectConfigForm</class>
+ <widget class="QWidget" name="KWin::MouseClickEffectConfigForm">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>292</width>
+ <height>378</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabs">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="basic_tab">
+ <attribute name="title">
+ <string>Basic Settings</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="1" column="1">
+ <widget class="KColorCombo" name="button1_color_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="button1_label">
+ <property name="text">
+ <string>Left Mouse Button Color:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buddy">
+ <cstring>button1_color_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="button2_label">
+ <property name="text">
+ <string>Middle Mouse Button Color:</string>
+ </property>
+ <property name="buddy">
+ <cstring>button2_color_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="KColorCombo" name="button2_color_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="button3_label">
+ <property name="text">
+ <string>Right Mouse Button Color:</string>
+ </property>
+ <property name="buddy">
+ <cstring>button3_color_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="KColorCombo" name="button3_color_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="advanced_tab">
+ <attribute name="title">
+ <string>Advanced Settings</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="rings">
+ <property name="title">
+ <string>Rings</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="ring_line_width_label">
+ <property name="text">
+ <string>Line Width:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ring_line_width_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="KDoubleNumInput" name="ring_line_width_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="KIntSpinBox" name="ring_duration_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>50</number>
+ </property>
+ <property name="maximum">
+ <number>5000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="ring_duration_label">
+ <property name="text">
+ <string>Ring Duration:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ring_duration_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="ring_radius_label">
+ <property name="text">
+ <string>Ring Radius:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ring_radius_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="KIntSpinBox" name="ring_radius_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>1000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="ring_count_label">
+ <property name="text">
+ <string>Ring Count:</string>
+ </property>
+ <property name="buddy">
+ <cstring>ring_count_input</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="KIntNumInput" name="ring_count_input">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="font">
+ <property name="title">
+ <string>Text</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_4">
+ <item row="3" column="0">
+ <widget class="QLabel" name="font_label">
+ <property name="text">
+ <string>Font:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="KFontRequester" name="font_input"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="showtext_input">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="showtext_label">
+ <property name="text">
+ <string>Show Text:</string>
+ </property>
+ <property name="buddy">
+ <cstring>showtext_input</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="KWin::GlobalShortcutsEditor" name="editor" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KColorCombo</class>
+ <extends>QComboBox</extends>
+ <header>kcolorcombo.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KDoubleNumInput</class>
+ <extends>QWidget</extends>
+ <header>knuminput.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KFontRequester</class>
+ <extends>QWidget</extends>
+ <header>kfontrequester.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KIntSpinBox</class>
+ <extends>QSpinBox</extends>
+ <header>knuminput.h</header>
+ </customwidget>
+ <customwidget>
+ <class>KIntNumInput</class>
+ <extends>QWidget</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>
+ <resources/>
+ <connections/>
+</ui>