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 "decorationpainter.h" | ||||
34 | #include "dummydecorationbridge.h" | ||||
35 | #include "dummydecorationsettings.h" | ||||
36 | #include "dummydecoratedclient.h" | ||||
37 | | ||||
38 | namespace KDecoration2 | ||||
39 | { | ||||
40 | | ||||
41 | DummyDecorationBridge::DummyDecorationBridge(const QString &decorationTheme, QObject *parent) | ||||
42 | : DecorationBridge(parent) | ||||
43 | , m_factory() | ||||
44 | , m_decoration() | ||||
45 | , m_client() | ||||
46 | { | ||||
47 | const QString pluginPath = windowDecorationPluginPath(decorationTheme); | ||||
48 | KPluginLoader loader {pluginPath}; | ||||
49 | m_factory = loader.factory(); | ||||
50 | | ||||
51 | QVariantMap args({ {QStringLiteral("bridge"), QVariant::fromValue(this)} }); | ||||
52 | m_decoration = m_factory->create<KDecoration2::Decoration>(m_factory, QVariantList({args})); | ||||
53 | | ||||
54 | auto decorationSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(this); | ||||
55 | m_decoration->setSettings(decorationSettings); | ||||
56 | m_decoration->init(); | ||||
57 | } | ||||
58 | | ||||
59 | std::unique_ptr< KDecoration2::DecorationSettingsPrivate > DummyDecorationBridge::settings(KDecoration2::DecorationSettings *parent) | ||||
60 | { | ||||
61 | return std::unique_ptr<DummyDecorationSettings>(new DummyDecorationSettings(parent)); | ||||
62 | } | ||||
63 | | ||||
64 | void DummyDecorationBridge::update(KDecoration2::Decoration *decoration, const QRect &geometry) | ||||
65 | { | ||||
66 | Q_UNUSED(decoration) | ||||
67 | Q_UNUSED(geometry) | ||||
68 | } | ||||
69 | | ||||
70 | std::unique_ptr< KDecoration2::DecoratedClientPrivate > DummyDecorationBridge::createClient(KDecoration2::DecoratedClient *client, KDecoration2::Decoration *decoration) | ||||
71 | { | ||||
72 | auto ptr = std::unique_ptr<DummyDecoratedClient>(new DummyDecoratedClient(client, decoration)); | ||||
73 | m_client = ptr.get(); | ||||
74 | return ptr; | ||||
75 | } | ||||
76 | | ||||
77 | void DummyDecorationBridge::paintButton(QPainter &painter, const QString &buttonType, const QString &buttonState) | ||||
78 | { | ||||
79 | std::unique_ptr<KDecoration2::DecorationButton> button {m_factory->create<KDecoration2::DecorationButton>( | ||||
80 | QStringLiteral("button"), | ||||
81 | m_decoration, | ||||
82 | QVariantList({ | ||||
83 | QVariant::fromValue(strToButtonType(buttonType)), | ||||
84 | QVariant::fromValue(m_decoration) | ||||
85 | }) | ||||
86 | )}; | ||||
87 | | ||||
88 | if (button == nullptr) { | ||||
89 | return; | ||||
90 | } | ||||
91 | | ||||
92 | button->setGeometry(DecorationPainter::ButtonGeometry); | ||||
93 | | ||||
94 | if (buttonType == QStringLiteral("maximized")) { | ||||
95 | // Different decorations use different ways to know if the window is maximized | ||||
96 | // For example Breeze uses 'checked' property, but Oxygen uses client's 'isMaximized' method | ||||
97 | button->setChecked(true); | ||||
98 | if (m_client) { | ||||
99 | dynamic_cast<DummyDecoratedClient*>(m_client)->setMaximized(true); | ||||
100 | } | ||||
101 | } | ||||
102 | | ||||
103 | if (buttonState == QStringLiteral("active")) { | ||||
104 | passMousePressEventToButton(button.get()); | ||||
105 | } else if (buttonState == QStringLiteral("hover")) { | ||||
106 | passMouseHoverEventToButton(button.get()); | ||||
107 | } | ||||
108 | | ||||
109 | button->paint(&painter, DecorationPainter::ButtonGeometry); | ||||
110 | } | ||||
111 | | ||||
112 | QString DummyDecorationBridge::windowDecorationPluginPath(const QString &decorationTheme) const | ||||
113 | { | ||||
114 | const auto decorationPlugins = KPluginLoader::findPlugins(QStringLiteral("org.kde.kdecoration2")); | ||||
115 | | ||||
116 | QString defaultPluginPath; | ||||
117 | | ||||
118 | for (const auto &pluginMetaData : decorationPlugins) { | ||||
119 | if (pluginMetaData.name() == QStringLiteral("Breeze")) { | ||||
120 | defaultPluginPath = pluginMetaData.fileName(); | ||||
121 | } | ||||
122 | | ||||
123 | if (pluginMetaData.name() == decorationTheme) { | ||||
124 | return pluginMetaData.fileName(); | ||||
125 | } | ||||
126 | } | ||||
127 | return defaultPluginPath; | ||||
128 | } | ||||
129 | | ||||
130 | void DummyDecorationBridge::passMouseHoverEventToButton(KDecoration2::DecorationButton *button) const | ||||
131 | { | ||||
132 | QHoverEvent event { | ||||
133 | QEvent::HoverEnter, | ||||
134 | { | ||||
135 | DecorationPainter::ButtonGeometry.width() / 2.0, | ||||
136 | DecorationPainter::ButtonGeometry.height() / 2.0, | ||||
137 | }, | ||||
138 | { | ||||
139 | (DecorationPainter::ButtonGeometry.width() / 2.0) - 1, | ||||
140 | (DecorationPainter::ButtonGeometry.height() / 2.0) - 1, | ||||
141 | }, | ||||
142 | Qt::NoModifier | ||||
143 | }; | ||||
144 | QCoreApplication::instance()->sendEvent(button, &event); | ||||
145 | } | ||||
146 | | ||||
147 | void DummyDecorationBridge::passMousePressEventToButton(KDecoration2::DecorationButton *button) const | ||||
148 | { | ||||
149 | QMouseEvent event { | ||||
150 | QEvent::MouseButtonPress, | ||||
151 | { | ||||
152 | DecorationPainter::ButtonGeometry.width() / 2.0, | ||||
153 | DecorationPainter::ButtonGeometry.height() / 2.0, | ||||
154 | }, | ||||
155 | Qt::LeftButton, | ||||
156 | Qt::LeftButton, | ||||
157 | Qt::NoModifier | ||||
158 | }; | ||||
159 | QCoreApplication::instance()->sendEvent(button, &event); | ||||
160 | } | ||||
161 | | ||||
162 | KDecoration2::DecorationButtonType DummyDecorationBridge::strToButtonType(const QString &type) const | ||||
163 | { | ||||
164 | if (type == QStringLiteral("minimize")) { | ||||
165 | return KDecoration2::DecorationButtonType::Minimize; | ||||
166 | } else if (type == QStringLiteral("close")) { | ||||
167 | return KDecoration2::DecorationButtonType::Close; | ||||
168 | } else { | ||||
169 | return KDecoration2::DecorationButtonType::Maximize; | ||||
170 | } | ||||
171 | } | ||||
172 | | ||||
173 | } |