File: osd.cpp

package info (click to toggle)
kscreen 4%3A6.5.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,444 kB
  • sloc: cpp: 6,786; xml: 19; makefile: 7; sh: 5
file content (110 lines) | stat: -rw-r--r-- 3,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
    SPDX-FileCopyrightText: 2014 Martin Klapetek <mklapetek@kde.org>
    SPDX-FileCopyrightText: 2016 Sebastian Kügler <sebas@kde.org>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "osd.h"

#include <KScreen/Mode>

#include <LayerShellQt/Window>

#include <KWindowSystem>
#include <KX11Extras>

#include <QCursor>
#include <QGuiApplication>
#include <QQuickItem>
#include <QScreen>
#include <QStandardPaths>
#include <QTimer>

#include <QQuickView>

using namespace KScreen;

Osd::Osd(const KScreen::OutputPtr &output, QObject *parent)
    : QObject(parent)
    , m_output(output)
{
    connect(output.data(), &KScreen::Output::isConnectedChanged, this, &Osd::onOutputAvailabilityChanged);
    connect(output.data(), &KScreen::Output::isEnabledChanged, this, &Osd::onOutputAvailabilityChanged);
    m_engine.setProperty("_kirigamiTheme", QStringLiteral("KirigamiPlasmaStyle"));
}

Osd::~Osd()
{
}

void Osd::showActionSelector()
{
    if (!m_osdActionSelector) {
        m_osdActionSelector = std::make_unique<QQuickView>(&m_engine, nullptr);
        m_osdActionSelector->setInitialProperties({{QLatin1String("actions"), QVariant::fromValue(OsdAction::availableActions())}});
        m_osdActionSelector->loadFromModule("org.kde.kscreen.osd", "OsdSelector");
        m_osdActionSelector->setColor(Qt::transparent);
        m_osdActionSelector->setFlag(Qt::FramelessWindowHint);

        if (m_osdActionSelector->status() != QQuickView::Ready) {
            qWarning() << "Failed to load OSD QML file";
            m_osdActionSelector.reset();
            return;
        }

        auto rootObject = m_osdActionSelector->rootObject();
        connect(rootObject, SIGNAL(clicked(int)), this, SLOT(onOsdActionSelected(int)));
    }

    auto screen = qGuiApp->screenAt(m_output->pos());
    if (!screen) {
        screen = qGuiApp->primaryScreen();
    }

    if (m_osdActionSelector->isVisible()) {
        QMetaObject::invokeMethod(m_osdActionSelector->rootObject(), "moveRight");
    }

    if (KWindowSystem::isPlatformWayland()) {
        auto layerWindow = LayerShellQt::Window::get(m_osdActionSelector.get());
        layerWindow->setScope(QStringLiteral("on-screen-display"));
        layerWindow->setLayer(LayerShellQt::Window::LayerOverlay);
        layerWindow->setAnchors({});
        layerWindow->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityOnDemand);
        m_osdActionSelector->setScreen(screen);
        m_osdActionSelector->setVisible(true);
    } else {
        auto newGeometry = m_osdActionSelector->geometry();
        newGeometry.moveCenter(screen->geometry().center());
        KX11Extras::setState(m_osdActionSelector->winId(), NET::SkipPager | NET::SkipSwitcher | NET::SkipTaskbar);
        KX11Extras::setType(m_osdActionSelector->winId(), NET::OnScreenDisplay);
        m_osdActionSelector->setVisible(true);
        // Workaround wrong geometry by setting geometry after it is visible, not before.
        // Because KWin replace OSD at lower area of the screen.
        m_osdActionSelector->setGeometry(newGeometry);
        m_osdActionSelector->requestActivate();
    }
}

void Osd::onOsdActionSelected(int action)
{
    Q_EMIT osdActionSelected(static_cast<OsdAction::Action>(action));
    hideOsd();
}

void Osd::onOutputAvailabilityChanged()
{
    if (!m_output || !m_output->isConnected() || !m_output->isEnabled() || !m_output->currentMode()) {
        hideOsd();
    }
}

void Osd::hideOsd()
{
    if (m_osdActionSelector) {
        m_osdActionSelector->setVisible(false);
    }
}

#include "moc_osd.cpp"