plugins: add a "hidecursor" effect

This hides the mouse cursor on inactivity or keypress (configurable in the KCM).

BUG: 465119
This commit is contained in:
Jin Liu 2024-02-28 11:23:21 +00:00
parent 494daab3d5
commit 7d7344a983
11 changed files with 344 additions and 0 deletions

View file

@ -66,6 +66,7 @@ add_subdirectory(fallapart)
add_subdirectory(frozenapp)
add_subdirectory(fullscreen)
add_subdirectory(glide)
add_subdirectory(hidecursor)
add_subdirectory(highlightwindow)
add_subdirectory(idletime)
add_subdirectory(invert)

View file

@ -0,0 +1,34 @@
kwin_add_builtin_effect(hidecursor)
target_sources(hidecursor PRIVATE
hidecursor.cpp
main.cpp
)
kconfig_add_kcfg_files(hidecursor
hidecursorconfig.kcfgc
)
target_link_libraries(hidecursor PRIVATE
kwin
KF6::ConfigGui
)
#######################################
# Config
if (KWIN_BUILD_KCMS)
set(kwin_hidecursor_config_SRCS hidecursor_config.cpp)
ki18n_wrap_ui(kwin_hidecursor_config_SRCS hidecursor_config.ui)
kconfig_add_kcfg_files(kwin_hidecursor_config_SRCS hidecursorconfig.kcfgc)
kwin_add_effect_config(kwin_hidecursor_config ${kwin_hidecursor_config_SRCS})
target_link_libraries(kwin_hidecursor_config
KF6::KCMUtils
KF6::CoreAddons
KF6::I18n
KF6::XmlGui
KWinEffectsInterface
)
endif()

View file

@ -0,0 +1,107 @@
/*
SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "hidecursor.h"
#include "cursor.h"
#include "effect/effecthandler.h"
#include "hidecursorconfig.h"
#include "input_event.h"
namespace KWin
{
HideCursorEffect::HideCursorEffect()
: m_cursor(Cursors::self()->mouse())
{
input()->installInputEventSpy(this);
m_inactivityTimer.setSingleShot(true);
connect(&m_inactivityTimer, &QTimer::timeout, this, [this]() {
hideCursor();
});
HideCursorConfig::instance(effects->config());
reconfigure(ReconfigureAll);
}
HideCursorEffect::~HideCursorEffect()
{
showCursor();
}
bool HideCursorEffect::supported()
{
return effects->waylandDisplay();
}
void HideCursorEffect::reconfigure(ReconfigureFlags flags)
{
HideCursorConfig::self()->read();
m_inactivityDuration = HideCursorConfig::inactivityDuration() * 1000;
m_hideOnTyping = HideCursorConfig::hideOnTyping();
m_inactivityTimer.stop();
showCursor();
if (m_inactivityDuration > 0) {
m_inactivityTimer.start(m_inactivityDuration);
}
}
bool HideCursorEffect::isActive() const
{
return false;
}
void HideCursorEffect::pointerEvent(MouseEvent *event)
{
showCursor();
if (m_inactivityDuration > 0) {
m_inactivityTimer.start(m_inactivityDuration);
}
}
void HideCursorEffect::keyEvent(KeyEvent *event)
{
if (m_hideOnTyping && event->type() == QEvent::KeyPress) {
auto key = event->key();
switch (key) {
case Qt::Key_Shift:
case Qt::Key_Control:
case Qt::Key_Meta:
case Qt::Key_Alt:
case Qt::Key_AltGr:
case Qt::Key_Super_L:
case Qt::Key_Super_R:
case Qt::Key_Hyper_L:
case Qt::Key_Hyper_R:
case Qt::Key_Escape:
break;
default:
hideCursor();
}
}
}
void HideCursorEffect::showCursor()
{
if (m_cursorHidden) {
effects->showCursor();
m_cursorHidden = false;
}
}
void HideCursorEffect::hideCursor()
{
if (!m_cursorHidden) {
effects->hideCursor();
m_cursorHidden = true;
}
}
} // namespace KWin
#include "moc_hidecursor.cpp"

View file

@ -0,0 +1,47 @@
/*
SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "effect/effect.h"
#include "input_event_spy.h"
#include <QTimer>
namespace KWin
{
class Cursor;
class HideCursorEffect : public Effect, public InputEventSpy
{
Q_OBJECT
public:
HideCursorEffect();
~HideCursorEffect() override;
static bool supported();
void reconfigure(ReconfigureFlags flags) override;
bool isActive() const override;
void pointerEvent(MouseEvent *event) override;
void keyEvent(KeyEvent *event) override;
private:
void showCursor();
void hideCursor();
int m_inactivityDuration;
bool m_hideOnTyping;
Cursor *m_cursor;
bool m_cursorHidden = false;
QTimer m_inactivityTimer;
};
} // namespace KWin

View file

@ -0,0 +1,43 @@
/*
SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "hidecursor_config.h"
#include <config-kwin.h>
// KConfigSkeleton
#include "hidecursorconfig.h"
#include <KPluginFactory>
#include <kwineffects_interface.h>
K_PLUGIN_CLASS(KWin::HideCursorEffectConfig)
namespace KWin
{
HideCursorEffectConfig::HideCursorEffectConfig(QObject *parent, const KPluginMetaData &data)
: KCModule(parent, data)
{
HideCursorConfig::instance(KWIN_CONFIG);
m_ui.setupUi(widget());
addConfig(HideCursorConfig::self(), widget());
}
void HideCursorEffectConfig::save()
{
KCModule::save();
OrgKdeKwinEffectsInterface interface(QStringLiteral("org.kde.KWin"),
QStringLiteral("/Effects"),
QDBusConnection::sessionBus());
interface.reconfigureEffect(QStringLiteral("hidecursor"));
}
} // namespace
#include "hidecursor_config.moc"
#include "moc_hidecursor_config.cpp"

View file

@ -0,0 +1,30 @@
/*
SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <kcmodule.h>
#include "ui_hidecursor_config.h"
class KActionCollection;
namespace KWin
{
class HideCursorEffectConfig : public KCModule
{
Q_OBJECT
public:
explicit HideCursorEffectConfig(QObject *parent, const KPluginMetaData &data);
public Q_SLOTS:
void save() override;
private:
Ui::HideCursorEffectConfig m_ui;
};
} // namespace

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HideCursorEffectConfig</class>
<widget class="QWidget" name="HideCursorEffectConfig">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_InactivityDuration">
<property name="text">
<string>Inactivity duration (seconds):</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="kcfg_InactivityDuration">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="kcfg_HideOnTyping">
<property name="text">
<string>Hide cursor on typing</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile arg="true"/>
<group name="Effect-hidecursor">
<entry name="InactivityDuration" type="UInt">
<default>5</default>
</entry>
<entry name="HideOnTyping" type="Bool">
<default>false</default>
</entry>
</group>
</kcfg>

View file

@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0-or-later
File=hidecursorconfig.kcfg
ClassName=HideCursorConfig
NameSpace=KWin
Singleton=true

View file

@ -0,0 +1,18 @@
/*
SPDX-FileCopyrightText: 2024 Jin Liu <m.liu.jin@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "hidecursor.h"
namespace KWin
{
KWIN_EFFECT_FACTORY_SUPPORTED(HideCursorEffect,
"metadata.json.stripped",
return HideCursorEffect::supported();)
} // namespace KWin
#include "main.moc"

View file

@ -0,0 +1,10 @@
{
"KPlugin": {
"Category": "Accessibility",
"Description": "Hide mouse cursor on inactivity or keyboard input",
"EnabledByDefault": false,
"License": "GPL",
"Name": "Hide Cursor"
},
"X-KDE-ConfigModule": "kwin_hidecursor_config"
}