2021-03-01 20:03:25 +00:00
|
|
|
/*
|
|
|
|
|
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
*/
|
2016-08-24 14:57:15 +00:00
|
|
|
|
|
|
|
|
#include "taskpanel.h"
|
|
|
|
|
|
2023-11-14 06:37:08 +00:00
|
|
|
#include <QDBusConnection>
|
2022-09-12 00:17:29 +00:00
|
|
|
#include <QDBusPendingReply>
|
2016-08-24 14:57:15 +00:00
|
|
|
#include <QDebug>
|
2023-09-13 22:17:11 +00:00
|
|
|
#include <QGuiApplication>
|
2016-08-24 14:57:15 +00:00
|
|
|
|
2024-11-08 07:52:45 +00:00
|
|
|
#include <kscreen/configmonitor.h>
|
|
|
|
|
#include <kscreen/getconfigoperation.h>
|
|
|
|
|
#include <kscreen/output.h>
|
|
|
|
|
#include <kscreen/setconfigoperation.h>
|
|
|
|
|
|
2022-09-12 00:17:29 +00:00
|
|
|
// register type for Keyboards.KWinVirtualKeyboard.forceActivate();
|
|
|
|
|
Q_DECLARE_METATYPE(QDBusPendingReply<>)
|
|
|
|
|
|
2024-11-08 07:52:45 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 11:44:41 +00:00
|
|
|
TaskPanel::TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
|
|
|
|
|
: Plasma::Containment(parent, data, args)
|
2024-11-08 07:52:45 +00:00
|
|
|
, m_sensor{new QOrientationSensor(this)}
|
2016-08-24 14:57:15 +00:00
|
|
|
{
|
2024-11-08 07:52:45 +00:00
|
|
|
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();
|
2016-08-24 14:57:15 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-06 06:38:43 +00:00
|
|
|
void TaskPanel::triggerTaskSwitcher() const
|
|
|
|
|
{
|
|
|
|
|
QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kglobalaccel", "/component/kwin", "org.kde.kglobalaccel.Component", "invokeShortcut");
|
|
|
|
|
message.setArguments({QStringLiteral("Mobile Task Switcher")});
|
|
|
|
|
|
|
|
|
|
// this does not block, so it won't necessarily be called before the method returns
|
|
|
|
|
QDBusConnection::sessionBus().send(message);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-08 07:52:45 +00:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-13 22:18:45 +00:00
|
|
|
K_PLUGIN_CLASS(TaskPanel)
|
2016-08-24 14:57:15 +00:00
|
|
|
|
|
|
|
|
#include "taskpanel.moc"
|