MauiKit Controls

linux/shadowhelper/windowshadow.cpp
1/*
2 * Copyright (C) 2021 CutefishOS Team.
3 *
4 * Author: revenmartin <revenmartin@gmail.com>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "windowshadow.h"
21#include "boxshadowrenderer.h"
22#include <QDebug>
23#include <QCoreApplication>
24#include <QDBusInterface>
25
26#include <KWindowSystem>
27#include <KWindowEffects>
28
29enum {
30 ShadowNone,
31 ShadowSmall,
32 ShadowMedium,
33 ShadowLarge,
34 ShadowVeryLarge
35};
36
37const CompositeShadowParams s_shadowParams[] = {
38 // None
39 CompositeShadowParams(),
40 // Small
41 CompositeShadowParams(
42 QPoint(0, 3),
43 ShadowParams(QPoint(0, 0), 16, 0.26),
44 ShadowParams(QPoint(0, -2), 8, 0.16)),
45 // Medium
46 CompositeShadowParams(
47 QPoint(0, 4),
48 ShadowParams(QPoint(0, 0), 20, 0.24),
49 ShadowParams(QPoint(0, -2), 10, 0.14)),
50 // Large
51 CompositeShadowParams(
52 QPoint(0, 5),
53 ShadowParams(QPoint(0, 0), 24, 0.22),
54 ShadowParams(QPoint(0, -3), 12, 0.12)),
55 // Very Large
56 CompositeShadowParams(
57 QPoint(0, 6),
58 ShadowParams(QPoint(0, 0), 36, 0.12),
59 ShadowParams(QPoint(0, -3), 20, 0.05))
60};
61
62WindowShadow::WindowShadow(QObject *parent) noexcept
63 : QObject(parent)
64 , m_view(nullptr)
65 , m_shadow(new KWindowShadow(this))
66{
67
68}
69
70WindowShadow::~WindowShadow()
71{
72 m_shadow->destroy();
73}
74
75CompositeShadowParams WindowShadow::lookupShadowParams(int shadowSizeEnum)
76{
77 switch (shadowSizeEnum) {
78 case ShadowNone:
79 return s_shadowParams[0];
80 case ShadowSmall:
81 return s_shadowParams[1];
82 case ShadowMedium:
83 return s_shadowParams[2];
84 case ShadowLarge:
85 return s_shadowParams[3];
86 case ShadowVeryLarge:
87 return s_shadowParams[4];
88 default:
89 // Fallback to the Large size.
90 return s_shadowParams[3];
91 }
92}
93
94void WindowShadow::classBegin()
95{
96 m_shadowTiles = this->shadowTiles();
97
99 createTile(m_shadowTiles.pixmap(1)),
100 createTile(m_shadowTiles.pixmap(2)),
101 createTile(m_shadowTiles.pixmap(5)),
102 createTile(m_shadowTiles.pixmap(8)),
103 createTile(m_shadowTiles.pixmap(7)),
104 createTile(m_shadowTiles.pixmap(6)),
105 createTile(m_shadowTiles.pixmap(3)),
106 createTile(m_shadowTiles.pixmap(0))
107 };
108
109 m_tile = tiles;
110}
111
112void WindowShadow::componentComplete()
113{
114 configureTiles();
115}
116
117void WindowShadow::setView(QWindow *view)
118{
119 if (view != m_view) {
120 m_view = view;
121 Q_EMIT viewChanged();
122 configureTiles();
123
124 connect(m_view, &QWindow::visibleChanged, this, &WindowShadow::onViewVisibleChanged);
125 }
126}
127
128QWindow *WindowShadow::view() const
129{
130 return m_view;
131}
132
133void WindowShadow::setGeometry(const QRect &rect)
134{
135 if (rect != m_rect) {
136 m_rect = rect;
137 Q_EMIT geometryChanged();
138 configureTiles();
139 }
140}
141
142QRect WindowShadow::geometry() const
143{
144 return m_rect;
145}
146
147void WindowShadow::setRadius(qreal value)
148{
149 if (m_radius != value) {
150 m_radius = value;
151 Q_EMIT radiusChanged();
152
153 this->classBegin();
154
155 configureTiles();
156 }
157}
158
159qreal WindowShadow::strength() const
160{
161 return m_strength;
162}
163
164void WindowShadow::setStrength(qreal strength)
165{
166 if (m_strength != strength) {
167 m_strength = strength;
168
169 this->classBegin();
170 configureTiles();
171
172 Q_EMIT strengthChanged();
173 }
174}
175
176void WindowShadow::onViewVisibleChanged(bool visible)
177{
178 if (visible && m_view) {
179 configureTiles();
180 }
181}
182
183void WindowShadow::configureTiles()
184{
185 //only for cask
186 // if(qEnvironmentVariableIsSet("XDG_CURRENT_DESKTOP") && qEnvironmentVariable("XDG_CURRENT_DESKTOP") == "Cask")
187 // {
188 auto chromeInterface = new QDBusInterface ("org.cask.Server",
189 "/Chrome",
190 "org.cask.Chrome",
192 qDebug() << "TRYING TO HOOK TO THE CASKSERVER" << qApp->desktopFileName() << qApp->desktopFileName();
193
194 if(chromeInterface->isValid())
195 {
196 qDebug() << "TRYING TO HOOK TO THE CASKSERVER IS VAL:ID";
197
198 chromeInterface->call("dropShadow", static_cast<int>(m_radius), qApp->desktopFileName());
199 }else
200 {
201 qDebug() << "COULD NTO HOOK TO THE CASKSERVER";
202 }
203
204 // return;
205 // }
206
207
208 //only for plasma
209 m_shadow->destroy();
210
211 if (!m_view)
212 return;
213
214 m_shadow->setWindow(m_view);
215 m_shadow->setTopTile(m_tile[0]);
216 m_shadow->setTopRightTile(m_tile[1]);
217 m_shadow->setRightTile(m_tile[2]);
218 m_shadow->setBottomRightTile(m_tile[3]);
219 m_shadow->setBottomTile(m_tile[4]);
220 m_shadow->setBottomLeftTile(m_tile[5]);
221 m_shadow->setLeftTile(m_tile[6]);
222 m_shadow->setTopLeftTile(m_tile[7]);
223 m_shadow->setPadding(shadowMargins(m_shadowTiles));
224 m_shadow->create();
225}
226
227KWindowShadowTile::Ptr WindowShadow::createTile(const QPixmap& source)
228{
229 KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create();
230 tile->setImage(source.toImage());
231 return tile;
232}
233
234TileSet WindowShadow::shadowTiles()
235{
236 const qreal frameRadius = m_radius;
237 const CompositeShadowParams params = lookupShadowParams(ShadowVeryLarge);
238
239 if (params.isNone())
240 return TileSet();
241
242 auto withOpacity = [](const QColor &color, qreal opacity) -> QColor {
243 QColor c(color);
244 c.setAlphaF(opacity);
245 return c;
246 };
247
248 const QColor color = Qt::black;
249 const qreal strength = m_strength;
250
251 const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius)
252 .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius));
253
254 const qreal dpr = qApp->devicePixelRatio();
255
256 BoxShadowRenderer shadowRenderer;
257 shadowRenderer.setBorderRadius(frameRadius);
258 shadowRenderer.setBoxSize(boxSize);
259 shadowRenderer.setDevicePixelRatio(dpr);
260
261 shadowRenderer.addShadow(params.shadow1.offset, params.shadow1.radius,
262 withOpacity(color, params.shadow1.opacity * strength));
263 shadowRenderer.addShadow(params.shadow2.offset, params.shadow2.radius,
264 withOpacity(color, params.shadow2.opacity * strength));
265
266 QImage shadowTexture = shadowRenderer.render();
267
268 const QRect outerRect(QPoint(0, 0), shadowTexture.size() / dpr);
269
270 QRect boxRect(QPoint(0, 0), boxSize);
271 boxRect.moveCenter(outerRect.center());
272
273 // Mask out inner rect.
274 QPainter painter(&shadowTexture);
275 painter.setRenderHint(QPainter::Antialiasing);
276
277 int Shadow_Overlap = 3;
278 const QMargins margins = QMargins(
279 boxRect.left() - outerRect.left() - Shadow_Overlap - params.offset.x(),
280 boxRect.top() - outerRect.top() - Shadow_Overlap - params.offset.y(),
281 outerRect.right() - boxRect.right() - Shadow_Overlap + params.offset.x(),
282 outerRect.bottom() - boxRect.bottom() - Shadow_Overlap + params.offset.y());
283
284 painter.setPen(Qt::NoPen);
285 painter.setBrush(Qt::black);
286 painter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
287 painter.drawRoundedRect(
288 outerRect - margins,
289 frameRadius,
290 frameRadius);
291
292 // We're done.
293 painter.end();
294
295 const QPoint innerRectTopLeft = outerRect.center();
296 TileSet tiles = TileSet(
297 QPixmap::fromImage(shadowTexture),
298 innerRectTopLeft.x(),
299 innerRectTopLeft.y(),
300 1, 1);
301
302 return tiles;
303}
304
305QMargins WindowShadow::shadowMargins(TileSet shadowTiles) const
306{
307 const CompositeShadowParams params = lookupShadowParams(ShadowVeryLarge);
308 if (params.isNone())
309 return QMargins();
310
311 const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius)
312 .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius));
313
314 const QSize shadowSize = BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow1.radius, params.shadow1.offset)
315 .expandedTo(BoxShadowRenderer::calculateMinimumShadowTextureSize(boxSize, params.shadow2.radius, params.shadow2.offset));
316
317 const QRect shadowRect(QPoint(0, 0), shadowSize);
318
319 QRect boxRect(QPoint(0, 0), boxSize);
320 boxRect.moveCenter(shadowRect.center());
321
322 int Shadow_Overlap = 4;
323 QMargins margins(
324 boxRect.left() - shadowRect.left() - Shadow_Overlap - params.offset.x(),
325 boxRect.top() - shadowRect.top() - Shadow_Overlap - params.offset.y(),
326 shadowRect.right() - boxRect.right() - Shadow_Overlap + params.offset.x(),
327 shadowRect.bottom() - boxRect.bottom() - Shadow_Overlap + params.offset.y());
328
329 margins *= shadowTiles.pixmap(0).devicePixelRatio();
330
331 return margins;
332}
void setBottomLeftTile(KWindowShadowTile::Ptr tile)
void setWindow(QWindow *window)
void setRightTile(KWindowShadowTile::Ptr tile)
void setTopRightTile(KWindowShadowTile::Ptr tile)
void setBottomTile(KWindowShadowTile::Ptr tile)
void setBottomRightTile(KWindowShadowTile::Ptr tile)
void setTopLeftTile(KWindowShadowTile::Ptr tile)
void setTopTile(KWindowShadowTile::Ptr tile)
void setLeftTile(KWindowShadowTile::Ptr tile)
void setPadding(const QMargins &padding)
tilesets are collections of stretchable pixmaps corresponding to a given widget corners,...
QDBusConnection sessionBus()
QSize size() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
CompositionMode_DestinationOut
qreal devicePixelRatio() const const
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QImage toImage() const const
int x() const const
int y() const const
QSize expandedTo(const QSize &otherSize) const const
void visibleChanged(bool arg)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:56:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.