mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-07-31 16:54:46 +00:00
navigationpanel: Add manual screen rotation button
When the device is rotated and autorotate is off, a button will appear on the navigation panel to manually rotate. This is specific to the navigation panel, perhaps we can have a floating button in gesture-only mode similar to Android? TODO: PoC, I haven't yet actually tested this on device. I also need to make sure that I check for whether autorotation is enabled on the output.
This commit is contained in:
parent
aa3e42f65a
commit
3d9ddbde15
5 changed files with 188 additions and 0 deletions
|
|
@ -54,6 +54,21 @@ Item {
|
||||||
color: root.backgroundColor
|
color: root.backgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NavigationPanelButton {
|
||||||
|
id: leftCornerButton
|
||||||
|
visible: root.leftCornerAction.visible
|
||||||
|
Kirigami.Theme.colorSet: root.foregroundColorGroup
|
||||||
|
Kirigami.Theme.inherit: false
|
||||||
|
enabled: root.leftCornerAction.enabled
|
||||||
|
iconSizeFactor: root.leftCornerAction.iconSizeFactor
|
||||||
|
iconSource: root.leftCornerAction.iconSource
|
||||||
|
onClicked: {
|
||||||
|
if (enabled) {
|
||||||
|
root.leftCornerAction.triggered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// button row (anchors provided by state)
|
// button row (anchors provided by state)
|
||||||
NavigationPanelButton {
|
NavigationPanelButton {
|
||||||
id: leftButton
|
id: leftButton
|
||||||
|
|
@ -166,6 +181,18 @@ Item {
|
||||||
height: Kirigami.Units.gridUnit * 2
|
height: Kirigami.Units.gridUnit * 2
|
||||||
width: icons.width
|
width: icons.width
|
||||||
}
|
}
|
||||||
|
AnchorChanges {
|
||||||
|
target: leftCornerButton
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: leftCornerButton
|
||||||
|
height: Kirigami.Units.gridUnit * 2
|
||||||
|
width: icons.width
|
||||||
|
}
|
||||||
}, State {
|
}, State {
|
||||||
name: "horizontal"
|
name: "horizontal"
|
||||||
when: !root.isVertical
|
when: !root.isVertical
|
||||||
|
|
@ -214,6 +241,18 @@ Item {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: Kirigami.Units.gridUnit * 2
|
width: Kirigami.Units.gridUnit * 2
|
||||||
}
|
}
|
||||||
|
AnchorChanges {
|
||||||
|
target: leftCornerButton
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyChanges {
|
||||||
|
target: leftCornerButton
|
||||||
|
height: parent.height
|
||||||
|
width: Kirigami.Units.gridUnit * 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@ target_link_libraries(org.kde.plasma.mobile.taskpanel
|
||||||
Qt::DBus
|
Qt::DBus
|
||||||
Qt::Qml
|
Qt::Qml
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
|
Qt::Sensors
|
||||||
Plasma::Plasma
|
Plasma::Plasma
|
||||||
|
KF6::Screen
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,18 @@ MobileShell.NavigationPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leftCornerAction: MobileShell.NavigationPanelAction {
|
||||||
|
id: rotationAction
|
||||||
|
visible: Plasmoid.showRotationButton
|
||||||
|
enabled: true
|
||||||
|
iconSource: "rotation-allowed-symbolic"
|
||||||
|
iconSizeFactor: 0.75
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
Plasmoid.rotateToSuggestedRotation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rightCornerAction: MobileShell.NavigationPanelAction {
|
rightCornerAction: MobileShell.NavigationPanelAction {
|
||||||
id: keyboardToggleAction
|
id: keyboardToggleAction
|
||||||
visible: ShellSettings.Settings.alwaysShowKeyboardToggleOnNavigationPanel ||
|
visible: ShellSettings.Settings.alwaysShowKeyboardToggleOnNavigationPanel ||
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,54 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
#include <kscreen/configmonitor.h>
|
||||||
|
#include <kscreen/getconfigoperation.h>
|
||||||
|
#include <kscreen/output.h>
|
||||||
|
#include <kscreen/setconfigoperation.h>
|
||||||
|
|
||||||
// register type for Keyboards.KWinVirtualKeyboard.forceActivate();
|
// register type for Keyboards.KWinVirtualKeyboard.forceActivate();
|
||||||
Q_DECLARE_METATYPE(QDBusPendingReply<>)
|
Q_DECLARE_METATYPE(QDBusPendingReply<>)
|
||||||
|
|
||||||
|
KScreen::Output::Rotation mapReadingOrientation(QOrientationReading::Orientation orientation)
|
||||||
|
{
|
||||||
|
switch (orientation) {
|
||||||
|
case QOrientationReading::Orientation::TopUp:
|
||||||
|
return KScreen::Output::Rotation::None;
|
||||||
|
case QOrientationReading::Orientation::TopDown:
|
||||||
|
return KScreen::Output::Rotation::Inverted;
|
||||||
|
case QOrientationReading::Orientation::LeftUp:
|
||||||
|
return KScreen::Output::Rotation::Left;
|
||||||
|
case QOrientationReading::Orientation::RightUp:
|
||||||
|
return KScreen::Output::Rotation::Right;
|
||||||
|
case QOrientationReading::Orientation::FaceUp:
|
||||||
|
case QOrientationReading::Orientation::FaceDown:
|
||||||
|
case QOrientationReading::Orientation::Undefined:
|
||||||
|
return KScreen::Output::Rotation::None;
|
||||||
|
}
|
||||||
|
return KScreen::Output::Rotation::None;
|
||||||
|
}
|
||||||
|
|
||||||
TaskPanel::TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
|
TaskPanel::TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
|
||||||
: Plasma::Containment(parent, data, args)
|
: Plasma::Containment(parent, data, args)
|
||||||
|
, m_sensor{new QOrientationSensor(this)}
|
||||||
{
|
{
|
||||||
|
connect(new KScreen::GetConfigOperation(), &KScreen::GetConfigOperation::finished, this, [this](auto *op) {
|
||||||
|
m_config = qobject_cast<KScreen::GetConfigOperation *>(op)->config();
|
||||||
|
KScreen::ConfigMonitor::instance()->addConfig(m_config);
|
||||||
|
|
||||||
|
// update all screens with event connect
|
||||||
|
for (KScreen::OutputPtr output : m_config->outputs()) {
|
||||||
|
connect(output.data(), &KScreen::Output::autoRotatePolicyChanged, this, &TaskPanel::updateShowRotationButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen to all new screens and connect
|
||||||
|
connect(m_config.data(), &KScreen::Config::outputAdded, this, [this](const auto &output) {
|
||||||
|
connect(output.data(), &KScreen::Output::autoRotatePolicyChanged, this, &TaskPanel::updateShowRotationButton);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(m_sensor, &QOrientationSensor::readingChanged, this, &TaskPanel::updateShowRotationButton);
|
||||||
|
m_sensor->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TaskPanel::triggerTaskSwitcher() const
|
void TaskPanel::triggerTaskSwitcher() const
|
||||||
|
|
@ -28,6 +70,79 @@ void TaskPanel::triggerTaskSwitcher() const
|
||||||
QDBusConnection::sessionBus().send(message);
|
QDBusConnection::sessionBus().send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TaskPanel::rotateToSuggestedRotation()
|
||||||
|
{
|
||||||
|
if (!m_config || !m_showRotationButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto outputs = m_config->outputs();
|
||||||
|
if (outputs.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: Assume the output we care about is the first device
|
||||||
|
for (KScreen::OutputPtr output : outputs) {
|
||||||
|
// apparently it's possible to get nullptr outputs?
|
||||||
|
if (!output) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->setRotation(m_rotateTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto setop = new KScreen::SetConfigOperation(m_config, this);
|
||||||
|
setop->exec();
|
||||||
|
|
||||||
|
updateShowRotationButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TaskPanel::showRotationButton() const
|
||||||
|
{
|
||||||
|
return m_showRotationButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TaskPanel::updateShowRotationButton()
|
||||||
|
{
|
||||||
|
if (!m_config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QOrientationReading *reading = m_sensor->reading();
|
||||||
|
if (!reading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rotateTo = mapReadingOrientation(reading->orientation());
|
||||||
|
|
||||||
|
const auto outputs = m_config->outputs();
|
||||||
|
|
||||||
|
if (outputs.empty()) {
|
||||||
|
m_showRotationButton = false;
|
||||||
|
Q_EMIT showRotationButtonChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: Assume the output we care about is the first device
|
||||||
|
for (KScreen::OutputPtr output : outputs) {
|
||||||
|
if (!output) {
|
||||||
|
// apparently it's possible to get nullptr outputs?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (output->autoRotatePolicy() == KScreen::Output::AutoRotatePolicy::Always) {
|
||||||
|
// only check displays that have autorotate on
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_showRotationButton = output->rotation() != m_rotateTo;
|
||||||
|
Q_EMIT showRotationButtonChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_showRotationButton = false;
|
||||||
|
Q_EMIT showRotationButtonChanged();
|
||||||
|
}
|
||||||
|
|
||||||
K_PLUGIN_CLASS(TaskPanel)
|
K_PLUGIN_CLASS(TaskPanel)
|
||||||
|
|
||||||
#include "taskpanel.moc"
|
#include "taskpanel.moc"
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,33 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Plasma/Containment>
|
#include <Plasma/Containment>
|
||||||
|
#include <QOrientationSensor>
|
||||||
|
|
||||||
|
#include <kscreen/config.h>
|
||||||
|
|
||||||
class TaskPanel : public Plasma::Containment
|
class TaskPanel : public Plasma::Containment
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool showRotationButton READ showRotationButton NOTIFY showRotationButtonChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
|
TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args);
|
||||||
|
|
||||||
Q_INVOKABLE void triggerTaskSwitcher() const;
|
Q_INVOKABLE void triggerTaskSwitcher() const;
|
||||||
|
|
||||||
|
bool showRotationButton() const;
|
||||||
|
Q_INVOKABLE void rotateToSuggestedRotation();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void showRotationButtonChanged();
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void updateShowRotationButton();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_showRotationButton{false};
|
||||||
|
KScreen::Output::Rotation m_rotateTo;
|
||||||
|
|
||||||
|
KScreen::ConfigPtr m_config{nullptr};
|
||||||
|
QOrientationSensor *m_sensor{nullptr};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue