mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-08-03 10:14:45 +00:00
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:
parent
151bb9dbfc
commit
3353cfc498
14 changed files with 129 additions and 2 deletions
|
|
@ -46,6 +46,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED
|
||||||
Qml
|
Qml
|
||||||
Quick
|
Quick
|
||||||
QuickCompiler
|
QuickCompiler
|
||||||
|
Feedback
|
||||||
)
|
)
|
||||||
|
|
||||||
if (QUICK_COMPILER)
|
if (QUICK_COMPILER)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||||
|
|
||||||
set(mobileshellplugin_SRCS
|
set(mobileshellplugin_SRCS
|
||||||
mobileshellplugin.cpp
|
mobileshellplugin.cpp
|
||||||
|
haptics.cpp
|
||||||
mobileshellsettings.cpp
|
mobileshellsettings.cpp
|
||||||
quicksetting.cpp
|
quicksetting.cpp
|
||||||
quicksettingsmodel.cpp
|
quicksettingsmodel.cpp
|
||||||
|
|
@ -37,6 +38,7 @@ target_link_libraries(mobileshellplugin
|
||||||
Qt::Qml
|
Qt::Qml
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
|
Qt::Feedback
|
||||||
KF5::ConfigWidgets # for KStandardAction
|
KF5::ConfigWidgets # for KStandardAction
|
||||||
KF5::KIOGui
|
KF5::KIOGui
|
||||||
KF5::Plasma
|
KF5::Plasma
|
||||||
|
|
|
||||||
26
components/mobileshell/haptics.cpp
Normal file
26
components/mobileshell/haptics.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
18
components/mobileshell/haptics.h
Normal file
18
components/mobileshell/haptics.h
Normal 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();
|
||||||
|
};
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "taskswitcher/displaysmodel.h"
|
#include "taskswitcher/displaysmodel.h"
|
||||||
|
|
||||||
|
#include "haptics.h"
|
||||||
#include "mobileshellsettings.h"
|
#include "mobileshellsettings.h"
|
||||||
#include "quicksetting.h"
|
#include "quicksetting.h"
|
||||||
#include "quicksettingsmodel.h"
|
#include "quicksettingsmodel.h"
|
||||||
|
|
@ -38,6 +39,10 @@ void MobileShellPlugin::registerTypes(const char *uri)
|
||||||
return ShellUtil::instance();
|
return ShellUtil::instance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
qmlRegisterSingletonType<Haptics>(uri, 1, 0, "Haptics", [](QQmlEngine *, QJSEngine *) -> QObject * {
|
||||||
|
return Haptics::self();
|
||||||
|
});
|
||||||
|
|
||||||
qmlRegisterSingletonType<MobileShellSettings>(uri, 1, 0, "MobileShellSettings", [](QQmlEngine *, QJSEngine *) -> QObject * {
|
qmlRegisterSingletonType<MobileShellSettings>(uri, 1, 0, "MobileShellSettings", [](QQmlEngine *, QJSEngine *) -> QObject * {
|
||||||
return MobileShellSettings::self();
|
return MobileShellSettings::self();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ MobileShellSettings::MobileShellSettings(QObject *parent)
|
||||||
|
|
||||||
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group, const QByteArrayList &names) -> void {
|
||||||
if (group.name() == GENERAL_CONFIG_GROUP) {
|
if (group.name() == GENERAL_CONFIG_GROUP) {
|
||||||
|
Q_EMIT vibrationsEnabledChanged();
|
||||||
Q_EMIT navigationPanelEnabledChanged();
|
Q_EMIT navigationPanelEnabledChanged();
|
||||||
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
} else if (group.name() == QUICKSETTINGS_CONFIG_GROUP) {
|
||||||
Q_EMIT enabledQuickSettingsChanged();
|
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
|
bool MobileShellSettings::navigationPanelEnabled() const
|
||||||
{
|
{
|
||||||
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
auto group = KConfigGroup{m_config, GENERAL_CONFIG_GROUP};
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
class MobileShellSettings : public QObject
|
class MobileShellSettings : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool vibrationsEnabled READ vibrationsEnabled WRITE setVibrationsEnabled NOTIFY vibrationsEnabledChanged)
|
||||||
Q_PROPERTY(bool navigationPanelEnabled READ navigationPanelEnabled WRITE setNavigationPanelEnabled NOTIFY navigationPanelEnabledChanged)
|
Q_PROPERTY(bool navigationPanelEnabled READ navigationPanelEnabled WRITE setNavigationPanelEnabled NOTIFY navigationPanelEnabledChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -21,6 +22,9 @@ public:
|
||||||
|
|
||||||
MobileShellSettings(QObject *parent = nullptr);
|
MobileShellSettings(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool vibrationsEnabled() const;
|
||||||
|
void setVibrationsEnabled(bool vibrationsEnabled);
|
||||||
|
|
||||||
bool navigationPanelEnabled() const;
|
bool navigationPanelEnabled() const;
|
||||||
void setNavigationPanelEnabled(bool navigationPanelEnabled);
|
void setNavigationPanelEnabled(bool navigationPanelEnabled);
|
||||||
|
|
||||||
|
|
@ -31,6 +35,7 @@ public:
|
||||||
void setDisabledQuickSettings(QList<QString> &list);
|
void setDisabledQuickSettings(QList<QString> &list);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void vibrationsEnabledChanged();
|
||||||
void navigationPanelEnabledChanged();
|
void navigationPanelEnabledChanged();
|
||||||
void enabledQuickSettingsChanged();
|
void enabledQuickSettingsChanged();
|
||||||
void disabledQuickSettingsChanged();
|
void disabledQuickSettingsChanged();
|
||||||
|
|
|
||||||
|
|
@ -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.core 2.0 as PlasmaCore
|
||||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
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 org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
|
|
||||||
import "../../components" as Components
|
import "../../components" as Components
|
||||||
|
|
@ -41,8 +42,14 @@ QuickSettingsDelegate {
|
||||||
|
|
||||||
contentItem: MouseArea {
|
contentItem: MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
|
||||||
|
onPressed: MobileShell.Haptics.buttonVibrate()
|
||||||
onClicked: root.delegateClick()
|
onClicked: root.delegateClick()
|
||||||
onPressAndHold: root.delegatePressAndHold()
|
onPressAndHold: {
|
||||||
|
MobileShell.Haptics.buttonVibrate();
|
||||||
|
root.delegatePressAndHold();
|
||||||
|
}
|
||||||
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
PlasmaCore.IconItem {
|
PlasmaCore.IconItem {
|
||||||
|
|
|
||||||
|
|
@ -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.core 2.0 as PlasmaCore
|
||||||
import org.kde.plasma.private.nanoshell 2.0 as NanoShell
|
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 org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
|
|
||||||
import "../../components" as Components
|
import "../../components" as Components
|
||||||
|
|
@ -37,8 +38,14 @@ QuickSettingsDelegate {
|
||||||
|
|
||||||
contentItem: MouseArea {
|
contentItem: MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
|
|
||||||
|
onPressed: MobileShell.Haptics.buttonVibrate();
|
||||||
onClicked: root.delegateClick()
|
onClicked: root.delegateClick()
|
||||||
onPressAndHold: root.delegatePressAndHold()
|
onPressAndHold: {
|
||||||
|
MobileShell.Haptics.buttonVibrate();
|
||||||
|
root.delegatePressAndHold();
|
||||||
|
}
|
||||||
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
|
||||||
PlasmaCore.IconItem {
|
PlasmaCore.IconItem {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@ Item {
|
||||||
startMouseX = oldMouseX = mouse.y;
|
startMouseX = oldMouseX = mouse.y;
|
||||||
startMouseY = oldMouseY = mouse.y;
|
startMouseY = oldMouseY = mouse.y;
|
||||||
activeButton = icons.childAt(mouse.x, mouse.y);
|
activeButton = icons.childAt(mouse.x, mouse.y);
|
||||||
|
if (activeButton && activeButton.enabled) {
|
||||||
|
MobileShell.Haptics.buttonVibrate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,30 @@ KCM.SimpleKCM {
|
||||||
MobileForm.FormCard {
|
MobileForm.FormCard {
|
||||||
Layout.fillWidth: true
|
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 {
|
contentItem: ColumnLayout {
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,12 @@ import QtQuick 2.12
|
||||||
import QtQuick.Controls 2.1
|
import QtQuick.Controls 2.1
|
||||||
import QtQuick.Layouts 1.1
|
import QtQuick.Layouts 1.1
|
||||||
import QtGraphicalEffects 1.12
|
import QtGraphicalEffects 1.12
|
||||||
|
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents
|
import org.kde.plasma.components 3.0 as PlasmaComponents
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
import org.kde.plasma.workspace.keyboardlayout 1.0
|
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
|
import org.kde.kirigami 2.12 as Kirigami
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|
@ -188,6 +191,7 @@ Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onPressedChanged: {
|
onPressedChanged: {
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
|
MobileShell.Haptics.buttonVibrate();
|
||||||
parent.color = keypadRoot.buttonPressedColor;
|
parent.color = keypadRoot.buttonPressedColor;
|
||||||
} else {
|
} else {
|
||||||
parent.color = keypadRoot.buttonColor;
|
parent.color = keypadRoot.buttonColor;
|
||||||
|
|
@ -205,6 +209,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
onPressAndHold: {
|
onPressAndHold: {
|
||||||
if (modelData === "R") {
|
if (modelData === "R") {
|
||||||
|
MobileShell.Haptics.buttonVibrate();
|
||||||
passwordBar.clear();
|
passwordBar.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import QtQuick 2.8
|
import QtQuick 2.8
|
||||||
|
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
import org.kde.plasma.components 3.0 as PlasmaComponents3
|
||||||
|
import org.kde.plasma.private.mobileshell 1.0 as MobileShell
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
@ -19,6 +21,7 @@ Item {
|
||||||
property alias circleVisiblity: iconCircle.visible
|
property alias circleVisiblity: iconCircle.visible
|
||||||
property int fontSize: config.fontSize
|
property int fontSize: config.fontSize
|
||||||
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
|
readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software
|
||||||
|
|
||||||
signal clicked
|
signal clicked
|
||||||
|
|
||||||
activeFocusOnTab: true
|
activeFocusOnTab: true
|
||||||
|
|
@ -102,6 +105,7 @@ Item {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onClicked: root.clicked()
|
onClicked: root.clicked()
|
||||||
|
onPressed: MobileShell.Haptics.buttonVibrate();
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import QtQuick.Controls 2.8 as Controls
|
||||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||||
import org.kde.kcoreaddons 1.0 as KCoreAddons
|
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
|
import org.kde.plasma.private.sessions 2.0
|
||||||
|
|
||||||
PlasmaCore.ColorScope {
|
PlasmaCore.ColorScope {
|
||||||
|
|
@ -27,6 +28,8 @@ PlasmaCore.ColorScope {
|
||||||
signal cancelRequested()
|
signal cancelRequested()
|
||||||
signal lockScreenRequested()
|
signal lockScreenRequested()
|
||||||
|
|
||||||
|
Component.onCompleted: MobileShell.Haptics.buttonVibrate();
|
||||||
|
|
||||||
Controls.Action {
|
Controls.Action {
|
||||||
onTriggered: root.cancelRequested()
|
onTriggered: root.cancelRequested()
|
||||||
shortcut: "Escape"
|
shortcut: "Escape"
|
||||||
|
|
@ -55,6 +58,7 @@ PlasmaCore.ColorScope {
|
||||||
|
|
||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
id: openAnim
|
id: openAnim
|
||||||
|
running: true
|
||||||
ScaleAnimator {
|
ScaleAnimator {
|
||||||
target: lay
|
target: lay
|
||||||
from: 10
|
from: 10
|
||||||
|
|
@ -80,6 +84,8 @@ PlasmaCore.ColorScope {
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
id: closeAnim
|
id: closeAnim
|
||||||
|
running: false
|
||||||
|
|
||||||
property var callback
|
property var callback
|
||||||
function execute(call) {
|
function execute(call) {
|
||||||
callback = call;
|
callback = call;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue