From 1f5e3b1d3f9339612ba1bc3d77dba4d091f34dd3 Mon Sep 17 00:00:00 2001 From: wheaney <42350981+wheaney@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:05:50 -0700 Subject: [PATCH] Add Zoom on Focus shortcut support --- kwin/src/breezydesktopconfig.kcfg | 5 + kwin/src/breezydesktopconfig.kcfgc | 1 + kwin/src/breezydesktopeffect.cpp | 30 +++-- kwin/src/breezydesktopeffect.h | 6 + kwin/src/kcm/breezydesktopeffectkcm.cpp | 31 ++++- kwin/src/kcm/breezydesktopeffectkcm.h | 8 ++ kwin/src/kcm/breezydesktopeffectkcm.ui | 150 +++++++++++++----------- kwin/src/kcm/shortcuts.h | 6 + kwin/src/qml/BreezyDesktop.qml | 26 ++-- 9 files changed, 174 insertions(+), 89 deletions(-) diff --git a/kwin/src/breezydesktopconfig.kcfg b/kwin/src/breezydesktopconfig.kcfg index 5164008..f986f19 100644 --- a/kwin/src/breezydesktopconfig.kcfg +++ b/kwin/src/breezydesktopconfig.kcfg @@ -17,5 +17,10 @@ 250 + + false + + Enable zooming in on the focused display. + diff --git a/kwin/src/breezydesktopconfig.kcfgc b/kwin/src/breezydesktopconfig.kcfgc index 4f16263..f1666fe 100644 --- a/kwin/src/breezydesktopconfig.kcfgc +++ b/kwin/src/breezydesktopconfig.kcfgc @@ -2,3 +2,4 @@ File=breezydesktopconfig.kcfg ClassName=BreezyDesktopConfig Singleton=true Mutators=true +Notifiers=true \ No newline at end of file diff --git a/kwin/src/breezydesktopeffect.cpp b/kwin/src/breezydesktopeffect.cpp index dede417..54607f6 100644 --- a/kwin/src/breezydesktopeffect.cpp +++ b/kwin/src/breezydesktopeffect.cpp @@ -82,6 +82,10 @@ BreezyDesktopEffect::BreezyDesktopEffect() BreezyShortcuts::RECENTER, [this]() { this->recenter(); } ); + setupGlobalShortcut( + BreezyShortcuts::TOGGLE_ZOOM_ON_FOCUS, + [this]() { this->toggleZoomOnFocus(); } + ); connect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::updateCursorImage); updateCursorImage(); @@ -127,14 +131,7 @@ void BreezyDesktopEffect::setupGlobalShortcut(const BreezyShortcuts::Shortcut &s action->setText(shortcut.actionText); KGlobalAccel::self()->setDefaultShortcut(action, {shortcut.shortcut}); KGlobalAccel::self()->setShortcut(action, {shortcut.shortcut}); - QList shortcutKeys = KGlobalAccel::self()->shortcut(action); connect(action, &QAction::triggered, this, triggeredFunc); - connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, [this, shortcut, &shortcutKeys](QAction *action, const QKeySequence &seq) { - if (action->objectName() == shortcut.actionName) { - shortcutKeys.clear(); - shortcutKeys.append(seq); - } - }); } void BreezyDesktopEffect::reconfigure(ReconfigureFlags) @@ -142,6 +139,7 @@ void BreezyDesktopEffect::reconfigure(ReconfigureFlags) BreezyDesktopConfig::self()->read(); setFocusedDisplayDistance(BreezyDesktopConfig::focusedDisplayDistance() / 100.0f); setAllDisplaysDistance(BreezyDesktopConfig::allDisplaysDistance() / 100.0f); + setZoomOnFocusEnabled(BreezyDesktopConfig::zoomOnFocusEnabled()); } QVariantMap BreezyDesktopEffect::initialProperties(Output *screen) @@ -222,6 +220,11 @@ void BreezyDesktopEffect::recenter() } } +void BreezyDesktopEffect::toggleZoomOnFocus() +{ + setZoomOnFocusEnabled(!m_zoomOnFocusEnabled); +} + void BreezyDesktopEffect::addVirtualDisplay(QSize size) { // QSize size(2560, 1440); @@ -241,6 +244,19 @@ bool BreezyDesktopEffect::isEnabled() const { return m_enabled; } +bool BreezyDesktopEffect::isZoomOnFocusEnabled() const { + return m_zoomOnFocusEnabled; +} + +void BreezyDesktopEffect::setZoomOnFocusEnabled(bool enabled) { + if (m_zoomOnFocusEnabled != enabled) { + m_zoomOnFocusEnabled = enabled; + BreezyDesktopConfig::setZoomOnFocusEnabled(enabled); + BreezyDesktopConfig::self()->save(); + Q_EMIT zoomOnFocusChanged(); + } +} + bool BreezyDesktopEffect::imuResetState() const { return m_imuResetState; } diff --git a/kwin/src/breezydesktopeffect.h b/kwin/src/breezydesktopeffect.h index f68316b..08c2e54 100644 --- a/kwin/src/breezydesktopeffect.h +++ b/kwin/src/breezydesktopeffect.h @@ -15,6 +15,7 @@ namespace KWin { Q_OBJECT Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY enabledStateChanged) + Q_PROPERTY(bool zoomOnFocusEnabled READ isZoomOnFocusEnabled WRITE setZoomOnFocusEnabled NOTIFY zoomOnFocusChanged) Q_PROPERTY(bool imuResetState READ imuResetState NOTIFY imuRotationsChanged) Q_PROPERTY(QList imuRotations READ imuRotations NOTIFY imuRotationsChanged) Q_PROPERTY(quint32 imuTimeElapsedMs READ imuTimeElapsedMs NOTIFY imuRotationsChanged) @@ -42,6 +43,8 @@ namespace KWin QPointF cursorPos() const; bool isEnabled() const; + bool isZoomOnFocusEnabled() const; + void setZoomOnFocusEnabled(bool enabled); QList imuRotations() const; quint32 imuTimeElapsedMs() const; quint64 imuTimestamp() const; @@ -65,6 +68,7 @@ namespace KWin void deactivate(); void toggle(); void recenter(); + void toggleZoomOnFocus(); void addVirtualDisplay(QSize size); void updateImuRotation(); void updateCursorImage(); @@ -73,6 +77,7 @@ namespace KWin Q_SIGNALS: void displayDistanceChanged(); void enabledStateChanged(); + void zoomOnFocusChanged(); void imuRotationsChanged(); void cursorImageChanged(); void cursorPosChanged(); @@ -91,6 +96,7 @@ namespace KWin QString m_cursorImageSource; bool m_enabled = false; + bool m_zoomOnFocusEnabled = false; bool m_imuResetState; QList m_imuRotations; quint32 m_imuTimeElapsedMs; diff --git a/kwin/src/kcm/breezydesktopeffectkcm.cpp b/kwin/src/kcm/breezydesktopeffectkcm.cpp index 9013c4a..8df3273 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.cpp +++ b/kwin/src/kcm/breezydesktopeffectkcm.cpp @@ -7,12 +7,18 @@ #include #include #include +#include +#include #include #include #include +Q_LOGGING_CATEGORY(KWIN_XR, "kwin.xr") + +static const char EFFECT_GROUP[] = "Effect-breezy_desktop_effect"; + void addShortcutAction(KActionCollection *collection, const BreezyShortcuts::Shortcut &shortcut) { QAction *action = collection->addAction(shortcut.actionName); @@ -29,6 +35,22 @@ BreezyDesktopEffectConfig::BreezyDesktopEffectConfig(QObject *parent, const KPlu { ui.setupUi(widget()); addConfig(BreezyDesktopConfig::self(), widget()); + + m_configWatcher = KConfigWatcher::create(BreezyDesktopConfig::self()->sharedConfig()); + if (m_configWatcher) { + connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, + [this](const KConfigGroup &group, const QByteArrayList &names) { + if (m_updatingFromConfig) { + return; + } + if (group.name() != QLatin1String(EFFECT_GROUP)) { + return; + } + BreezyDesktopConfig::self()->read(); + updateUiFromConfig(); + updateUnmanagedState(); + }); + } auto actionCollection = new KActionCollection(this, QStringLiteral("kwin")); actionCollection->setComponentDisplayName(i18n("KWin")); @@ -37,6 +59,7 @@ BreezyDesktopEffectConfig::BreezyDesktopEffectConfig(QObject *parent, const KPlu addShortcutAction(actionCollection, BreezyShortcuts::TOGGLE); addShortcutAction(actionCollection, BreezyShortcuts::RECENTER); + addShortcutAction(actionCollection, BreezyShortcuts::TOGGLE_ZOOM_ON_FOCUS); ui.shortcutsEditor->addCollection(actionCollection); connect(ui.shortcutsEditor, &KShortcutsEditor::keyChange, this, &BreezyDesktopEffectConfig::markAsChanged); connect(ui.kcfg_FocusedDisplayDistance, &QSlider::valueChanged, this, &BreezyDesktopEffectConfig::save); @@ -56,9 +79,12 @@ void BreezyDesktopEffectConfig::load() void BreezyDesktopEffectConfig::save() { + // Prevent reacting to the file change we ourselves are about to write. + m_updatingFromConfig = true; updateConfigFromUi(); BreezyDesktopConfig::self()->save(); KCModule::save(); + m_updatingFromConfig = false; updateUnmanagedState(); OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QDBusConnection::sessionBus()); @@ -79,6 +105,9 @@ void BreezyDesktopEffectConfig::updateConfigFromUi() void BreezyDesktopEffectConfig::updateUiFromConfig() { + ui.kcfg_FocusedDisplayDistance->setValue(BreezyDesktopConfig::self()->focusedDisplayDistance()); + ui.kcfg_AllDisplaysDistance->setValue(BreezyDesktopConfig::self()->allDisplaysDistance()); + ui.kcfg_ZoomOnFocusEnabled->setChecked(BreezyDesktopConfig::self()->zoomOnFocusEnabled()); } void BreezyDesktopEffectConfig::updateUiFromDefaultConfig() @@ -90,4 +119,4 @@ void BreezyDesktopEffectConfig::updateUnmanagedState() { } -#include "breezydesktopeffectkcm.moc" +#include "breezydesktopeffectkcm.moc" \ No newline at end of file diff --git a/kwin/src/kcm/breezydesktopeffectkcm.h b/kwin/src/kcm/breezydesktopeffectkcm.h index fa3b5e6..f795942 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.h +++ b/kwin/src/kcm/breezydesktopeffectkcm.h @@ -7,9 +7,14 @@ #pragma once #include +#include +#include #include "ui_breezydesktopeffectkcm.h" +class KConfigWatcher; +class KConfigGroup; + class BreezyDesktopEffectConfig : public KCModule { Q_OBJECT @@ -30,4 +35,7 @@ private: void updateUnmanagedState(); ::Ui::BreezyDesktopEffectConfig ui; + + KConfigWatcher::Ptr m_configWatcher; + bool m_updatingFromConfig = false; }; diff --git a/kwin/src/kcm/breezydesktopeffectkcm.ui b/kwin/src/kcm/breezydesktopeffectkcm.ui index 50048e9..f9ad626 100644 --- a/kwin/src/kcm/breezydesktopeffectkcm.ui +++ b/kwin/src/kcm/breezydesktopeffectkcm.ui @@ -21,76 +21,86 @@ 250 - - - - - Focused Display Distance: - - - - - - - 20 - - - 250 - - - QSlider::TicksBelow - - - 20 - - - Qt::Horizontal - - - true - - - - - - - All Displays Distance: - - - - - - - 20 - - - 250 - - - QSlider::TicksBelow - - - 20 - - - Qt::Horizontal - - - true - - - - - - - - 0 - 0 - - - - - + + + + + Zoom on Focus + + + false + + + + + + + Focused Display Distance: + + + + + + + 20 + + + 250 + + + QSlider::TicksBelow + + + 20 + + + Qt::Horizontal + + + true + + + + + + + All Displays Distance: + + + + + + + 20 + + + 250 + + + QSlider::TicksBelow + + + 20 + + + Qt::Horizontal + + + true + + + + + + + + 0 + 0 + + + + + diff --git a/kwin/src/kcm/shortcuts.h b/kwin/src/kcm/shortcuts.h index 1eb8c75..f5792a6 100644 --- a/kwin/src/kcm/shortcuts.h +++ b/kwin/src/kcm/shortcuts.h @@ -22,4 +22,10 @@ namespace BreezyShortcuts { QStringLiteral("Recenter"), QStringLiteral("Recenter") }; + + const Shortcut TOGGLE_ZOOM_ON_FOCUS = { + Qt::CTRL | Qt::META | Qt::Key_0, + QStringLiteral("Toggle Zoom on Focus"), + QStringLiteral("Toggle Zoom on Focus") + }; } diff --git a/kwin/src/qml/BreezyDesktop.qml b/kwin/src/qml/BreezyDesktop.qml index 56ef738..7fb0b32 100644 --- a/kwin/src/qml/BreezyDesktop.qml +++ b/kwin/src/qml/BreezyDesktop.qml @@ -94,20 +94,24 @@ Node { running: true onTriggered: { if (breezyDesktop.imuRotations && breezyDesktop.imuRotations.length > 0) { - const focusedIndex = displays.findFocusedMonitor( - displays.eusToNwuQuat(breezyDesktop.imuRotations[0]), - breezyDesktop.monitorPlacements.map(monitorVectors => monitorVectors.centerLook), - breezyDesktop.focusedMonitorIndex, - false, // TODO smooth follow - breezyDesktop.fovDetails, - breezyDesktop.screens.map(screen => screen.geometry) - ); + let focusedIndex = -1; + + if (effect.zoomOnFocusEnabled) { + focusedIndex = displays.findFocusedMonitor( + displays.eusToNwuQuat(breezyDesktop.imuRotations[0]), + breezyDesktop.monitorPlacements.map(monitorVectors => monitorVectors.centerLook), + breezyDesktop.focusedMonitorIndex, + false, // TODO smooth follow + breezyDesktop.fovDetails, + breezyDesktop.screens.map(screen => screen.geometry) + ); + } const focusedDisplay = focusedIndex !== -1 ? breezyDesktop.displayAtIndex(focusedIndex) : null; if (focusedIndex !== breezyDesktop.focusedMonitorIndex) { - zoomOutAnimation.stop(); - zoomInAnimation.stop(); - zoomOnFocusSequence.stop(); + // zoomOutAnimation.stop(); + // zoomInAnimation.stop(); + // zoomOnFocusSequence.stop(); if (focusedDisplay === null) { zoomOutAnimation.target = breezyDesktop.displayAtIndex(breezyDesktop.focusedMonitorIndex); zoomOutAnimation.target.targetDistance = zoomOutAnimation.to;