diff --git a/autotests/test_builtin_effectloader.cpp b/autotests/test_builtin_effectloader.cpp --- a/autotests/test_builtin_effectloader.cpp +++ b/autotests/test_builtin_effectloader.cpp @@ -110,6 +110,7 @@ QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true; QTest::newRow("Slide") << QStringLiteral("slide") << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true; + QTest::newRow("SlideDesktops") << QStringLiteral("slidedesktops") << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << true; @@ -166,6 +167,7 @@ << QStringLiteral("showpaint") << QStringLiteral("slide") << QStringLiteral("slideback") + << QStringLiteral("slidedesktops") << QStringLiteral("slidingpopups") << QStringLiteral("snaphelper") << QStringLiteral("startupfeedback") @@ -246,6 +248,7 @@ QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc << true; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc << true; + QTest::newRow("SlideDesktops") << QStringLiteral("slidedesktops") << true << xc << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc << true; @@ -334,6 +337,7 @@ QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc; + QTest::newRow("SlideDesktops") << QStringLiteral("slidedesktops") << true << xc; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc; diff --git a/autotests/test_plugin_effectloader.cpp b/autotests/test_plugin_effectloader.cpp --- a/autotests/test_plugin_effectloader.cpp +++ b/autotests/test_plugin_effectloader.cpp @@ -102,6 +102,7 @@ QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << false; QTest::newRow("Slide") << QStringLiteral("slide") << false; QTest::newRow("SlideBack") << QStringLiteral("slideback") << false; + QTest::newRow("SlideDesktops") << QStringLiteral("slidedesktops") << false; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << false; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << false; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false; diff --git a/autotests/test_scripted_effectloader.cpp b/autotests/test_scripted_effectloader.cpp --- a/autotests/test_scripted_effectloader.cpp +++ b/autotests/test_scripted_effectloader.cpp @@ -132,6 +132,7 @@ QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << false; QTest::newRow("Slide") << QStringLiteral("slide") << false; QTest::newRow("SlideBack") << QStringLiteral("slideback") << false; + QTest::newRow("SlideDesktops") << QStringLiteral("slidedesktops") << false; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << false; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << false; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false; diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt --- a/effects/CMakeLists.txt +++ b/effects/CMakeLists.txt @@ -92,6 +92,7 @@ resize/resize.cpp showfps/showfps.cpp slide/slide.cpp + slidedesktops/slidedesktops.cpp thumbnailaside/thumbnailaside.cpp touchpoints/touchpoints.cpp trackmouse/trackmouse.cpp @@ -121,6 +122,7 @@ resize/resizeconfig.kcfgc showfps/showfpsconfig.kcfgc slide/slideconfig.kcfgc + slidedesktops/slidedesktopsconfig.kcfgc slidingpopups/slidingpopupsconfig.kcfgc thumbnailaside/thumbnailasideconfig.kcfgc trackmouse/trackmouseconfig.kcfgc @@ -162,6 +164,7 @@ include( showpaint/CMakeLists.txt ) add_subdirectory( slide ) include( slideback/CMakeLists.txt ) +add_subdirectory( slidedesktops ) include( slidingpopups/CMakeLists.txt ) add_subdirectory( thumbnailaside ) add_subdirectory( windowgeometry ) diff --git a/effects/effect_builtins.h b/effects/effect_builtins.h --- a/effects/effect_builtins.h +++ b/effects/effect_builtins.h @@ -64,6 +64,7 @@ ShowPaint, Slide, SlideBack, + SlideDesktops, SlidingPopups, SnapHelper, StartupFeedback, diff --git a/effects/effect_builtins.cpp b/effects/effect_builtins.cpp --- a/effects/effect_builtins.cpp +++ b/effects/effect_builtins.cpp @@ -41,6 +41,7 @@ #include "showpaint/showpaint.h" #include "slide/slide.h" #include "slideback/slideback.h" +#include "slidedesktops/slidedesktops.h" #include "thumbnailaside/thumbnailaside.h" #include "touchpoints/touchpoints.h" #include "windowgeometry/windowgeometry.h" @@ -546,6 +547,21 @@ nullptr, nullptr #endif +EFFECT_FALLBACK + }, { + QStringLiteral("slidedesktops"), + i18ndc("kwin_effects", "Name of a KWin Effect", "Slide Desktops"), + i18ndc("kwin_effects", "Comment describing the KWin Effect", "Slide desktops when switching virtual desktops"), + QStringLiteral("Virtual Desktop Switching Animation"), + QStringLiteral("desktop-animations"), + QUrl(), + false, + false, +#ifdef EFFECT_BUILTINS + &createHelper, + &SlideDesktopsEffect::supported, + nullptr +#endif EFFECT_FALLBACK }, { QStringLiteral("slidingpopups"), diff --git a/effects/slidedesktops/CMakeLists.txt b/effects/slidedesktops/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/CMakeLists.txt @@ -0,0 +1,24 @@ +####################################### +# Config +set(kwin_slidedesktops_config_SRCS slidedesktops_config.cpp) +ki18n_wrap_ui(kwin_slidedesktops_config_SRCS slidedesktops_config.ui) +qt5_add_dbus_interface(kwin_slidedesktops_config_SRCS ${kwin_effects_dbus_xml} kwineffects_interface) +kconfig_add_kcfg_files(kwin_slidedesktops_config_SRCS slidedesktopsconfig.kcfgc) + +add_library(kwin_slidedesktops_config MODULE ${kwin_slidedesktops_config_SRCS}) + +target_link_libraries(kwin_slidedesktops_config + Qt5::DBus + KF5::ConfigWidgets + KF5::I18n + KF5::Service +) + +kcoreaddons_desktop_to_json(kwin_slidedesktops_config slidedesktops_config.desktop SERVICE_TYPES kcmodule.desktop) + +install( + TARGETS + kwin_slidedesktops_config + DESTINATION + ${PLUGIN_INSTALL_DIR}/kwin/effects/configs +) diff --git a/effects/slidedesktops/slidedesktops.h b/effects/slidedesktops/slidedesktops.h new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops.h @@ -0,0 +1,104 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#ifndef KWIN_SLIDEDESKTOPS_H +#define KWIN_SLIDEDESKTOPS_H + +// KDE +#include + +// Qt +#include +#include + +namespace KWin +{ + +class SlideDesktopsEffect + : public Effect +{ + Q_OBJECT +public: + SlideDesktopsEffect(); + + void reconfigure(ReconfigureFlags) override; + + void prePaintScreen(ScreenPrePaintData& data, int time) override; + void paintScreen(int mask, QRegion region, ScreenPaintData& data) override; + void postPaintScreen() override; + + void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) override; + void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) override; + + bool isActive() const override { + return m_active; + } + + int requestedEffectChainPosition() const override { + return 50; + } + + static bool supported(); + +private Q_SLOTS: + void desktopChanged(int old, int current, EffectWindow* with); + void windowAdded(EffectWindow* w); + void windowDeleted(EffectWindow* w); + + void numberDesktopsChanged(uint old); + void numberScreensChanged(); + +private: + QPoint desktopCoords(int id) const; + QRect desktopGeometry(int id) const; + int workspaceWidth() const; + int workspaceHeight() const; + + bool isTranslated(const EffectWindow* w) const; + bool isPainted(const EffectWindow* w) const; + + void start(int old, int current, EffectWindow* movingWindow = nullptr); + void stop(); + +private: + int m_hGap = 45; + int m_vGap = 20; + + bool m_active = false; + QTimeLine m_timeline; + QPoint m_startPos; + QPoint m_diff; + EffectWindow* m_movingWindow = nullptr; + + struct { + int desktop; + bool firstPass; + bool lastPass; + QPoint translation; + + EffectWindowList fullscreenWindows; + } m_paintCtx; + + QList m_backgroundContrastForcedBefore; +}; + +} // namespace + +#endif diff --git a/effects/slidedesktops/slidedesktops.cpp b/effects/slidedesktops/slidedesktops.cpp new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops.cpp @@ -0,0 +1,422 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2018 Vlad Zagorodniy + +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 . +*********************************************************************/ + +// Qt +#include + +#include "slidedesktops.h" +// KConfigSkeleton +#include "slidedesktopsconfig.h" + +namespace KWin +{ + +SlideDesktopsEffect::SlideDesktopsEffect() +{ + initConfig(); + reconfigure(ReconfigureAll); + connect(effects, static_cast(&EffectsHandler::desktopChanged), + this, &SlideDesktopsEffect::desktopChanged); + connect(effects, &EffectsHandler::windowAdded, + this, &SlideDesktopsEffect::windowAdded); + connect(effects, &EffectsHandler::windowDeleted, + this, &SlideDesktopsEffect::windowDeleted); + connect(effects, &EffectsHandler::numberDesktopsChanged, + this, &SlideDesktopsEffect::numberDesktopsChanged); + connect(effects, &EffectsHandler::numberScreensChanged, + this, &SlideDesktopsEffect::numberScreensChanged); +} + +bool SlideDesktopsEffect::supported() +{ + return effects->animationsSupported(); +} + +void SlideDesktopsEffect::reconfigure(ReconfigureFlags) +{ + SlideDesktopsConfig::self()->read(); + + const int d = animationTime( + SlideDesktopsConfig::duration() != 0 ? SlideDesktopsConfig::duration() : 500); + QEasingCurve easing(QEasingCurve::OutCubic); + m_timeline.setDuration(d); + m_timeline.setEasingCurve(easing); + + m_hGap = SlideDesktopsConfig::horizontalGap(); + m_vGap = SlideDesktopsConfig::verticalGap(); +} + +void SlideDesktopsEffect::prePaintScreen(ScreenPrePaintData& data, int time) +{ + if (m_active) { + m_timeline.setCurrentTime(m_timeline.currentTime() + time); + data.mask |= PAINT_SCREEN_TRANSFORMED + | PAINT_SCREEN_BACKGROUND_FIRST; + } + + effects->prePaintScreen(data, time); +} + +/** + * Wrap vector @p diff around grid @p w x @p h. + * + * Wrapping is done in such a way that magnitude of x and y component of vector + * @p diff is less than half of @p w and half of @p h, respectively. This will + * result in having the "shortest" path between two points. + * + * @param diff Vector between two points + * @param w Width of the desktop grid + * @param h Height of the desktop grid + */ +inline void wrapDiff(QPoint& diff, int w, int h) +{ + if (diff.x() > w/2) { + diff.setX(diff.x() - w); + } else if (diff.x() < -w/2) { + diff.setX(diff.x() + w); + } + + if (diff.y() > h/2) { + diff.setY(diff.y() - h); + } else if (diff.y() < -h/2) { + diff.setY(diff.y() + h); + } +} + +inline QRegion buildClipRegion(QPoint pos, int w, int h) +{ + const QSize screenSize = effects->virtualScreenSize(); + QRegion r = QRect(pos, screenSize); + if (effects->optionRollOverDesktops()) { + r |= (r & QRect(-w, 0, w, h)).translated(w, 0); // W + r |= (r & QRect(w, 0, w, h)).translated(-w, 0); // E + + r |= (r & QRect(0, -h, w, h)).translated(0, h); // N + r |= (r & QRect(0, h, w, h)).translated(0, -h); // S + + r |= (r & QRect(-w, -h, w, h)).translated(w, h); // NW + r |= (r & QRect(w, -h, w, h)).translated(-w, h); // NE + r |= (r & QRect(w, h, w, h)).translated(-w, -h); // SE + r |= (r & QRect(-w, h, w, h)).translated(w, -h); // SW + } + return r; +} + +void SlideDesktopsEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) +{ + if (! m_active) { + effects->paintScreen(mask, region, data); + return; + } + + const bool wrap = effects->optionRollOverDesktops(); + const int w = workspaceWidth(); + const int h = workspaceHeight(); + + QPoint currentPos = m_startPos + m_diff * m_timeline.currentValue(); + + // When "Desktop navigation wraps around" checkbox is checked, currentPos + // can be outside the rectangle Rect{x:-w, y:-h, width:2*w, height: 2*h}, + // so we map currentPos back to the rect. + if (wrap) { + currentPos.setX(currentPos.x() % w); + currentPos.setY(currentPos.y() % h); + } + + QRegion clipRegion = buildClipRegion(currentPos, w, h); + QList visibleDesktops; + for (int i = 1; i <= effects->numberOfDesktops(); i++) { + QRect desktopGeo = desktopGeometry(i); + if (! clipRegion.contains(desktopGeo)) { + continue; + } + visibleDesktops << i; + } + + // When we enter a virtual desktop that has a window in fullscreen mode, + // stacking order is fine. When we leave a virtual desktop that has + // a window in fullscreen mode, stacking order is no longer valid + // because panels are raised above the fullscreen window. Construct + // a list of fullscreen windows, so we can decide later whether + // docks should be visible on different virtual desktops. + m_paintCtx.fullscreenWindows.clear(); + foreach (EffectWindow* w, effects->stackingOrder()) { + if (! w->isFullScreen()) { + continue; + } + m_paintCtx.fullscreenWindows << w; + } + + m_paintCtx.firstPass = true; + const int lastDesktop = visibleDesktops.last(); + foreach (int desktop, visibleDesktops) { + m_paintCtx.desktop = desktop; + m_paintCtx.lastPass = (lastDesktop == desktop); + m_paintCtx.translation = desktopCoords(desktop) - currentPos; + if (wrap) { + wrapDiff(m_paintCtx.translation, w, h); + } + effects->paintScreen(mask, region, data); + m_paintCtx.firstPass = false; + } +} + +/** + * Decide whether given window @p w should be transformed/translated. + * @returns @c true if given window @p w should be transformed, otherwise @c false + */ +bool SlideDesktopsEffect::isTranslated(const EffectWindow* w) const +{ + if (w->isOnAllDesktops()) { + return (w->isDock() || w->isDesktop()); + } else if (w == m_movingWindow) { + return false; + } else if (w->isOnDesktop(m_paintCtx.desktop)) { + return true; + } + return false; +} + +/** + * Decide whether given window @p w should be painted. + * @returns @c true if given window @p w should be painted, otherwise @c false + */ +bool SlideDesktopsEffect::isPainted(const EffectWindow* w) const +{ + if (w->isOnAllDesktops()) { + // In order to make sure that 'keep above' windows are above + // other windows during transition to another virtual desktop, + // they should be painted in the last pass. + if (w->keepAbove()) { + return m_paintCtx.lastPass; + } + // Do not draw dock windows if there is a fullscreen window + // on currently painted desktop. + if (w->isDock()) { + foreach (EffectWindow* fw, m_paintCtx.fullscreenWindows) { + if (fw->isOnDesktop(m_paintCtx.desktop) + && fw->screen() == w->screen()) { + return false; + } + } + } + return true; + } if (w == m_movingWindow) { + return m_paintCtx.lastPass; + } else if (w->isOnDesktop(m_paintCtx.desktop)) { + return true; + } + return false; +} + +void SlideDesktopsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) +{ + if (m_active) { + const bool painted = isPainted(w); + if (painted) { + w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); + } else { + w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP); + } + if (painted && isTranslated(w)) { + data.setTransformed(); + } + } + effects->prePaintWindow(w, data, time); +} + +void SlideDesktopsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) +{ + if (m_active && isTranslated(w)) { + data += m_paintCtx.translation; + } + effects->paintWindow(w, mask, region, data); +} + +void SlideDesktopsEffect::postPaintScreen() +{ + if (m_active) { + if (m_timeline.currentValue() == 1) { + stop(); + } + effects->addRepaintFull(); + } + effects->postPaintScreen(); +} + +/** + * Get position of the top-left corner of desktop @p id within desktop grid with gaps. + * @param id ID of a virtual desktop + */ +QPoint SlideDesktopsEffect::desktopCoords(int id) const +{ + QPoint c = effects->desktopCoords(id); + QPoint gridPos = effects->desktopGridCoords(id); + c.setX(c.x() + m_hGap * gridPos.x()); + c.setY(c.y() + m_vGap * gridPos.y()); + return c; +} + +/** + * Get geometry of desktop @p id within desktop grid with gaps. + * @param id ID of a virtual desktop + */ +QRect SlideDesktopsEffect::desktopGeometry(int id) const +{ + QRect g = effects->virtualScreenGeometry(); + g.translate(desktopCoords(id)); + return g; +} + +/** + * Get width of a virtual desktop grid. + */ +int SlideDesktopsEffect::workspaceWidth() const +{ + int w = effects->workspaceWidth(); + w += m_hGap * effects->desktopGridWidth(); + return w; +} + +/** + * Get height of a virtual desktop grid. + */ +int SlideDesktopsEffect::workspaceHeight() const +{ + int h = effects->workspaceHeight(); + h += m_vGap * effects->desktopGridHeight(); + return h; +} + +inline bool shouldForceBackgroundContrast(const EffectWindow *w) +{ + if (w->data(WindowForceBackgroundContrastRole).isValid()) { + return false; + } + return w->hasAlpha() + && w->isOnAllDesktops() + && (w->isDock() || w->keepAbove()); +} + +void SlideDesktopsEffect::start(int old, int current, EffectWindow* movingWindow) +{ + m_movingWindow = movingWindow; + + const bool wrap = effects->optionRollOverDesktops(); + const int w = workspaceWidth(); + const int h = workspaceHeight(); + + if (m_active) { + QPoint passed = m_diff * m_timeline.currentValue(); + QPoint currentPos = m_startPos + passed; + QPoint delta = desktopCoords(current) - desktopCoords(old); + if (wrap) { + wrapDiff(delta, w, h); + } + m_diff += delta - passed; + m_startPos = currentPos; + m_timeline.setCurrentTime(0); + return; + } + + foreach (EffectWindow* w, effects->stackingOrder()) { + w->setData(WindowForceBlurRole, QVariant(true)); + if (shouldForceBackgroundContrast(w)) { + w->setData(WindowForceBackgroundContrastRole, QVariant(true)); + m_backgroundContrastForcedBefore << w; + } + } + + m_diff = desktopCoords(current) - desktopCoords(old); + if (wrap) { + wrapDiff(m_diff, w, h); + } + m_startPos = desktopCoords(old); + m_timeline.setCurrentTime(0); + m_active = true; + effects->setActiveFullScreenEffect(this); + effects->addRepaintFull(); +} + +void SlideDesktopsEffect::stop() +{ + foreach (EffectWindow* w, effects->stackingOrder()) { + w->setData(WindowForceBlurRole, QVariant(false)); + if (m_backgroundContrastForcedBefore.contains(w)) { + w->setData(WindowForceBackgroundContrastRole, QVariant()); + } + } + m_backgroundContrastForcedBefore.clear(); + m_paintCtx.fullscreenWindows.clear(); + m_timeline.setCurrentTime(0); + m_movingWindow = nullptr; + m_active = false; + effects->setActiveFullScreenEffect(nullptr); +} + +void SlideDesktopsEffect::desktopChanged(int old, int current, EffectWindow* with) +{ + if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this) { + return; + } + start(old, current, with); +} + +void SlideDesktopsEffect::windowAdded(EffectWindow *w) +{ + if (! m_active) { + return; + } + w->setData(WindowForceBlurRole, QVariant(true)); + if (shouldForceBackgroundContrast(w)) { + w->setData(WindowForceBackgroundContrastRole, QVariant(true)); + m_backgroundContrastForcedBefore << w; + } +} + +void SlideDesktopsEffect::windowDeleted(EffectWindow *w) +{ + if (! m_active) { + return; + } + m_backgroundContrastForcedBefore.removeAll(w); + m_paintCtx.fullscreenWindows.removeAll(w); + if (w == m_movingWindow) { + m_movingWindow = nullptr; + } +} + +void SlideDesktopsEffect::numberDesktopsChanged(uint) +{ + if (! m_active) { + return; + } + stop(); +} + +void SlideDesktopsEffect::numberScreensChanged() +{ + if (! m_active) { + return; + } + stop(); +} + +} // namespace diff --git a/effects/slidedesktops/slidedesktops.kcfg b/effects/slidedesktops/slidedesktops.kcfg new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops.kcfg @@ -0,0 +1,19 @@ + + + + + + + 500 + + + 45 + + + 20 + + + diff --git a/effects/slidedesktops/slidedesktops_config.h b/effects/slidedesktops/slidedesktops_config.h new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops_config.h @@ -0,0 +1,47 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + + +#ifndef SLIDEDESKTOPS_CONFIG_H +#define SLIDEDESKTOPS_CONFIG_H + +#include +#include "ui_slidedesktops_config.h" + +namespace KWin +{ + +class SlideDesktopsEffectConfig : public KCModule +{ + Q_OBJECT + +public: + explicit SlideDesktopsEffectConfig(QWidget *parent = nullptr, const QVariantList& args = QVariantList()); + ~SlideDesktopsEffectConfig(); + + void save(); + +private: + ::Ui::SlideDesktopsEffectConfig m_ui; +}; + +} // namespace KWin + +#endif diff --git a/effects/slidedesktops/slidedesktops_config.cpp b/effects/slidedesktops/slidedesktops_config.cpp new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops_config.cpp @@ -0,0 +1,63 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + + Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "slidedesktops_config.h" +// KConfigSkeleton +#include "slidedesktopsconfig.h" +#include + +#include + +#include +#include + +K_PLUGIN_FACTORY_WITH_JSON(SlideDesktopsEffectConfigFactory, + "slidedesktops_config.json", + registerPlugin();) + +namespace KWin +{ + +SlideDesktopsEffectConfig::SlideDesktopsEffectConfig(QWidget *parent, const QVariantList &args) + : KCModule(KAboutData::pluginData(QStringLiteral("slidedesktops")), parent, args) +{ + m_ui.setupUi(this); + SlideDesktopsConfig::instance(KWIN_CONFIG); + addConfig(SlideDesktopsConfig::self(), this); + load(); +} + +SlideDesktopsEffectConfig::~SlideDesktopsEffectConfig() +{ +} + +void SlideDesktopsEffectConfig::save() +{ + KCModule::save(); + + OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), + QStringLiteral("/Effects"), + QDBusConnection::sessionBus()); + interface.reconfigureEffect(QStringLiteral("slidedesktops")); +} + +} // namespace KWin + +#include "slidedesktops_config.moc" diff --git a/effects/slidedesktops/slidedesktops_config.desktop b/effects/slidedesktops/slidedesktops_config.desktop new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops_config.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Service +X-KDE-ServiceTypes=KCModule + +X-KDE-Library=kwin_slidedesktops_config +X-KDE-ParentComponents=slidedesktops + +Name=Slide Desktops diff --git a/effects/slidedesktops/slidedesktops_config.ui b/effects/slidedesktops/slidedesktops_config.ui new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktops_config.ui @@ -0,0 +1,175 @@ + + + SlideDesktopsEffectConfig + + + + 0 + 0 + 400 + 185 + + + + + + + + + + 100 + 0 + + + + D&uration: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_Duration + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Default + + + milliseconds + + + 9999 + + + 10 + + + + + + + + + true + + + Gap between desktops + + + + + + + + + 100 + 0 + + + + Hori&zontal: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_HorizontalGap + + + + + + + + 0 + 0 + + + + + + + 1000 + + + 5 + + + + + + + + + + + + 100 + 0 + + + + Ver&tical: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_VerticalGap + + + + + + + + 0 + 0 + + + + 1000 + + + 5 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/effects/slidedesktops/slidedesktopsconfig.kcfgc b/effects/slidedesktops/slidedesktopsconfig.kcfgc new file mode 100644 --- /dev/null +++ b/effects/slidedesktops/slidedesktopsconfig.kcfgc @@ -0,0 +1,5 @@ +File=slidedesktops.kcfg +ClassName=SlideDesktopsConfig +NameSpace=KWin +Singleton=true +Mutators=true