Changeset View
Changeset View
Standalone View
Standalone View
kstyle/breezeshadowhelper.cpp
Show All 14 Lines | |||||
15 | * along with this program; if not, write to the * | 15 | * along with this program; if not, write to the * | ||
16 | * Free Software Foundation, Inc., * | 16 | * Free Software Foundation, Inc., * | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | 17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * | ||
18 | *************************************************************************/ | 18 | *************************************************************************/ | ||
19 | 19 | | |||
20 | #include "breezeshadowhelper.h" | 20 | #include "breezeshadowhelper.h" | ||
21 | 21 | | |||
22 | #include "breeze.h" | 22 | #include "breeze.h" | ||
23 | #include "breezeboxshadowhelper.h" | ||||
23 | #include "breezehelper.h" | 24 | #include "breezehelper.h" | ||
24 | #include "breezepropertynames.h" | 25 | #include "breezepropertynames.h" | ||
25 | #include "breezestyleconfigdata.h" | 26 | #include "breezestyleconfigdata.h" | ||
26 | 27 | | |||
27 | #include <QDockWidget> | 28 | #include <QDockWidget> | ||
28 | #include <QEvent> | 29 | #include <QEvent> | ||
29 | #include <QApplication> | 30 | #include <QApplication> | ||
30 | #include <QMenu> | 31 | #include <QMenu> | ||
Show All 10 Lines | |||||
41 | #include <KWayland/Client/buffer.h> | 42 | #include <KWayland/Client/buffer.h> | ||
42 | #include <KWayland/Client/connection_thread.h> | 43 | #include <KWayland/Client/connection_thread.h> | ||
43 | #include <KWayland/Client/registry.h> | 44 | #include <KWayland/Client/registry.h> | ||
44 | #include <KWayland/Client/shadow.h> | 45 | #include <KWayland/Client/shadow.h> | ||
45 | #include <KWayland/Client/shm_pool.h> | 46 | #include <KWayland/Client/shm_pool.h> | ||
46 | #include <KWayland/Client/surface.h> | 47 | #include <KWayland/Client/surface.h> | ||
47 | #endif | 48 | #endif | ||
48 | 49 | | |||
50 | namespace | ||||
51 | { | ||||
52 | using Breeze::CompositeShadowParams; | ||||
53 | using Breeze::ShadowParams; | ||||
54 | | ||||
55 | const CompositeShadowParams s_shadowParams[] = { | ||||
56 | // None | ||||
57 | CompositeShadowParams(), | ||||
58 | // Small | ||||
59 | CompositeShadowParams( | ||||
60 | QPoint(0, 6), | ||||
61 | ShadowParams(QPoint(0, 0), 12, 0.2), | ||||
62 | ShadowParams(QPoint(0, -3), 6, 0.16)), | ||||
63 | // Medium | ||||
64 | CompositeShadowParams( | ||||
65 | QPoint(0, 8), | ||||
66 | ShadowParams(QPoint(0, 0), 16, 0.21), | ||||
67 | ShadowParams(QPoint(0, -4), 6, 0.14)), | ||||
68 | // Large | ||||
69 | CompositeShadowParams( | ||||
70 | QPoint(0, 10), | ||||
71 | ShadowParams(QPoint(0, 0), 20, 0.23), | ||||
72 | ShadowParams(QPoint(0, -5), 8, 0.12)), | ||||
73 | // Very Large | ||||
74 | CompositeShadowParams( | ||||
75 | QPoint(0, 12), | ||||
76 | ShadowParams(QPoint(0, 0), 24, 0.26), | ||||
77 | ShadowParams(QPoint(0, -5), 10, 0.12)) | ||||
78 | }; | ||||
79 | } | ||||
80 | | ||||
49 | namespace Breeze | 81 | namespace Breeze | ||
50 | { | 82 | { | ||
51 | 83 | | |||
52 | const char ShadowHelper::netWMShadowAtomName[] ="_KDE_NET_WM_SHADOW"; | 84 | const char ShadowHelper::netWMShadowAtomName[] ="_KDE_NET_WM_SHADOW"; | ||
53 | 85 | | |||
54 | //_____________________________________________________ | 86 | //_____________________________________________________ | ||
55 | int ShadowHelper::shadowSize( int shadowSizeEnum ) | 87 | CompositeShadowParams ShadowHelper::lookupShadowParams(int shadowSizeEnum) | ||
56 | { | 88 | { | ||
57 | 89 | | |||
58 | switch( shadowSizeEnum ) | 90 | switch (shadowSizeEnum) { | ||
59 | { | 91 | case StyleConfigData::ShadowNone: | ||
92 | return s_shadowParams[0]; | ||||
93 | case StyleConfigData::ShadowSmall: | ||||
94 | return s_shadowParams[1]; | ||||
95 | case StyleConfigData::ShadowMedium: | ||||
96 | return s_shadowParams[2]; | ||||
97 | case StyleConfigData::ShadowLarge: | ||||
98 | return s_shadowParams[3]; | ||||
99 | case StyleConfigData::ShadowVeryLarge: | ||||
100 | return s_shadowParams[4]; | ||||
60 | default: | 101 | default: | ||
61 | case Breeze::StyleConfigData::ShadowLarge: return 16; | 102 | // Fallback to the Large size. | ||
62 | case Breeze::StyleConfigData::ShadowNone: return 0; | 103 | return s_shadowParams[3]; | ||
63 | case Breeze::StyleConfigData::ShadowSmall: return 12; | | |||
64 | case Breeze::StyleConfigData::ShadowMedium: return 14; | | |||
65 | case Breeze::StyleConfigData::ShadowVeryLarge: return 24; | | |||
66 | } | 104 | } | ||
67 | 105 | | |||
hpereiradacosta: ok. I know this whole chunc of code is to make it look like css, but this is ugly sorry.
The… | |||||
No, I just prefer this method of initialization of structs. IMHO, it's more readable. I'll see what I can do. PS. I'd say it looks like js. zzag: No, I just prefer this method of initialization of structs. IMHO, it's more readable.
I'll see… | |||||
yeah well, but unless you sign up as the maintainer of this code, what you prefer is not the most relevant, sorry. What I don't like with this construction is that if I change the name of a member of the class, I also have to change all the initializations. Please change. hpereiradacosta: yeah well, but unless you sign up as the maintainer of this code, what you prefer is not the… | |||||
68 | } | 106 | } | ||
69 | 107 | | |||
70 | | ||||
71 | //_____________________________________________________ | 108 | //_____________________________________________________ | ||
72 | ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): | 109 | ShadowHelper::ShadowHelper( QObject* parent, Helper& helper ): | ||
73 | QObject( parent ), | 110 | QObject( parent ), | ||
74 | _helper( helper ) | 111 | _helper( helper ) | ||
75 | #if BREEZE_HAVE_X11 | 112 | #if BREEZE_HAVE_X11 | ||
76 | ,_gc( 0 ), | 113 | ,_gc( 0 ), | ||
77 | _atom( 0 ) | 114 | _atom( 0 ) | ||
78 | #endif | 115 | #endif | ||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Line(s) | 227 | { | |||
229 | 266 | | |||
230 | return false; | 267 | return false; | ||
231 | 268 | | |||
232 | } | 269 | } | ||
233 | 270 | | |||
234 | //_______________________________________________________ | 271 | //_______________________________________________________ | ||
235 | TileSet ShadowHelper::shadowTiles() | 272 | TileSet ShadowHelper::shadowTiles() | ||
236 | { | 273 | { | ||
237 | // metrics | 274 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | ||
238 | const int shadowSize = this->shadowSize( StyleConfigData::shadowSize() ); | | |||
239 | if( !shadowSize ) return TileSet(); | | |||
240 | else if( !_shadowTiles.isValid() ) | | |||
241 | { | | |||
242 | | ||||
243 | const QPalette palette( QApplication::palette() ); | | |||
244 | const QColor shadowColor( StyleConfigData::shadowColor() ); | | |||
245 | const int shadowOffset = qMax( shadowSize/2, Metrics::Shadow_Overlap*2 ); | | |||
246 | const int shadowStrength = StyleConfigData::shadowStrength(); | | |||
247 | | ||||
248 | // pixmap | | |||
249 | QPixmap pixmap = _helper.highDpiPixmap( shadowSize*2 ); | | |||
250 | pixmap.fill( Qt::transparent ); | | |||
251 | | ||||
252 | // create gradient | | |||
253 | // gaussian delta function | | |||
254 | auto alpha = [](qreal x) { return std::exp( -x*x/0.15 ); }; | | |||
255 | 275 | | |||
256 | // color calculation delta function | 276 | if (params.isNone()) { | ||
257 | auto gradientStopColor = [](QColor color, int alpha) | 277 | return TileSet(); | ||
258 | { | 278 | } else if (_shadowTiles.isValid()) { | ||
259 | color.setAlpha(alpha); | 279 | return _shadowTiles; | ||
260 | return color; | | |||
261 | }; | | |||
262 | | ||||
263 | QRadialGradient radialGradient( shadowSize, shadowSize, shadowSize); | | |||
264 | for( int i = 0; i < 10; ++i ) | | |||
265 | { | | |||
266 | const qreal x( qreal( i )/9 ); | | |||
267 | radialGradient.setColorAt(x, gradientStopColor(shadowColor, alpha(x)*shadowStrength)); | | |||
268 | } | 280 | } | ||
269 | 281 | | |||
270 | radialGradient.setColorAt(1, gradientStopColor( shadowColor, 0 ) ); | 282 | auto withOpacity = [](const QColor &color, qreal opacity) -> QColor { | ||
271 | 283 | QColor c(color); | |||
272 | // fill | 284 | c.setAlphaF(opacity); | ||
273 | QPainter p(&pixmap); | 285 | return c; | ||
274 | p.setRenderHint( QPainter::Antialiasing, true ); | 286 | }; | ||
275 | p.fillRect( pixmap.rect(), radialGradient); | | |||
276 | | ||||
277 | p.setPen( Qt::NoPen ); | | |||
278 | p.setBrush( Qt::black ); | | |||
279 | | ||||
280 | QRectF innerRect( | | |||
281 | shadowSize - Metrics::Shadow_Overlap, shadowSize - shadowOffset - Metrics::Shadow_Overlap, | | |||
282 | 2*Metrics::Shadow_Overlap,shadowOffset + 2*Metrics::Shadow_Overlap ); | | |||
283 | | ||||
284 | p.setCompositionMode(QPainter::CompositionMode_DestinationOut ); | | |||
285 | 287 | | |||
286 | const qreal radius( _helper.frameRadius() ); | 288 | const int shadowSize = qMax(params.shadow1.radius, params.shadow2.radius); | ||
287 | p.drawRoundedRect( innerRect, radius, radius ); | 289 | const QColor color = StyleConfigData::shadowColor(); | ||
288 | p.end(); | 290 | const qreal strength = static_cast<qreal>(StyleConfigData::shadowStrength()) / 255.0; | ||
289 | 291 | | |||
290 | // create tiles from pixmap | 292 | const QRect box( | ||
291 | _shadowTiles = TileSet( pixmap, | | |||
292 | shadowSize, | 293 | shadowSize, | ||
293 | shadowSize, | 294 | shadowSize, | ||
294 | 1, 1 ); | 295 | 2 * shadowSize + 1, | ||
296 | 2 * shadowSize + 1); | ||||
297 | const QRect outerRect = box.adjusted(-shadowSize, -shadowSize, shadowSize, shadowSize); | ||||
298 | | ||||
299 | QPixmap shadow = _helper.highDpiPixmap(outerRect.width(), outerRect.height()); | ||||
300 | shadow.fill(Qt::transparent); | ||||
301 | | ||||
302 | QPainter painter(&shadow); | ||||
303 | painter.setRenderHint(QPainter::Antialiasing); | ||||
304 | | ||||
305 | // Draw the "shape" shadow. | ||||
306 | BoxShadowHelper::boxShadow( | ||||
307 | &painter, | ||||
308 | box, | ||||
309 | params.shadow1.offset, | ||||
310 | params.shadow1.radius, | ||||
311 | withOpacity(color, params.shadow1.opacity * strength)); | ||||
312 | | ||||
313 | // Draw the "contrast" shadow. | ||||
314 | BoxShadowHelper::boxShadow( | ||||
315 | &painter, | ||||
316 | box, | ||||
317 | params.shadow2.offset, | ||||
318 | params.shadow2.radius, | ||||
319 | withOpacity(color, params.shadow2.opacity * strength)); | ||||
320 | | ||||
321 | // Mask out inner rect. | ||||
322 | const QMargins margins = QMargins( | ||||
323 | shadowSize - Metrics::Shadow_Overlap - params.offset.x(), | ||||
324 | shadowSize - Metrics::Shadow_Overlap - params.offset.y(), | ||||
325 | shadowSize - Metrics::Shadow_Overlap + params.offset.x(), | ||||
326 | shadowSize - Metrics::Shadow_Overlap + params.offset.y()); | ||||
327 | const qreal frameRadius = _helper.frameRadius(); | ||||
328 | | ||||
329 | painter.setPen(Qt::NoPen); | ||||
330 | painter.setBrush(Qt::black); | ||||
331 | painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); | ||||
332 | painter.drawRoundedRect( | ||||
333 | #if BREEZE_USE_KDE4 | ||||
334 | outerRect.adjusted(margins.left(), margins.top(), -margins.right(), -margins.bottom()), | ||||
335 | #else | ||||
336 | outerRect - margins, | ||||
337 | #endif | ||||
338 | frameRadius, | ||||
339 | frameRadius); | ||||
295 | 340 | | |||
296 | } | 341 | // We're done. | ||
342 | painter.end(); | ||||
297 | 343 | | |||
298 | return _shadowTiles; | 344 | const QPoint innerRectTopLeft = outerRect.center(); | ||
345 | _shadowTiles = TileSet( | ||||
346 | shadow, | ||||
347 | innerRectTopLeft.x(), | ||||
348 | innerRectTopLeft.y(), | ||||
349 | 1, 1); | ||||
299 | 350 | | |||
351 | return _shadowTiles; | ||||
300 | } | 352 | } | ||
301 | 353 | | |||
302 | 354 | | |||
303 | //_______________________________________________________ | 355 | //_______________________________________________________ | ||
304 | void ShadowHelper::objectDeleted( QObject* object ) | 356 | void ShadowHelper::objectDeleted( QObject* object ) | ||
305 | { _widgets.remove( static_cast<QWidget*>( object ) ); } | 357 | { _widgets.remove( static_cast<QWidget*>( object ) ); } | ||
306 | 358 | | |||
307 | //_______________________________________________________ | 359 | //_______________________________________________________ | ||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Line(s) | 535 | { | |||
516 | #endif | 568 | #endif | ||
517 | 569 | | |||
518 | return false; | 570 | return false; | ||
519 | } | 571 | } | ||
520 | 572 | | |||
521 | //_______________________________________________________ | 573 | //_______________________________________________________ | ||
522 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | 574 | QMargins ShadowHelper::shadowMargins( QWidget* widget ) const | ||
523 | { | 575 | { | ||
524 | // get devicePixelRatio | 576 | const CompositeShadowParams params = lookupShadowParams(StyleConfigData::shadowSize()); | ||
525 | // for testing purposes only | 577 | if (params.isNone()) { | ||
526 | const qreal devicePixelRatio( _helper.devicePixelRatio( _shadowTiles.pixmap( 0 ) ) ); | 578 | return QMargins(); | ||
527 | 579 | } | |||
528 | // metrics | | |||
529 | const int shadowSize = this->shadowSize( StyleConfigData::shadowSize() ); | | |||
530 | if( !shadowSize ) return QMargins(); | | |||
531 | const int shadowOffset = qMax( shadowSize/2, Metrics::Shadow_Overlap*2 ); | | |||
532 | | ||||
533 | // define shadows padding | | |||
534 | int size( shadowSize - Metrics::Shadow_Overlap ); | | |||
535 | int topSize = ( size - shadowOffset ) * devicePixelRatio; | | |||
536 | int bottomSize = size * devicePixelRatio; | | |||
537 | const int leftSize( size * devicePixelRatio ); | | |||
538 | const int rightSize( size * devicePixelRatio ); | | |||
539 | 580 | | |||
540 | if( widget->inherits( "QBalloonTip" ) ) | 581 | const int shadowSize = qMax(params.shadow1.radius, params.shadow2.radius); | ||
541 | { | 582 | QMargins margins( | ||
583 | shadowSize - Metrics::Shadow_Overlap - params.offset.x(), | ||||
584 | shadowSize - Metrics::Shadow_Overlap - params.offset.y(), | ||||
585 | shadowSize - Metrics::Shadow_Overlap + params.offset.x(), | ||||
586 | shadowSize - Metrics::Shadow_Overlap + params.offset.y()); | ||||
542 | 587 | | |||
543 | // balloon tip needs special margins to deal with the arrow | 588 | if (widget->inherits("QBalloonTip")) { | ||
589 | // Balloon tip needs special margins to deal with the arrow. | ||||
544 | int top = 0; | 590 | int top = 0; | ||
545 | int bottom = 0; | 591 | int bottom = 0; | ||
546 | widget->getContentsMargins( nullptr, &top, nullptr, &bottom ); | 592 | widget->getContentsMargins(nullptr, &top, nullptr, &bottom); | ||
547 | 593 | | |||
548 | // also need to decrement default size further due to extra hard coded round corner | 594 | // Need to decrement default size further due to extra hard coded round corner. | ||
549 | size -= 2 * devicePixelRatio; | 595 | #if BREEZE_USE_KDE4 | ||
550 | 596 | margins.setLeft(margins.left() - 1); | |||
551 | // it seems arrow can be either to the top or the bottom. Adjust margins accordingly | 597 | margins.setTop(margins.top() - 1); | ||
552 | if( top > bottom ) topSize -= (top - bottom); | 598 | margins.setRight(margins.right() - 1); | ||
553 | else bottomSize -= (bottom - top ); | 599 | margins.setBottom(margins.bottom() - 1); | ||
600 | #else | ||||
601 | margins -= 1; | ||||
602 | #endif | ||||
554 | 603 | | |||
604 | // Arrow can be either to the top or the bottom. Adjust margins accordingly. | ||||
605 | const int diff = qAbs(top - bottom); | ||||
606 | if (top > bottom) { | ||||
607 | margins.setTop(margins.top() - diff); | ||||
608 | } else { | ||||
609 | margins.setBottom(margins.bottom() - diff); | ||||
555 | } | 610 | } | ||
611 | } | ||||
612 | | ||||
613 | #if BREEZE_USE_KDE4 | ||||
614 | const qreal dpr = _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | ||||
615 | margins.setLeft(margins.left() * dpr); | ||||
616 | margins.setTop(margins.top() * dpr); | ||||
617 | margins.setRight(margins.right() * dpr); | ||||
618 | margins.setBottom(margins.bottom() * dpr); | ||||
619 | #else | ||||
620 | margins *= _helper.devicePixelRatio(_shadowTiles.pixmap(0)); | ||||
621 | #endif | ||||
556 | 622 | | |||
557 | return QMargins( leftSize, topSize, rightSize, bottomSize ); | 623 | return margins; | ||
558 | } | 624 | } | ||
559 | 625 | | |||
560 | //_______________________________________________________ | 626 | //_______________________________________________________ | ||
561 | void ShadowHelper::uninstallShadows( QWidget* widget ) const | 627 | void ShadowHelper::uninstallShadows( QWidget* widget ) const | ||
562 | { | 628 | { | ||
563 | if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; | 629 | if( !( widget && widget->testAttribute(Qt::WA_WState_Created) ) ) return; | ||
564 | if( Helper::isX11() ) uninstallX11Shadows( widget ); | 630 | if( Helper::isX11() ) uninstallX11Shadows( widget ); | ||
565 | if( Helper::isWayland() ) uninstallWaylandShadows( widget ); | 631 | if( Helper::isWayland() ) uninstallWaylandShadows( widget ); | ||
Show All 32 Lines |
ok. I know this whole chunc of code is to make it look like css, but this is ugly sorry.
The fact that you need to repeat all the member names for each new set of parameters is not maintainable in the long run. Please add a proper constructor to the structure (with three params), and use this to initialize the various sets of parameters.
Idem in the kdecoration.