kcm: Add vibration setting for shell, and add vibrations

We can control shell vibrations from here, which can be replaced once there is a mechanism to control system-wide vibrations for QtFeedback.
This commit is contained in:
Devin Lin 2022-04-29 16:15:53 -04:00
parent 151bb9dbfc
commit 3353cfc498
14 changed files with 129 additions and 2 deletions

View file

@ -46,6 +46,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED
Qml
Quick
QuickCompiler
Feedback
)
if (QUICK_COMPILER)

View file

@ -6,6 +6,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
set(mobileshellplugin_SRCS
mobileshellplugin.cpp
haptics.cpp
mobileshellsettings.cpp
quicksetting.cpp
quicksettingsmodel.cpp
@ -37,6 +38,7 @@ target_link_libraries(mobileshellplugin
Qt::Qml
Qt::Gui
Qt::Quick
Qt::Feedback
KF5::ConfigWidgets # for KStandardAction
KF5::KIOGui
KF5::Plasma

View file

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "haptics.h"
#include <QFeedbackHapticsEffect>
#include "mobileshellsettings.h"
Haptics *Haptics::self()
{
static Haptics *singleton = new Haptics();
return singleton;
}
void Haptics::buttonVibrate()
{
if (MobileShellSettings::self()->vibrationsEnabled()) {
QFeedbackHapticsEffect rumble;
rumble.setIntensity(0.5);
rumble.setDuration(100);
rumble.start();
}
}

View file

@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QObject>
class Haptics : public QObject
{
Q_OBJECT
public:
static Haptics *self();
Q_INVOKABLE void buttonVibrate();
};

View file

@ -19,6 +19,7 @@
#include "taskswitcher/displaysmodel.h"
#include "haptics.h"
#include "mobileshellsettings.h"
#include "quicksetting.h"
#include "quicksettingsmodel.h"
@ -38,6 +39,10 @@ void MobileShellPlugin::registerTypes(const char *uri)
return ShellUtil::instance();
});
qmlRegisterSingletonType<Haptics>(uri, 1, 0, "Haptics", [](QQmlEngine *, QJSEngine *) -> QObject * {
return Haptics::self();
});
qmlRegisterSingletonType<MobileShellSettings>(uri, 1, 0, "MobileShellSettings", [](QQmlEngine *, QJSEngine *) -> QObject * {
return MobileShellSettings::self();
});

View file

@ -26,6 +26,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
if (group.name() == GENERAL_CONFIG_GROUP) {
Q_EMIT vibrationsEnabledChanged();
Q_EMIT navigationPanelEnabledChanged();
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
Q_EMIT enabledQuickSettingsChanged();
@ -34,6 +35,19 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
});
}
bool MobileShellSettings::vibrationsEnabled() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
return group.readEntry("vibrationsEnabled", true);
}
void MobileShellSettings::setVibrationsEnabled(bool vibrationsEnabled)
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
group.writeEntry("vibrationsEnabled", vibrationsEnabled, KConfigGroup::Notify);
m_config->sync();
}
bool MobileShellSettings::navigationPanelEnabled() const
{
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};

View file

@ -14,6 +14,7 @@
class MobileShellSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(bool vibrationsEnabled READ vibrationsEnabled WRITE setVibrationsEnabled NOTIFY vibrationsEnabledChanged)
Q_PROPERTY(bool navigationPanelEnabled READ navigationPanelEnabled WRITE setNavigationPanelEnabled NOTIFY navigationPanelEnabledChanged)
public:
@ -21,6 +22,9 @@ public:
MobileShellSettings(QObject *parent = nullptr);
bool vibrationsEnabled() const;
void setVibrationsEnabled(bool vibrationsEnabled);
bool navigationPanelEnabled() const;
void setNavigationPanelEnabled(bool navigationPanelEnabled);
@ -31,6 +35,7 @@ public:
void setDisabledQuickSettings(QList<QString> &list);
Q_SIGNALS:
void vibrationsEnabledChanged();
void navigationPanelEnabledChanged();
void enabledQuickSettingsChanged();
void disabledQuickSettingsChanged();

View file

@ -12,6 +12,7 @@ import org.kde.kirigami 2.12 as Kirigami
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import org.kde.plasma.components 3.0 as PlasmaComponents
import "../../components" as Components
@ -41,8 +42,14 @@ QuickSettingsDelegate {
contentItem: MouseArea {
id: mouseArea
onPressed: MobileShell.Haptics.buttonVibrate()
onClicked: root.delegateClick()
onPressAndHold: root.delegatePressAndHold()
onPressAndHold: {
MobileShell.Haptics.buttonVibrate();
root.delegatePressAndHold();
}
cursorShape: Qt.PointingHandCursor
PlasmaCore.IconItem {

View file

@ -11,6 +11,7 @@ import org.kde.kirigami 2.12 as Kirigami
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import org.kde.plasma.components 3.0 as PlasmaComponents
import "../../components" as Components
@ -37,8 +38,14 @@ QuickSettingsDelegate {
contentItem: MouseArea {
id: mouseArea
onPressed: MobileShell.Haptics.buttonVibrate();
onClicked: root.delegateClick()
onPressAndHold: root.delegatePressAndHold()
onPressAndHold: {
MobileShell.Haptics.buttonVibrate();
root.delegatePressAndHold();
}
cursorShape: Qt.PointingHandCursor
PlasmaCore.IconItem {

View file

@ -61,6 +61,9 @@ Item {
startMouseX = oldMouseX = mouse.y;
startMouseY = oldMouseY = mouse.y;
activeButton = icons.childAt(mouse.x, mouse.y);
if (activeButton && activeButton.enabled) {
MobileShell.Haptics.buttonVibrate();
}
}
onPositionChanged: {

View file

@ -30,6 +30,30 @@ KCM.SimpleKCM {
MobileForm.FormCard {
Layout.fillWidth: true
contentItem: ColumnLayout {
spacing: 0
MobileForm.FormCardHeader {
title: i18n("General")
}
MobileForm.FormSwitchDelegate {
text: i18n("Shell Vibrations")
description: i18n("Whether to have vibrations enabled in the shell.")
checked: !MobileShell.MobileShellSettings.vibrationsEnabled
onCheckedChanged: {
if (checked != !MobileShell.MobileShellSettings.vibrationsEnabled) {
MobileShell.MobileShellSettings.vibrationsEnabled = !checked;
}
}
}
}
}
MobileForm.FormCard {
Layout.fillWidth: true
Layout.topMargin: Kirigami.Units.largeSpacing
contentItem: ColumnLayout {
spacing: 0

View file

@ -8,9 +8,12 @@ import QtQuick 2.12
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.12
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import org.kde.kirigami 2.12 as Kirigami
Rectangle {
@ -188,6 +191,7 @@ Rectangle {
anchors.fill: parent
onPressedChanged: {
if (pressed) {
MobileShell.Haptics.buttonVibrate();
parent.color = keypadRoot.buttonPressedColor;
} else {
parent.color = keypadRoot.buttonColor;
@ -205,6 +209,7 @@ Rectangle {
}
onPressAndHold: {
if (modelData === "R") {
MobileShell.Haptics.buttonVibrate();
passwordBar.clear();
}
}

View file

@ -5,8 +5,10 @@
*/
import QtQuick 2.8
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents3
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
Item {
id: root
@ -19,6 +21,7 @@ Item {
property alias circleVisiblity: iconCircle.visible
property int fontSize: config.fontSize
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
signal clicked
activeFocusOnTab: true
@ -102,6 +105,7 @@ Item {
id: mouseArea
hoverEnabled: true
onClicked: root.clicked()
onPressed: MobileShell.Haptics.buttonVibrate();
anchors.fill: parent
}

View file

@ -13,6 +13,7 @@ import QtQuick.Controls 2.8 as Controls
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.kcoreaddons 1.0 as KCoreAddons
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
import org.kde.plasma.private.sessions 2.0
PlasmaCore.ColorScope {
@ -27,6 +28,8 @@ PlasmaCore.ColorScope {
signal cancelRequested()
signal lockScreenRequested()
Component.onCompleted: MobileShell.Haptics.buttonVibrate();
Controls.Action {
onTriggered: root.cancelRequested()
shortcut: "Escape"
@ -55,6 +58,7 @@ PlasmaCore.ColorScope {
ParallelAnimation {
id: openAnim
running: true
ScaleAnimator {
target: lay
from: 10
@ -80,6 +84,8 @@ PlasmaCore.ColorScope {
SequentialAnimation {
id: closeAnim
running: false
property var callback
function execute(call) {
callback = call;