Allow configuring click behavior in Desktop Grid effect

The following click behaviors are defined:
 * Switch desktop and activate window [default]
 * Switch desktop only

The former emulates the previous default of activating clicked windows
using the Present Windows effect. The latter introduces a new mode where
the clicked window is not activated, allowing the user to select a
virtual desktop without worrying about disrupting the last active
window.

The configuration toggle that controlled the use of the Present Windows
effect has been subsumed into the first click behavior, i.e., if the
effect is enabled, it will be implicitly triggered.
This commit is contained in:
Konstantinos Smanis 2020-10-30 09:39:00 +00:00 committed by David Edmundson
parent 458ea6dc5e
commit dbcf43abfe
8 changed files with 118 additions and 23 deletions

View file

@ -48,6 +48,7 @@ DesktopGridEffect::DesktopGridEffect()
, isValidMove(false) , isValidMove(false)
, windowMove(nullptr) , windowMove(nullptr)
, windowMoveDiff() , windowMoveDiff()
, windowMoveElevateTimer(new QTimer(this))
, gridSize() , gridSize()
, orientation(Qt::Horizontal) , orientation(Qt::Horizontal)
, activeCell(1, 1) , activeCell(1, 1)
@ -79,12 +80,20 @@ DesktopGridEffect::DesktopGridEffect()
connect(effects, &EffectsHandler::screenAboutToLock, this, [this]() { connect(effects, &EffectsHandler::screenAboutToLock, this, [this]() {
setActive(false); setActive(false);
windowMoveElevateTimer->stop();
if (keyboardGrab) { if (keyboardGrab) {
effects->ungrabKeyboard(); effects->ungrabKeyboard();
keyboardGrab = false; keyboardGrab = false;
} }
}); });
windowMoveElevateTimer->setInterval(QApplication::startDragTime());
windowMoveElevateTimer->setSingleShot(true);
connect(windowMoveElevateTimer, &QTimer::timeout, this, [this]() {
effects->setElevatedWindow(windowMove, true);
wasWindowMove = true;
});
// Load all other configuration details // Load all other configuration details
reconfigure(ReconfigureAll); reconfigure(ReconfigureAll);
} }
@ -115,7 +124,7 @@ void DesktopGridEffect::reconfigure(ReconfigureFlags)
desktopNameAlignment = Qt::Alignment(DesktopGridConfig::desktopNameAlignment()); desktopNameAlignment = Qt::Alignment(DesktopGridConfig::desktopNameAlignment());
layoutMode = DesktopGridConfig::layoutMode(); layoutMode = DesktopGridConfig::layoutMode();
customLayoutRows = DesktopGridConfig::customLayoutRows(); customLayoutRows = DesktopGridConfig::customLayoutRows();
m_usePresentWindows = DesktopGridConfig::presentWindows(); clickBehavior = DesktopGridConfig::clickBehavior();
// deactivate and activate all touch border // deactivate and activate all touch border
const QVector<ElectricBorder> relevantBorders{ElectricLeft, ElectricTop, ElectricRight, ElectricBottom}; const QVector<ElectricBorder> relevantBorders{ElectricLeft, ElectricTop, ElectricRight, ElectricBottom};
@ -457,6 +466,10 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
if (windowMove != nullptr && if (windowMove != nullptr &&
(me->pos() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) { (me->pos() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) {
// Handle window moving // Handle window moving
if (windowMoveElevateTimer->isActive()) { // Window started moving, but is not elevated yet!
windowMoveElevateTimer->stop();
effects->setElevatedWindow(windowMove, true);
}
if (!wasWindowMove) { // Activate on move if (!wasWindowMove) { // Activate on move
if (isUsingPresentWindows()) { if (isUsingPresentWindows()) {
foreach (const int i, desktopList(windowMove)) { foreach (const int i, desktopList(windowMove)) {
@ -574,7 +587,7 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
// Prepare it for moving // Prepare it for moving
windowMoveDiff = w->pos() - unscalePos(me->pos(), nullptr); windowMoveDiff = w->pos() - unscalePos(me->pos(), nullptr);
windowMove = w; windowMove = w;
effects->setElevatedWindow(windowMove, true); windowMoveElevateTimer->start();
} }
} else if ((me->buttons() == Qt::MiddleButton || me->buttons() == Qt::RightButton) && windowMove == nullptr) { } else if ((me->buttons() == Qt::MiddleButton || me->buttons() == Qt::RightButton) && windowMove == nullptr) {
EffectWindow* w = windowAt(me->pos()); EffectWindow* w = windowAt(me->pos());
@ -607,8 +620,16 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
} }
if (e->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton) { if (e->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton) {
isValidMove = false; isValidMove = false;
if (windowMove) if (windowMove) {
effects->activateWindow(windowMove); if (windowMoveElevateTimer->isActive()) {
// no need to elevate window, it was just a click
windowMoveElevateTimer->stop();
}
if (clickBehavior == SwitchDesktopAndActivateWindow || wasWindowMove) {
// activate window if relevant config is set or window was moved
effects->activateWindow(windowMove);
}
}
if (wasWindowMove || wasDesktopMove) { // reset pointer if (wasWindowMove || wasDesktopMove) { // reset pointer
effects->defineCursor(Qt::PointingHandCursor); effects->defineCursor(Qt::PointingHandCursor);
} else { // click -> exit } else { // click -> exit
@ -1068,7 +1089,7 @@ void DesktopGridEffect::setup()
setCurrentDesktop(effects->currentDesktop()); setCurrentDesktop(effects->currentDesktop());
// setup the motion managers // setup the motion managers
if (m_usePresentWindows) if (clickBehavior == SwitchDesktopAndActivateWindow)
m_proxy = static_cast<PresentWindowsEffectProxy*>(effects->getProxy(BuiltInEffects::nameForEffect(BuiltInEffect::PresentWindows))); m_proxy = static_cast<PresentWindowsEffectProxy*>(effects->getProxy(BuiltInEffects::nameForEffect(BuiltInEffect::PresentWindows)));
if (isUsingPresentWindows()) { if (isUsingPresentWindows()) {
m_proxy->reCreateGrids(); // revalidation on multiscreen, bug #351724 m_proxy->reCreateGrids(); // revalidation on multiscreen, bug #351724
@ -1192,6 +1213,8 @@ void DesktopGridEffect::finish()
desktopNames.clear(); desktopNames.clear();
} }
windowMoveElevateTimer->stop();
if (keyboardGrab) if (keyboardGrab)
effects->ungrabKeyboard(); effects->ungrabKeyboard();
keyboardGrab = false; keyboardGrab = false;

View file

@ -15,6 +15,8 @@
#include <QObject> #include <QObject>
#include <QTimeLine> #include <QTimeLine>
class QTimer;
#include "kwineffectquickview.h" #include "kwineffectquickview.h"
namespace KWin namespace KWin
@ -52,6 +54,7 @@ public:
} }
enum { LayoutPager, LayoutAutomatic, LayoutCustom }; // Layout modes enum { LayoutPager, LayoutAutomatic, LayoutCustom }; // Layout modes
enum { SwitchDesktopAndActivateWindow, SwitchDesktopOnly }; // Click behavior
// for properties // for properties
int configuredZoomDuration() const { int configuredZoomDuration() const {
@ -70,7 +73,7 @@ public:
return customLayoutRows; return customLayoutRows;
} }
bool isUsePresentWindows() const { bool isUsePresentWindows() const {
return m_usePresentWindows; return clickBehavior == SwitchDesktopAndActivateWindow;
} }
private Q_SLOTS: private Q_SLOTS:
void toggle(); void toggle();
@ -114,6 +117,7 @@ private:
Qt::Alignment desktopNameAlignment; Qt::Alignment desktopNameAlignment;
int layoutMode; int layoutMode;
int customLayoutRows; int customLayoutRows;
int clickBehavior;
bool activated; bool activated;
QTimeLine timeline; QTimeLine timeline;
@ -126,6 +130,7 @@ private:
EffectWindow* windowMove; EffectWindow* windowMove;
QPoint windowMoveDiff; QPoint windowMoveDiff;
QPoint dragStartPos; QPoint dragStartPos;
QTimer *windowMoveElevateTimer;
// Soft highlighting // Soft highlighting
QList<QTimeLine*> hoverTimeline; QList<QTimeLine*> hoverTimeline;
@ -146,7 +151,6 @@ private:
PresentWindowsEffectProxy* m_proxy; PresentWindowsEffectProxy* m_proxy;
QList<WindowMotionManager> m_managers; QList<WindowMotionManager> m_managers;
bool m_usePresentWindows;
QRect m_windowMoveGeometry; QRect m_windowMoveGeometry;
QPoint m_windowMoveStartPoint; QPoint m_windowMoveStartPoint;

View file

@ -22,8 +22,8 @@
<entry name="CustomLayoutRows" type="Int"> <entry name="CustomLayoutRows" type="Int">
<default>2</default> <default>2</default>
</entry> </entry>
<entry name="PresentWindows" type="Bool"> <entry name="ClickBehavior" type="Int">
<default>true</default> <default code="true">0</default>
</entry> </entry>
<entry name="ShowAddRemove" type="Bool"> <entry name="ShowAddRemove" type="Bool">
<default>true</default> <default>true</default>

View file

@ -73,10 +73,14 @@ DesktopGridEffectConfig::DesktopGridEffectConfig(QWidget* parent, const QVariant
m_ui->desktopNameAlignmentCombo->addItem(i18n("Top-Left"), QVariant(Qt::AlignLeft | Qt::AlignTop)); m_ui->desktopNameAlignmentCombo->addItem(i18n("Top-Left"), QVariant(Qt::AlignLeft | Qt::AlignTop));
m_ui->desktopNameAlignmentCombo->addItem(i18n("Center"), QVariant(Qt::AlignCenter)); m_ui->desktopNameAlignmentCombo->addItem(i18n("Center"), QVariant(Qt::AlignCenter));
m_ui->clickBehaviorButtonGroup->setId(m_ui->switchDesktopAndActivateWindow, DesktopGridEffect::SwitchDesktopAndActivateWindow);
m_ui->clickBehaviorButtonGroup->setId(m_ui->switchDesktopOnly, DesktopGridEffect::SwitchDesktopOnly);
DesktopGridConfig::instance(KWIN_CONFIG); DesktopGridConfig::instance(KWIN_CONFIG);
addConfig(DesktopGridConfig::self(), m_ui); addConfig(DesktopGridConfig::self(), m_ui);
connect(m_ui->kcfg_LayoutMode, qOverload<int>(&KComboBox::currentIndexChanged), this, &DesktopGridEffectConfig::layoutSelectionChanged); connect(m_ui->kcfg_LayoutMode, qOverload<int>(&KComboBox::currentIndexChanged), this, &DesktopGridEffectConfig::layoutSelectionChanged);
connect(m_ui->desktopNameAlignmentCombo, qOverload<int>(&KComboBox::currentIndexChanged), this, &DesktopGridEffectConfig::markAsChanged); connect(m_ui->desktopNameAlignmentCombo, qOverload<int>(&KComboBox::currentIndexChanged), this, &DesktopGridEffectConfig::markAsChanged);
connect(m_ui->clickBehaviorButtonGroup, qOverload<int>(&QButtonGroup::buttonClicked), this, &DesktopGridEffectConfig::markAsChanged);
connect(m_ui->shortcutEditor, &KShortcutsEditor::keyChange, this, &DesktopGridEffectConfig::markAsChanged); connect(m_ui->shortcutEditor, &KShortcutsEditor::keyChange, this, &DesktopGridEffectConfig::markAsChanged);
load(); load();
@ -93,6 +97,7 @@ void DesktopGridEffectConfig::save()
{ {
m_ui->shortcutEditor->save(); m_ui->shortcutEditor->save();
DesktopGridConfig::setDesktopNameAlignment(m_ui->desktopNameAlignmentCombo->itemData(m_ui->desktopNameAlignmentCombo->currentIndex()).toInt()); DesktopGridConfig::setDesktopNameAlignment(m_ui->desktopNameAlignmentCombo->itemData(m_ui->desktopNameAlignmentCombo->currentIndex()).toInt());
DesktopGridConfig::setClickBehavior(m_ui->clickBehaviorButtonGroup->checkedId());
KCModule::save(); KCModule::save();
OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"), OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
@ -105,6 +110,10 @@ void DesktopGridEffectConfig::load()
{ {
KCModule::load(); KCModule::load();
m_ui->desktopNameAlignmentCombo->setCurrentIndex(m_ui->desktopNameAlignmentCombo->findData(QVariant(DesktopGridConfig::desktopNameAlignment()))); m_ui->desktopNameAlignmentCombo->setCurrentIndex(m_ui->desktopNameAlignmentCombo->findData(QVariant(DesktopGridConfig::desktopNameAlignment())));
QAbstractButton *clickBehaviorButton = m_ui->clickBehaviorButtonGroup->button(DesktopGridConfig::clickBehavior());
if (clickBehaviorButton) {
clickBehaviorButton->setChecked(true);
}
} }
void DesktopGridEffectConfig::layoutSelectionChanged() void DesktopGridEffectConfig::layoutSelectionChanged()
@ -122,6 +131,7 @@ void DesktopGridEffectConfig::defaults()
{ {
KCModule::defaults(); KCModule::defaults();
m_ui->desktopNameAlignmentCombo->setCurrentIndex(0); m_ui->desktopNameAlignmentCombo->setCurrentIndex(0);
m_ui->clickBehaviorButtonGroup->button(0)->setChecked(true);
} }
} // namespace } // namespace

View file

@ -171,7 +171,50 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="clickBehaviorLabel">
<property name="text">
<string>Click behavior:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>switchDesktopAndActivateWindow</cstring>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QRadioButton" name="switchDesktopAndActivateWindow">
<property name="toolTip">
<string>If the Present Windows effect is enabled, it will be automatically triggered.</string>
</property>
<property name="text">
<string>Switch desktop and activate window</string>
</property>
<attribute name="buttonGroup">
<string notr="true">clickBehaviorButtonGroup</string>
</attribute>
</widget>
</item>
<item row="6" column="1">
<widget class="QRadioButton" name="switchDesktopOnly">
<property name="text">
<string>Switch desktop only</string>
</property>
<attribute name="buttonGroup">
<string notr="true">clickBehaviorButtonGroup</string>
</attribute>
</widget>
</item>
<item row="7" column="0" colspan="2"> <item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="kcfg_ShowAddRemove">
<property name="text">
<string>Show buttons to alter count of virtual desktops</string>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -184,20 +227,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="kcfg_PresentWindows">
<property name="text">
<string>Use Present Windows effect to layout the windows</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="kcfg_ShowAddRemove">
<property name="text">
<string>Show buttons to alter count of virtual desktops</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -247,4 +276,7 @@
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>
<buttongroups>
<buttongroup name="clickBehaviorButtonGroup"/>
</buttongroups>
</ui> </ui>

View file

@ -4,6 +4,8 @@ install(PROGRAMS kwin-5.16-auto-bordersize.sh
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
install(PROGRAMS kwin-5.18-move-animspeed.py install(PROGRAMS kwin-5.18-move-animspeed.py
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
install(PROGRAMS kwin-5.21-desktop-grid-click-behavior.py
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
install(FILES kwinrules.upd install(FILES kwinrules.upd
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})

View file

@ -0,0 +1,18 @@
#!/usr/bin/env python
from __future__ import print_function
import sys
VALUE_MAP = {
'true': 0,
'false': 1,
}
if __name__ == '__main__':
for line in sys.stdin:
line = line.strip()
if line.startswith('PresentWindows='):
_, value = line.split('=', 1)
print("# DELETE PresentWindows")
print("ClickBehavior=%d" % VALUE_MAP[value])

View file

@ -37,3 +37,9 @@ Id=animation-speed
File=kwinrc,kdeglobals File=kwinrc,kdeglobals
Group=Compositing,KDE Group=Compositing,KDE
Script=kwin-5.18-move-animspeed.py,python3 Script=kwin-5.18-move-animspeed.py,python3
# In the Desktop Grid effect, replace the PresentWindows boolean with an enum
Id=desktop-grid-click-behavior
File=kwinrc
Group=Effect-DesktopGrid
Script=kwin-5.21-desktop-grid-click-behavior.py,python