Changeset View
Changeset View
Standalone View
Standalone View
kded/kwin_bridge/dummydecorationbridge.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright 2020 Mikhail Zolotukhin <zomial@protonmail.com> | ||||
3 | * | ||||
4 | * This program is free software; you can redistribute it and/or | ||||
5 | * modify it under the terms of the GNU General Public License as | ||||
6 | * published by the Free Software Foundation; either version 2 of | ||||
7 | * the License or (at your option) version 3 or any later version | ||||
8 | * accepted by the membership of KDE e.V. (or its successor approved | ||||
9 | * by the membership of KDE e.V.), which shall act as a proxy | ||||
10 | * defined in Section 14 of version 3 of the license. | ||||
11 | * | ||||
12 | * This program is distributed in the hope that it will be useful, | ||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | * GNU General Public License for more details. | ||||
16 | * | ||||
17 | * You should have received a copy of the GNU General Public License | ||||
18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | */ | ||||
20 | | ||||
21 | #include <QCoreApplication> | ||||
22 | #include <QMouseEvent> | ||||
23 | | ||||
24 | #include <KDecoration2/Decoration> | ||||
25 | #include <KDecoration2/DecorationSettings> | ||||
26 | #include <KDecoration2/DecoratedClient> | ||||
27 | #include <KDecoration2/Private/DecoratedClientPrivate> | ||||
28 | #include <KDecoration2/Private/DecorationSettingsPrivate> | ||||
29 | #include <KPluginFactory> | ||||
30 | #include <KPluginLoader> | ||||
31 | #include <KPluginMetaData> | ||||
32 | | ||||
33 | #include "dummydecorationbridge.h" | ||||
34 | #include "dummydecorationsettings.h" | ||||
35 | #include "dummydecoratedclient.h" | ||||
36 | | ||||
37 | namespace KDecoration2 | ||||
38 | { | ||||
39 | | ||||
40 | DummyDecorationBridge::DummyDecorationBridge(const QString &decorationTheme, QObject *parent) | ||||
41 | : DecorationBridge(parent) | ||||
42 | , m_factory() | ||||
43 | , m_decoration() | ||||
44 | , m_client() | ||||
45 | { | ||||
46 | const QString pluginPath = windowDecorationPluginPath(decorationTheme); | ||||
47 | KPluginLoader loader {pluginPath}; | ||||
48 | m_factory = loader.factory(); | ||||
49 | | ||||
50 | QVariantMap args({ {QStringLiteral("bridge"), QVariant::fromValue(this)} }); | ||||
51 | m_decoration = m_factory->create<KDecoration2::Decoration>(m_factory, QVariantList({args})); | ||||
52 | | ||||
53 | auto decorationSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(this); | ||||
54 | m_decoration->setSettings(decorationSettings); | ||||
55 | m_decoration->init(); | ||||
56 | } | ||||
57 | | ||||
58 | std::unique_ptr< KDecoration2::DecorationSettingsPrivate > DummyDecorationBridge::settings(KDecoration2::DecorationSettings *parent) | ||||
59 | { | ||||
60 | return std::unique_ptr<DummyDecorationSettings>(new DummyDecorationSettings(parent)); | ||||
61 | } | ||||
62 | | ||||
63 | void DummyDecorationBridge::update(KDecoration2::Decoration *decoration, const QRect &geometry) | ||||
64 | { | ||||
65 | Q_UNUSED(decoration) | ||||
66 | Q_UNUSED(geometry) | ||||
67 | } | ||||
68 | | ||||
69 | std::unique_ptr< KDecoration2::DecoratedClientPrivate > DummyDecorationBridge::createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) | ||||
70 | { | ||||
71 | auto ptr = std::unique_ptr<DummyDecoratedClient>(new DummyDecoratedClient(client, decoration)); | ||||
72 | m_client = ptr.get(); | ||||
73 | return ptr; | ||||
74 | } | ||||
75 | | ||||
76 | void DummyDecorationBridge::paintButton(QPainter &painter, const QString &buttonType, const QString &buttonState) | ||||
77 | { | ||||
78 | std::unique_ptr<KDecoration2::DecorationButton> button {m_factory->create<KDecoration2::DecorationButton>( | ||||
79 | QStringLiteral("button"), | ||||
80 | m_decoration, | ||||
81 | QVariantList({ | ||||
82 | QVariant::fromValue(strToButtonType(buttonType)), | ||||
83 | QVariant::fromValue(m_decoration) | ||||
84 | }) | ||||
85 | )}; | ||||
86 | | ||||
87 | if (button == nullptr) { | ||||
88 | return; | ||||
89 | } | ||||
90 | | ||||
91 | if (buttonType == QStringLiteral("maximized")) { | ||||
92 | // Different decorations use different ways to know if the windows is maximized | ||||
93 | // For example Breeze uses 'checked' property, but Oxygen uses client's 'isMaximized' method | ||||
94 | button->setChecked(true); | ||||
95 | if (m_client) { | ||||
96 | dynamic_cast<DummyDecoratedClient*>(m_client)->setMaximized(true); | ||||
97 | } | ||||
98 | } | ||||
99 | | ||||
100 | if (buttonState == QStringLiteral("active")) { | ||||
101 | passMousePressEventToButton(button.get()); | ||||
102 | } else if (buttonState == QStringLiteral("hover")) { | ||||
103 | passMouseHoverEventToButton(button.get()); | ||||
104 | } | ||||
105 | | ||||
106 | button->paint(&painter, {0, 0, 20, 20}); | ||||
107 | } | ||||
108 | | ||||
109 | QString DummyDecorationBridge::windowDecorationPluginPath(const QString &decorationTheme) const | ||||
110 | { | ||||
111 | const auto decorationPlugins = KPluginLoader::findPlugins(QStringLiteral("org.kde.kdecoration2")); | ||||
112 | | ||||
113 | QString defaultPluginPath; | ||||
114 | | ||||
115 | for (const auto &pluginMetaData : decorationPlugins) { | ||||
116 | if (pluginMetaData.name() == QStringLiteral("Breeze")) { | ||||
117 | defaultPluginPath = pluginMetaData.fileName(); | ||||
118 | } | ||||
119 | | ||||
120 | if (pluginMetaData.name() == decorationTheme) { | ||||
121 | return pluginMetaData.fileName(); | ||||
122 | } | ||||
123 | } | ||||
124 | return defaultPluginPath; | ||||
125 | } | ||||
126 | | ||||
127 | void DummyDecorationBridge::passMouseHoverEventToButton(KDecoration2::DecorationButton *button) const | ||||
128 | { | ||||
129 | QHoverEvent event { | ||||
130 | QEvent::HoverEnter, {5, 5}, {4, 4}, Qt::NoModifier | ||||
131 | }; | ||||
132 | QCoreApplication::instance()->sendEvent(button, &event); | ||||
133 | } | ||||
134 | | ||||
135 | void DummyDecorationBridge::passMousePressEventToButton(KDecoration2::DecorationButton *button) const | ||||
136 | { | ||||
137 | QMouseEvent event { | ||||
138 | QEvent::MouseButtonPress, | ||||
139 | {5, 5}, | ||||
140 | Qt::LeftButton, | ||||
141 | Qt::LeftButton, | ||||
142 | Qt::NoModifier | ||||
143 | }; | ||||
144 | QCoreApplication::instance()->sendEvent(button, &event); | ||||
145 | } | ||||
146 | | ||||
147 | KDecoration2::DecorationButtonType DummyDecorationBridge::strToButtonType(const QString &type) const | ||||
148 | { | ||||
149 | if (type == QStringLiteral("minimize")) { | ||||
150 | return KDecoration2::DecorationButtonType::Minimize; | ||||
151 | } else if (type == QStringLiteral("close")) { | ||||
152 | return KDecoration2::DecorationButtonType::Close; | ||||
153 | } else { | ||||
154 | return KDecoration2::DecorationButtonType::Maximize; | ||||
155 | } | ||||
156 | } | ||||
157 | | ||||
158 | } |